/* -----------------------------------------------------------------------------

  GEDApp v1.0 - GoldED AppIcon handler, ©1995 Dietmar Eilert

  DICE:

  dcc app.c appIconA.a -// -proto -mRR -mi -pr -2.0 -o ram:GEDApp

 CONTENTS

  C source code of GEDApp.

 PURPOSE

   GEDApp is a simple AppIcon handler for the editor  GoldED.  It  will  put  an
   Application  icon on the workbench screen. Icons of text files may be dragged
   and dropped over this icon to make  GoldED  load  them  into  a  new  window.
   Doubleclick at the AppIcon to make it disappear.

 INSTALLATION

   There is nothing to install - simply doubleclick GEDApp's icon to run it.  Or
   copy  this  utility to your WBStartup drawer if you want to have it available
   every time you boot your Amiga. GEDApp uses the  default  AppIcon  of  GoldED
   itself, so GoldED should already be installed.

 HOW TO SET THE DEFAULT ICON POSITION ...

   Open the 'golded:config' drawer. Move the 'AppIcon'  icon  from  within  that
   directory to your preferred position, than snapshot it (workbench/icon menu).
   Finally move the icon back to its drawer. GEDApp will read the  new  position
   the next time it is evoked.

  ------------------------------------------------------------------------------
*/

/// "includes"

#include <amiga20/exec/exec.h>
#include <string.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <amiga20/intuition/intuition.h>
#include <amiga20/dos/dos.h>
#include <amiga20/dos/dosextens.h>
#include <amiga20/dos/rdargs.h>
#include <amiga20/dos/dostags.h>
#include <amiga20/workbench/startup.h>
#include <amiga20/workbench/workbench.h>
#include <amiga20/rexx/errors.h>
#include <amiga20/rexx/rxslib.h>

#include <amiga20/clib/alib_protos.h>
#include <amiga20/clib/dos_protos.h>
#include <amiga20/clib/exec_protos.h>
#include <amiga20/clib/icon_protos.h>
#include <amiga20/clib/intuition_protos.h>
#include <amiga20/clib/utility_protos.h>
#include <amiga20/clib/rexxsyslib_protos.h>
#include <amiga20/clib/wb_protos.h>

#ifdef PRAGMAS

#include "Pragmas/exec.h"
#include "Pragmas/disk.h"
#include "Pragmas/diskfont.h"
#include "Pragmas/dynamic.h"
#include "Pragmas/gadtools.h"
#include "Pragmas/keymap.h"
#include "Pragmas/graphics.h"
#include "Pragmas/icon.h"
#include "Pragmas/input.h"
#include "Pragmas/intuition.h"
#include "Pragmas/layers.h"
#include "Pragmas/locale.h"
#include "Pragmas/misc.h"
#include "Pragmas/timer.h"
#include "Pragmas/wb.h"
#include "Pragmas/xpkmaster.h"
#include "Pragmas/amigaguide.h"
#include "Pragmas/reqtools.h"

#endif

#define Prototype    extern
#define MAX_LEN      150

///
/// "prototypes"

Prototype void   main(ULONG, char **);
Prototype int    wbmain(struct WBStartup *);
Prototype void   MainLoop(void);
Prototype char  *MakeFileName(char *, char *);
Prototype char  *CompletePath(char *);
Prototype char  *StartGED(void);
Prototype struct RexxMsg *SendRexxCommand(char *, char *, struct MsgPort *);
Prototype void   FreeRexxCommand (struct RexxMsg *);
Prototype ULONG  WaitForAnswer(struct MsgPort *);
Prototype char  *LookForGED(void);
Prototype void   ReadWBCmd(ULONG, struct WBArg *);

extern struct Library *IconBase;
extern struct Library *DOSBase;
extern struct Library *SysBase;
extern struct Library *IntuitionBase;
extern struct Library *WorkbenchBase;

///
/// "entry points"

void
main(argc, argv)

ULONG argc;
char *argv[];
{
    MainLoop();
}

int
wbmain(struct WBStartup *wbs)
{
    MainLoop();
}


///
/// "main loop"

/* --------------------------------- MainLoop ----------------------------------

 Open AppIcon, handle incoming messages

*/

void
MainLoop()
{
    const char *version = "$VER: GEDApp 1.0 (26.1.95)";

    struct DiskObject *appDiskObject;

    if (!(appDiskObject = GetDiskObject("golded:config/AppIcon")))
        appDiskObject = GetDefDiskObject(WBTOOL);

    if (appDiskObject) {

        struct MsgPort     *msgPort;
        struct AppMessage  *amsg;
        struct AppIcon     *appIcon;

        if (msgPort = CreateMsgPort()) {

            if (appIcon = AddAppIconA(0, NULL, "GED", msgPort, NULL, appDiskObject, TAG_END)) {

                BOOL terminated = FALSE;

                while (!terminated) {

                    WaitPort(msgPort);

                    while (amsg = (struct AppMessage *)GetMsg(msgPort)) {

                        if (amsg->am_NumArgs)
                            ReadWBCmd(amsg->am_NumArgs, amsg->am_ArgList);
                        else
                            terminated = TRUE;

                        ReplyMsg((struct Message *)amsg);
                    }
                }
            }
            else
                puts("Couldn't allocate AppIcon. Workbench closed ?!");

            RemoveAppIcon(appIcon);

            DeleteMsgPort(msgPort);
        }
        else
            puts("Couldn't create message port ?!");

        FreeDiskObject(appDiskObject);
    }
    else
        puts("Impossible d'allouer DiskObject ?!");

    exit(0);
}


///
/// "misc"

/* ------------------------------- MakeFileName --------------------------------

 Build fully qualified path from file/path names; return pointer to static copy.

*/

char *
MakeFileName(path, file)

char *path, *file;
{
    static char buffer[MAX_LEN + 1];

    strcpy(buffer, "\42");

    strcat(buffer, path);

    CompletePath(buffer);

    strcat(buffer, file);

    strcat(buffer, "\42");

    return(buffer);
}

/* ------------------------------ CompletePath -----------------------------------

 Add '/' to path if missing so far

*/

char *
CompletePath(char *path)
{
    UWORD len;

    if (len = strlen(path))
        if ((path[len - 1] != ':') && (path[len - 1] != '/'))
            strcat(path, "/");

    return(path);
}

/* ---------------------------------- ReadWBCmd --------------------------------

 Parse AppIcon message

*/

void
ReadWBCmd(numArgs, argList)

ULONG  numArgs;
struct WBArg  *argList;
{
    char *host;
    BOOL loadGED = !(host = LookForGED());

    if (loadGED)
        host = StartGED();

    if (host) {

        struct MsgPort *replyPort;

        if (replyPort = CreateMsgPort()) {

            if (SendRexxCommand(host, "LOCK CURRENT", replyPort)) {

                if (WaitForAnswer(replyPort) == RC_OK) {

                    UWORD count;
                    char  path[MAX_LEN + 1], *command;

                    for (count = 0; numArgs--; count++) {

                        NameFromLock(argList[count].wa_Lock, path, MAX_LEN);

                        command = MakeFileName(path, argList[count].wa_Name);

                        strins(command, "OPEN SMART QUIET ");

                        if (SendRexxCommand(host, command, replyPort))

                            WaitForAnswer(replyPort);
                    }
                }

                if (SendRexxCommand(host, "UNLOCK", replyPort))

                    WaitForAnswer(replyPort);
            }

            DeleteMsgPort(replyPort);
        }
    }
}


/* ----------------------------------- LookForGED ----------------------------

 Look for running GoldED task

*/

char *
LookForGED()
{
    static char host[] = "GOLDED.1";
    UWORD  try;

    for (try = '1'; try <= '9'; try++) {

        host[7] = try;

        if (FindPort(host))
            return(host);
    } 

    return(NULL);
}

/* ------------------------------------- StartGED -----------------------------

 Launch a new GoldED task. Return pointer to host name (or NULL).

*/

char *
StartGED()
{
    static char *host = "GOLDED.1";

    if (!SystemTags("GoldED:GoldED", SYS_Asynch, TRUE, SYS_Input, NULL, SYS_Output, NULL, TAG_DONE))

        UWORD try;

        for (try = 50; try; try--, Delay(10))
            if (FindPort(host))
                return(host);

    return(FALSE);
}

///
/// "ARexx"

/* -------------------------------------- WaitForAnswer -----------------------

  Wait for answer on previously sent message. Free message afterwards. Primary
  return code is returned.

*/

ULONG
WaitForAnswer(port)

struct MsgPort *port;
{
    struct RexxMsg *rexxMsg;
    ULONG  result;

    do {
        
        WaitPort(port);

        if (rexxMsg = (struct RexxMsg *)GetMsg(port))
            result = rexxMsg->rm_Result1;

    } while (!rexxMsg);

    FreeRexxCommand(rexxMsg);

    return(result);
}

/* ------------------------------------- FreeRexxCommand ----------------------

 Free ARexx message

*/

void
FreeRexxCommand(rexxmessage)

struct RexxMsg *rexxmessage;
{
    if (rexxmessage->rm_Result1 == RC_OK) 
        if (rexxmessage->rm_Result2)
            DeleteArgstring((char *)rexxmessage->rm_Result2);

    DeleteArgstring((char *)ARG0(rexxmessage));

    DeleteRexxMsg(rexxmessage);
}

/* ---------------------------------- SendRexxCommand -------------------------

 Send ARexx message

*/

struct RexxMsg *
SendRexxCommand(port, cmd, replyPort)

char   *cmd,   *port;
struct MsgPort *replyPort;
{
    struct MsgPort *rexxport;
    struct RexxMsg *rexx_command_message = NULL;

    Forbid();

    if (rexxport = FindPort(port)) {

        if (rexx_command_message = CreateRexxMsg(replyPort, NULL, NULL)) {

            if (rexx_command_message->rm_Args[0] = CreateArgstring(cmd, strlen(cmd))) {

                rexx_command_message->rm_Action = RXCOMM | RXFF_RESULT;

                PutMsg(rexxport, &rexx_command_message->rm_Node);
            }
        }
    }

    Permit();

    return(rexx_command_message);
}

///
