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

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

  DICE:

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

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

/// "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.

 Générer le chemin d'accès complet à partir des icônes; retourne un pointeur
 pour une copie statique.

*/

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);
}

///
