/*******************  help.c  ********************
 *                                               *
 *                                               *
 *                     v1.15                     *
 *                                               *
 *                  © by Koessi                  *
 *                                               *
 *             Tuesday, 21 Nov 1992              *
 *                                               *
 *                                               *
 *  this is an help showing the usage of         *
 *  "hyper" from inside another program          *
 *                                               *
 *  Compile with DICE:                           *
 *  dcc help.c -ohelp -rr -2.0                   *
 *                                               *
 *************************************************/

#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <rexx/storage.h>

/* Prototypes */
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/alib_protos.h>
#include <clib/rexxsyslib_protos.h>

#define  MSG struct Message
#define RMSG struct RexxMsg
#define MSGP struct MsgPort
#define SIZE 32

extern void SendRxMsg(char *);
extern __stkargs void _main(short, char *);
extern int main(int, char **);

#define NUMARGS 12

const char version[]    = {'$','V','E','R',':',' ' };
const char taskname[]   = "Help  v1.15 © Koessi 92 - Funware\n";
const char exthelpstr[] = "›32mUsage:\tHelp [FILENAME] [DOC chapter]"
                                           "[SCREEN publicscreen]\n"
                          "\t\t[X n] [Y n] [WIDTH n] [HEIGHT n] [GADS ON|OFF]\n"
                          "\t\t[FONT name.font<n>] [SLEEP] [QUIT]›0m\n"
                          "\n\tcall Hyper (>= Ver1.15) via its ARexx-port:\n"
                          "\tFILENAME\tshould be a hyper-text-file\n"
                          "\tDOC/K\t\trequest a special chapter\n"
                          "\tSCREEN/K\tmake Hyper appear on that screen\n"
                          "\tX/N, Y/N\n"
                          "\tW=WIDTH/N\n"
                          "\tH=HEIGHT/N\tset position&size for the window\n"
                          "\tG=GADS/T\ttoggle gadgets ON/OFF (default is OFF)\n"
                          "\tF=FONT/K\tuse this font to render text (default is \"pearl.font8\")\n"
                          "\tonly if Hyper is already running:\n"
                          "\tS=SLEEP/S\tstart Hyper into the background\n"
                          "\tQ=QUIT/S\tend Hyper and free memory\n"
                          "\t\t\t";

const char template[]   = "FILENAME,DOC/K,SCREEN/K,X/N,Y/N,W=WIDTH/N,H=HEIGHT/N,"
                          "G=GADS/T,F=FONT/K,S=SLEEP/S,Q=QUIT/S";
const char portname[]   = "HYPER_RXPORT";
const char command[]    = "SYS:Utilities/hyper S";
const char error[]      = "\n\n›32m***ERROR›0m";

const void *argarray[NUMARGS] = {0};                  /*  holds argptrs   */


/*************************************************
 *                                               *
 *                                               *
 *    FUNCTION: _main                            *
 *                                               *
 *                                               *
 *    INPUT:    short len                        *
 *              char *arg                        *
 *                                               *
 *    OUTPUT:   __stkargs void                   *
 *                                               *
 *    NOTE:                                      *
 *                                               *
 *************************************************/


__stkargs void
_main(short len, char *arg)
{
  PutStr(taskname);
  int errorcode = ERROR_REQUIRED_ARG_MISSING;
  if (len > 1)          /*  args ? */
  {
    struct RDArgs *rdargs;
    if (rdargs = AllocVec(sizeof(struct RDArgs), MEMF_PUBLIC|MEMF_CLEAR))
    {
      rdargs->RDA_ExtHelp = exthelpstr;   /*  shown if 2 x ? */

      struct RDArgs *rda;
      if (rda = ReadArgs(template, argarray, rdargs))
      {
        long **argptr = argarray;
        for (BYTE i = 0; i < NUMARGS; ++i)
        {
          if (argptr && *argptr)
          {
            errorcode = RETURN_OK;
            break;
          }
          ++argptr;
        }
        if (errorcode == RETURN_OK)
        {
          MSGP *port;
          if (!(port = FindPort(portname)))
          {
            SystemTags(command, SYS_Asynch, TRUE,
                                SYS_Output, NULL,
                                SYS_Input,  NULL,
                                TAG_DONE);

            for (BYTE i = 10; i; --i)
            {
              Delay(20);
              if (port = FindPort(portname))
                break;
            }
          }
          PutStr("\n");
          if (port)
            SendRxMsg(arg);
          else
            PrintFault(ERROR_OBJECT_NOT_FOUND, portname);
        }
        FreeArgs(rda);
      }
      else
        errorcode = IoErr();

      FreeVec(rdargs);
    }
    else
      errorcode = ERROR_NO_FREE_STORE;
  }
  if (errorcode)
  {
    PutStr(exthelpstr);
    PrintFault(errorcode, error);
  }
}

/*************************************************
 *                                               *
 *                                               *
 *    FUNCTION: SendRxMsg                        *
 *                                               *
 *                                               *
 *    INPUT:    char *msgtxt                     *
 *                                               *
 *    OUTPUT:   void                             *
 *                                               *
 *    NOTE:     like cmdline                     *
 *                                               *
 *************************************************/


void
SendRxMsg(char *msgtxt)
{
  MSGP *reply_port;
  if (reply_port = CreateMsgPort())
  {
    void *rx_msg;       /*  casted to parts of a RexxMsg struct */
    if (rx_msg = AllocVec(sizeof(RMSG), MEMF_PUBLIC|MEMF_CLEAR))
    {
      ((struct Node *)rx_msg)->ln_Type      = NT_MESSAGE;
      ((MSG         *)rx_msg)->mn_ReplyPort = reply_port;
      ((MSG         *)rx_msg)->mn_Length    = sizeof(RMSG);
      ((RMSG        *)rx_msg)->rm_Args[0]   = msgtxt;

      Forbid();
      MSGP *rx_port;
      if (rx_port = (MSGP *)FindPort(portname))
      {
        PutMsg(rx_port, (MSG *)rx_msg);
        Permit();
        WaitPort(reply_port);
        ReplyMsg(GetMsg(reply_port));
      }
      else
        Permit();

      FreeVec(rx_msg);
    }
    DeleteMsgPort(reply_port);
  }
}
