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

  Read the project list (example).

  DICE:

  dcc main.c -// -3.0 -o project


  This C source code demonstrates reading the project list using ARexx (so that
  you can develop external project management tools compatible with GoldED).

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

/// "includes & prototypes"

#include <exec/exec.h>
#include <rexx/errors.h>
#include <rexx/rxslib.h>
#include <clib/exec_protos.h>
#include <clib/rexxsyslib_protos.h>

#define Prototype extern

///
/// "prototypes"

Prototype void            FreeRexxCommand(struct RexxMsg *);
Prototype void            ListTree       (struct List *);
Prototype void            main           (ULONG, char **);
Prototype struct RexxMsg *SendRexxCommand(UBYTE *, UBYTE *, struct MsgPort *);
Prototype ULONG           WaitForAnswer  (struct MsgPort *, UBYTE *);

///
/// "defines"

// editor's internal configuration format is based on "objects"

struct Object {

    struct Node Node;                                // it's a linked list

    UWORD            ID;                             // object ID
    UWORD            Type;                           // class ID
    struct Class    *Class;                          // class base

    union {                                          // object's data section

        ULONG        Number;                         // number
        UBYTE       *String;                         // string
        struct List *List;                           // object list
        APTR         Data;                           // memory block

    } Value;
};

// object types (bit 0-2)

#define OBJECT_TYPE_NUMBER 1
#define OBJECT_TYPE_STRING 2
#define OBJECT_TYPE_LIST   3
#define OBJECT_TYPE_DATA   4

#define OBJECTTYPE(a) (((struct Object *)(a))->Type & 0x7)

///
/// "globals"

UBYTE Version[] = "$VER: PRJ 1.3 (" __COMMODORE_DATE__ ")";

///
/// "main"

void
main(argc, argv)

ULONG argc;
char *argv[];
{
    struct MsgPort *replyPort;

    UBYTE *host = "GOLDED.1";

    if (replyPort = CreateMsgPort()) {

        if (SendRexxCommand(host, "LOCK CURRENT RELEASE=4", replyPort)) {

            UBYTE result[80];

            if (WaitForAnswer(replyPort, result) == RC_OK) {

                if (SendRexxCommand(host, "QUERY PRJLIST", replyPort)) {

                    if (WaitForAnswer(replyPort, result) == RC_OK) {

                        struct List   *list;

                        if (list = (struct List *)atol(result)) {

                            if (list->lh_Head->ln_Succ) {

                                ListTree(list);
                            }
                            else
                                puts("project list is empty");
                        }
                    }
                }

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

                    WaitForAnswer(replyPort, result);
            }
        }

        DeleteMsgPort(replyPort);
    }

    exit(0);
}


/* --------------------------------- ListTree ----------------------------------

 Print project configuration (this is a recursive function)

*/

void
ListTree(list)

struct List *list;
{
    struct Object *object;

    for (object = (struct Object *)list->lh_Head; object->Node.ln_Succ; object = (struct Object *)object->Node.ln_Succ) {

        UBYTE *label = (object->Node.ln_Name) ? object->Node.ln_Name : "UNNAMED";

        if (OBJECTTYPE(object) == OBJECT_TYPE_LIST) {

            printf("category [%s]\n", label);

            ListTree(object->Value.List);
        }
        else
            puts(label);
    }
}

///
/// "ARexx"

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

  Wait for answer on previously sent message. Free message afterwards. Primary
  return code is returned, the result string (if any) written to <result>.

*/

ULONG
WaitForAnswer(port, result)

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

    *result = NULL;

    do {
        
        WaitPort(port);

        if (rexxMsg = (struct RexxMsg *)GetMsg(port)) {

            if ((error = rexxMsg->rm_Result1) == RC_OK) {

                if (rexxMsg->rm_Result2)

                    strcpy(result, (UBYTE *)rexxMsg->rm_Result2);
            }
        }

    } while (!rexxMsg);

    FreeRexxCommand(rexxMsg);

    return(error);
}


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

 Free ARexx message

*/

void
FreeRexxCommand(rexxmessage)

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

        if (rexxmessage->rm_Result2)

            DeleteArgstring((UBYTE *)rexxmessage->rm_Result2);

    DeleteArgstring((UBYTE *)ARG0(rexxmessage));

    DeleteRexxMsg(rexxmessage);
}


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

 Send ARexx message

*/

struct RexxMsg *
SendRexxCommand(port, cmd, replyPort)

struct MsgPort *replyPort;
UBYTE          *cmd, *port;
{
    struct MsgPort *rexxport;
    struct RexxMsg *rexx_command_message;

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

///
