/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* |_o_o|\\ Copyright (c) 1989 The Software Distillery.                    *
* |. o.| ||          All Rights Reserved                                  *
* | .  | ||          Written by John Toebes and Doug Walker               *
* | o  | ||          The Software Distillery                              *
* |  . |//           235 Trillingham Lane                                 *
* ======             Cary, NC 27513                                       *
*                    BBS:(919)-471-6436                                   *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
#include "pickpack.h"
#include "pwgen.h"

#ifdef DEBUG
int debug = 0;
#endif

#define RES1LINE 124
#define RES2LINE 136

static int Sendit(int);
static int PutRes(int, LONG, int, struct MsgPort *);
static int GetArg(int, LONG *, char *);
static void setgad(struct Gadget *, char *, int, struct Window *, int);

void main(int, char **);
void MemCleanup(void);

/* Global variables */

struct Window *Window;
struct TmpRas tmpras;


static char menutrans[7][14] = {
{
/* FILEHANDLE    */ SEL_HANDLE,
/* FILEINFOBLOCK */ SEL_FILEINFO,
/* INFODATA      */ SEL_INFODATA,
/* BUFFER        */ SEL_BUFFER,
/*               */ 0,
/* SEND          */ SEL_SEND,
/*               */ 0,
/* HELP          */ SEL_HELP,
/*               */ 0,
/* QUIT          */ SEL_QUIT
},

{
/* OPENINPUT     */ SEL_OPENINPUT,
/* OPENOUTPUT    */ SEL_OPENOUTPUT,
/* OPENUPDATE    */ SEL_OPENUPDATE,
/* READ          */ SEL_READ,
/* WRITE         */ SEL_WRITE,
/* SEEK          */ SEL_SEEK,
/* CLOSE         */ SEL_CLOSE,
/* TRUNCATE      */ SEL_TRUNCATE
},

{
/* LOCK          */ SEL_LOCK,
/* DUPLOCK       */ SEL_DUPLOCK,
/* UNLOCK        */ SEL_UNLOCK,
/* EXAMINE       */ SEL_EXAMINE,
/* EXNEXT        */ SEL_EXNEXT,
/* CREATEDIR     */ SEL_CREATEDIR,
/* DELETE        */ SEL_DELETE,
/* RENAME        */ SEL_RENAME,
/* PARENT        */ SEL_PARENT,
/* SETPROTECT    */ SEL_SETPROTECT,
/* SETCOMMENT    */ SEL_SETCOMMENT,
/* SETDATE       */ SEL_SETDATE
},

{
/* CURRENTVOL    */ SEL_CURRENTVOL,
/* INFO          */ SEL_INFO,
/* DISKINFO      */ SEL_DISKINFO,
/* RENAMEDISK    */ SEL_RENAMEDISK
},

{
/* DIE           */ SEL_DIE,
/* FLUSH         */ SEL_FLUSH,
/* MORECACHE     */ SEL_MORECACHE,
/* INHIBIT       */ SEL_INHIBIT,
/* WRITE_PROTECT */ SEL_WRITE_PROTECT,
/* NETWORKHELLO  */ SEL_NETWORKHELLO,
/* DEBUG         */ SEL_DEBUG,
/* SETTRANS      */ SEL_SETTRANS
},

{
/* PickPacket V1.0   */ 0,
/* Copyright...  */ 0,
/* All Rights..  */ 0,
/* See PickPacket... */ 0,
/* MUG SHOT      */ 0
},

{
/* DOSTRUE           -1 */ SEL_MIN1,
/* DOSFALSE           0 */ SEL_ZERO,
/*                      */ 0,
/* OFFSET_BEGINNING  -1 */ SEL_MIN1,
/* OFFSET_CURRENT     0 */ SEL_ZERO,
/* OFFSET_END         1 */ SEL_ONE,
/*                      */ 0,
/* SHARED_LOCK       -2 */ SEL_MIN2,
/* ACCESS_READ       -2 */ SEL_MIN2,
/*                      */ 0,
/* EXCLUSIVE_LOCK    -1 */ SEL_MIN1,
/* ACCESS_WRITE      -1 */ SEL_MIN1,
/*                      */ 0,
/* NULL               0 */ SEL_ZERO
}

};

UBYTE Buf1[14], Buf2[14], Buf3[14], Buf4[14], BufN[32];
static struct IntuiText 
Buf1Text = {3, 0, JAM2, 328,  62, &TOPAZ80, Buf1, NULL      },
Buf2Text = {3, 0, JAM2, 328,  78, &TOPAZ80, Buf2, &Buf1Text },
Buf3Text = {3, 0, JAM2, 328,  94, &TOPAZ80, Buf3, &Buf2Text },
Buf4Text = {3, 0, JAM2, 328, 110, &TOPAZ80, Buf4, &Buf3Text },
NameText = {3, 0, JAM2,  80,  46, &TOPAZ80, BufN, &Buf4Text };

struct packettype
   {
   int number;
   char *name;
   int arg1, arg2, arg3, arg4, res1;
   };

struct packettype packets[] = {
{ 0 }, /* First action begins at 0 */
{ ACTION_FINDINPUT,     "ACTION_FINDINPUT",      HAN, LCK, STR,   0, FLG },
{ ACTION_FINDOUTPUT,    "ACTION_FINDOUTPUT",     HAN, LCK, STR,   0, FLG },
{ ACTION_FINDUPDATE,    "ACTION_FINDUPDATE",     HAN, LCK, STR,   0, FLG },
{ ACTION_READ,          "ACTION_READ",           AG1, BUF, NUM,   0, NUM },
{ ACTION_WRITE,         "ACTION_WRITE",          AG1, BUF, NUM,   0, NUM },
{ ACTION_SEEK,          "ACTION_SEEK",           AG1, NUM, NUM,   0, NUM },
{ ACTION_END,           "ACTION_END",            AG1,   0,   0,   0, FLG },
{ ACTION_TRUNCATE,      "ACTION_TRUNCATE",       AG1,   0,   0,   0, FLG },
{ ACTION_LOCATE_OBJECT, "ACTION_LOCATE_OBJECT",  LCK, STR, NUM,   0, LCK },
{ ACTION_COPY_DIR,      "ACTION_COPY_DIR",       LCK,   0,   0,   0, LCK },
{ ACTION_FREE_LOCK,     "ACTION_FREE_LOCK",      LCK,   0,   0,   0, FLG },
{ ACTION_EXAMINE_OBJECT,"ACTION_EXAMINE_OBJECT", LCK, FIB,   0,   0, FLG },
{ ACTION_EXAMINE_NEXT,  "ACTION_EXAMINE_NEXT",   LCK, FIB,   0,   0, FLG },
{ ACTION_CREATE_DIR,    "ACTION_CREATE_DIR",     LCK, STR,   0,   0, LCK },
{ ACTION_DELETE_OBJECT, "ACTION_DELETE_OBJECT",  LCK, STR,   0,   0, FLG },
{ ACTION_RENAME_OBJECT, "ACTION_RENAME_OBJECT",  LCK, STR, LCK, STR, FLG },
{ ACTION_PARENT,        "ACTION_PARENT",         LCK,   0,   0,   0, LCK },
{ ACTION_SET_PROTECT,   "ACTION_SET_PROTECT",      0, LCK, STR, NUM, FLG },
{ ACTION_SET_COMMENT,   "ACTION_SET_COMMENT",      0, LCK, STR, STR, FLG },
{ ACTION_SET_DATE,      "ACTION_SET_DATE",       LCK, BUF,   0,   0, FLG },
{ ACTION_CURRENT_VOLUME,"ACTION_CURRENT_VOLUME",   0,   0,   0,   0, VOL },
{ ACTION_INFO,          "ACTION_INFO",           LCK, INF,   0,   0, FLG },
{ ACTION_DISK_INFO,     "ACTION_DISK_INFO",      INF,   0,   0,   0, FLG },
{ ACTION_RENAME_DISK,   "ACTION_RENAME_DISK",    STR,   0,   0,   0, FLG },
{ ACTION_DIE,           "ACTION_DIE",              0,   0,   0,   0, FLG },
{ ACTION_FLUSH,         "ACTION_FLUSH",            0,   0,   0,   0, FLG },
{ ACTION_MORE_CACHE,    "ACTION_MORE_CACHE",     NUM,   0,   0,   0, NUM },
{ ACTION_INHIBIT,       "ACTION_INHIBIT",        NUM,   0,   0,   0, FLG },
{ ACTION_WRITE_PROTECT, "ACTION_WRITE_PROTECT",  FLG, NUM,   0,   0, FLG },
{ ACTION_NETWORK_HELLO, "ACTION_NETWORK_HELLO",  STR,   0,   0,   0, FLG },
{ ACTION_HANDLER_DEBUG, "ACTION_HANDLER_DEBUG",  NUM,   0,   0,   0, NUM },
{ ACTION_SET_TRANS,     "ACTION_SET_TRANS",      STR, NUM,   0,   0, FLG },
{ 0 } /* Last packet type is 0 */
};

char *typnames[] = 
{ 
  "<UNUSED>     ",
  "STRING       ",
  "BOOLEAN      ",
  "FileLock     ",
  "FileHandle   ",
  "FileInfoBlock",
  "fh_Arg1      ",
  "InfoData     ",
  "Integer      ",
  "Volume Node  ",
  "<BAD 10>     ",
  "Data Buffer  "
};

extern struct WBStartup *WBenchMsg;

#define NOCONST 12345

#define LASTACT ((sizeof(packets)/sizeof(struct packettype))-2)
void main(argc, argv)
int argc;
char **argv;
{
  struct IntuiMessage *message;
  int setconst;
  int run = 1;
  int select, newsel, len;
  struct Gadget *gad;
  struct Window *CurrentWindow;

  char *tmpchar;
  BPTR olddir;

  olddir = NULL;
  if(argc == 0)
  {
     /* Workbench startup */
     if(WBenchMsg->sm_ArgList->wa_Lock != NULL)
        olddir = CurrentDir(WBenchMsg->sm_ArgList->wa_Lock);
     else
     {
        BUG(1, ("pickpack: Wa_Lock is NULL\n"))
     }
  }

#ifdef DEBUG
  if(argc>0 && argv[1][0] == '-' && 
     (argv[1][1] == 'd' || argv[1][1] == 'D'))
  {
     stcd_i(argv[1]+2, &debug);
     BUG(0, ("*** Debugging initialized at level %d\n", debug))
     argc--, argv++;
  }
#endif

  if(argc>1) strcpy(DevNameSIBuff, argv[1]);

  if ((IntuitionBase = (struct IntuitionBase *)
		       OpenLibrary("intuition.library", 0)) == NULL) 
  {
     BUG(0, ("Can't open intuition.library\n"))
     exit(1);
  }
  if ((GfxBase = (struct GfxBase *)
		 OpenLibrary("graphics.library", 0)) == NULL) 
  {
     BUG(0, ("Can't open graphics.library\n"))
     exit(2);
  }
  if ((Window = OpenWindow(&NewWindowStructure1)) == NULL) 
  {
     BUG(0, ("Can't open window\n"))
     exit(3);
  }

  /* Initialize the code to handle structure windows */
  InitST(Window->UserPort);

  SetDrMd(Window->RPort, JAM1);

  SetMenuStrip(Window, &Menu1);

  select = SEL_LOCK;
  CurrentWindow = NULL;
  setconst = NOCONST;

  while(run >= 0)
  {
     BUG(3, ("pickpack: Top of loop\n"))
     if (run)
        {
        memset(BufN, ' ', 24);
        len = strlen(packets[select].name);
        if (len > 23) len = 23;
        memcpy(BufN, packets[select].name, len);
        BufN[23] = 0;
        strcpy(Buf1, typnames[packets[select].arg1]);
        strcpy(Buf2, typnames[packets[select].arg2]);
        strcpy(Buf3, typnames[packets[select].arg3]);
        strcpy(Buf4, typnames[packets[select].arg4]);
        PrintIText(Window->RPort, &NameText, 0, 0);
        run = 0;
        }

     while((message = (struct IntuiMessage *) GetMsg(Window->UserPort)) == NULL)
     {
        /* No messages, it's safe to close windows */
        PurgeST();
        Wait(1 << Window->UserPort->mp_SigBit);
     }
     
     switch(message->Class)
     {
        case NEWSIZE:
           status("");
           BUG(2, ("Doing a newsize on the window %08lx\n", message->IDCMPWindow))
           MoveWind(message->IDCMPWindow, 0);
           break;

        case CLOSEWINDOW:
           status("");
           BUG(1, ("pickpack: shutting down\n"))
           if (message->IDCMPWindow == Window)
              run = -1;
           else
              {
              BUG(2, ("pickpack: Purge Item\n"))
              UnlinkST(message->IDCMPWindow);
              CurrentWindow = NULL;
              BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
              }
           setconst = NOCONST;
           break;

        case ACTIVEWINDOW:
           if (message->IDCMPWindow != Window)
              CurrentWindow = message->IDCMPWindow;
           BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
           break;

        case INACTIVEWINDOW:
           if (message->IDCMPWindow != Window)
              CurrentWindow = message->IDCMPWindow;
           BUG(3, ("pickpack: InActiveWindow to 0x%08x\n", message->IDCMPWindow))
           break;

        case MENUPICK:
           status("");
           if (message->Code == MENUNULL) break;
           newsel = menutrans[MENUNUM(message->Code)][ITEMNUM(message->Code)];
           BUG(9, ("pickpack: MENUNUM %d ITEMNUM %d newsel %d\n",
              MENUNUM(message->Code), ITEMNUM(message->Code), newsel))
           setconst = NOCONST;
           switch(newsel)
           {
              case 0: 
                 BUG(1, ("pickpack: 0 menu pick\n"))
                 break;

              case SEL_HELP:
                 goto DOHELP;
                 break;

              case SEL_SEND:
                 BUG(2, ("pickpack: Sending packet\n"))
                 if(Sendit(select)) DisplayBeep(NULL);
                 CurrentWindow = NULL;
                 break;

              case SEL_HANDLE:
                 BUG(2, ("pickpack: SEL_HANDLE menu pick\n"))
                 CurrentWindow = AllocST(ST_HANDLE, NULL, 0);
                 BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
                 break;

              case SEL_FILEINFO:
                 BUG(2, ("pickpack: SEL_FILEINFO menu pick\n"))
                 CurrentWindow = AllocST(ST_FIB, NULL, 0);
                 BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
                 break;

              case SEL_INFODATA:
                 BUG(2, ("pickpack: SEL_INFODATA menu pick\n"))
                 CurrentWindow = AllocST(ST_INFO, NULL, 0);
                 BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
                 break;

              case SEL_BUFFER:
                 BUG(2, ("pickpack: SEL_BUFFER menu pick\n"))
                 reqinit();
                 BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
                 break;

              case SEL_QUIT:
                 BUG(2, ("pickpack: SEL_QUIT menu pick\n"))
                 run = -1; 
                 break;

              case SEL_MIN2:
              case SEL_MIN1:
              case SEL_ZERO:
              case SEL_ONE:
                 setconst = newsel - SEL_ZERO;
                 status("Select field to recieve constant value");
                 break;

              default:
                 BUG(2, ("pickpack: %d menu pick\n", newsel))
                 select = newsel;
                 run = 1;
                 break;
           }
           BUG(3, ("pickpack: Menu end Active window changed to 0x%08x\n", CurrentWindow))
           CurrentWindow = NULL;
           break;

        case GADGETDOWN:
        case GADGETUP:
           status("");
           BUG(2, ("pickpack: GADGETDOWN/GADGETUP\n"))
           gad = (struct Gadget *)message->IAddress;
           switch(gad->GadgetID)
           {
              case GAD_BUFLEN:
              case GAD_BLOK:
              case GAD_BLCAN:
                 len = reqkill();
                 if(len > 0 && gad->GadgetID != GAD_BLCAN)
                    CurrentWindow = AllocST(ST_DATA, NULL, len);
                 break;

              case GAD_SEND:
                 BUG(2, ("pickpack: Sending packet\n"))
                 if(Sendit(select)) DisplayBeep(NULL);
                 CurrentWindow = NULL;
                 break;

              case GAD_ARG1:
                 BUG(2, ("pickpack: Case GAD_ARG1\n"))
                 setgad(&STR1, STR1SIBuff, packets[select].arg1,
                        CurrentWindow, setconst);
                 CurrentWindow = NULL;
                 break;

              case GAD_ARG2:
                 BUG(2, ("pickpack: Case GAD_ARG2\n"))
                 setgad(&STR2, STR2SIBuff, packets[select].arg2,
                        CurrentWindow, setconst);
                 CurrentWindow = NULL;
                 break;

              case GAD_ARG3:
                 BUG(2, ("pickpack: Case GAD_ARG3\n"))
                 setgad(&STR3, STR3SIBuff, packets[select].arg3, 
                        CurrentWindow, setconst);
                 CurrentWindow = NULL;
                 break;

              case GAD_ARG4:
                 BUG(2, ("pickpack: Case GAD_ARG4\n"))
                 setgad(&STR4, STR4SIBuff, packets[select].arg4, 
                        CurrentWindow, setconst);
                 CurrentWindow = NULL;
                 break;

              case GAD_PREV:
                 BUG(2, ("pickpack: Case GAD_PREV\n"))
                 select--;
                 if (select < 1)
                    select = LASTACT;
                 run = 1;
                 CurrentWindow = NULL;
                 BUG(3, ("pickpack: prev: Active window changed to 0x%08x\n", CurrentWindow))
                 break;

              case GAD_NEXT:
                 BUG(2, ("pickpack: Case GAD_NEXT\n"))
                 select++;
                 if (select > LASTACT)
                    select = 1;
                 run = 1;
                 BUG(3, ("pickpack: next: Active window changed to 0x%08x\n", CurrentWindow))
                 CurrentWindow = NULL;
                 break;

              case GAD_HANDLE:
                 BUG(2, ("pickpack: GAD_HANDLE gadget pick\n"))
                 CurrentWindow = AllocST(ST_HANDLE, NULL, 0);
                 BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
                 break;

              case GAD_FILEINFO:
                 BUG(2, ("pickpack: GAD_FILEINFO gadget pick\n"))
                 CurrentWindow = AllocST(ST_FIB, NULL, 0);
                 BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
                 break;

              case GAD_INFODATA:
                 BUG(2, ("pickpack: GAD_INFODATA gadget pick\n"))
                 CurrentWindow = AllocST(ST_INFO, NULL, 0);
                 BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
                 break;

              case GAD_BUFFER:
                 BUG(2, ("pickpack: GAD_BUFFER gadget pick\n"))
                 reqinit();
                 BUG(3, ("pickpack: Active window changed to 0x%08x\n", CurrentWindow))
                 break;
#ifdef DEBUG
              case GAD_DEBUG:
                 debug = atoi(DBGVALSIBuff);
                 BUG(1, ("Debugging set to level %d\n", debug))
                 break;
#endif
              case GAD_UP:
              case GAD_DOWN:
              case GAD_SLIDER:
                 BUG(2, ("Doing a move on the window %08lx\n", message->IDCMPWindow))
                 MoveWind(message->IDCMPWindow, GAD_SLIDER-gad->GadgetID);
                 break;

              default:
                 BUG(2, ("pickpack: default gadget\n"))
                 CurrentWindow = NULL;
                 BUG(3, ("pickpack: default: Active window changed to 0x%08x\n", CurrentWindow))
                 break;

           }
           setconst = NOCONST;
           break;

        case SELECTUP:
        case MOUSEBUTTONS:
           BUG(2, ("pickpack: SELECTUP/MOUSEBUTTONS\n"))
           break;  /* Don't change the status() message */

        case RAWKEY:
           BUG(2, ("pickpack: RAWKEY\n"))
           status("");
           if (message->Code == 0x5f || /* Help Key */
               message->Code == 0x3a || /* / ? key */
               message->Code == 0x25)   /* h key */
           {
DOHELP:
              BUG(3, ("pickpack: HELP requested\n"))
              if(GetHelp(&tmpchar, &len) ||
                 AllocST(ST_VIEW, (APTR)tmpchar, len))
              {
                 BUG(1, ("pickpack: There's no help for you!\n"))
              }
              
           }
           CurrentWindow = NULL;
           break;

        default:
           BUG(2, ("pickpack: Unknown IntuiMessage\n"))
           CurrentWindow = NULL;
           break;
     }
     ReplyMsg((struct Message *)message);
  }
  TermST();

  if(olddir) CurrentDir(olddir);

  ClearMenuStrip(Window);
  CloseWindow(Window);
  CloseLibrary(IntuitionBase);
  CloseLibrary(GfxBase);
  exit(0);
}

static void setgad(gad, buf, type, wind, val)
struct Gadget *gad;
char *buf;
int type;
struct Window *wind;
int val;
{
if (val != NOCONST)
   {
   /* We have a pending constant to deal with */
   switch(type)
       {
       case FLG:
          if (val == 0) strcpy(buf, "DOSTRUE");
          else if (val == -1) strcpy(buf, "DOSFALSE");
          else
             {
             DisplayBeep(NULL);
             status("Invalid flag value");
             return;
             }
          break;
       case LCK:
          if (val != 0)
             {
             DisplayBeep(NULL);
             status("Invalid lock value");
             return;
             }
          /* Fall through to the num */             
       case NUM:
          sprintf(buf, "%d", val);      
          break;
       default:
          status("Numeric argument not allowed");
          DisplayBeep(NULL);
          return;
       }
   }
else if (wind != NULL)
   {
   switch(type)
      {
      case LCK:
      case HAN:
      case FIB:
      case AG1:
      case INF:
      case VOL:
      case BUF:
         strcpy(buf, wind->Title);
         break;

      case NUM:
         sprintf(buf, "%d", WindSize(wind));
         break;

      default:
         status("Window argument not allowed");
         DisplayBeep(NULL);
         break;
      }
   }

else
   {
   status("No argument pending for field");
   return;
   }

RefreshGList(gad, Window, NULL, 1);
}

#define FNLEN 101
static int fnused;
static char fn1[FNLEN], fn2[FNLEN];

static int Sendit(select)
int select;
{
   int rc;
   struct MsgPort *pid;
   char buf[100];
   LONG args[8];
   LONG res[2];
   BUG(1,("Sendit: Entry, select %d device '%s'\n", select, DevNameSIBuff))

   pid = DeviceProc(DevNameSIBuff);
   if(!pid)
   {
      BUG(1, ("Sendit: Exit, no such device\n"))
      sprintf(buf, "Unknown device '%s'", DevNameSIBuff);
      status(buf);
      return(RC_ERRNODEVICE);
   }

   fnused = 0;

   if (rc=GetArg(packets[select].arg1, args,   STR1SIBuff))
   {
     status("Invalid value for dp_Arg1");
     return(rc);
   }
   if (rc=GetArg(packets[select].arg2, args+1, STR2SIBuff))
   {
     status("Invalid value for dp_Arg2");
     return(rc);
   }
   if (rc=GetArg(packets[select].arg3, args+2, STR3SIBuff))
   {
     status("Invalid value for dp_Arg3");
     return(rc);
   }
   if (rc=GetArg(packets[select].arg4, args+3, STR4SIBuff))
   {
     status("Invalid value for dp_Arg4");
     return(rc);
   }

   sendpkt(pid, packets[select].number, args, 4, res);

   BUG(1, ("Sendit: Sendpkt returned %ld, %ld\n", res[0], res[1]))

   PutRes(packets[select].res1, res[0], RES1LINE, pid);
   PutRes(RCNUM, res[1], RES2LINE, pid);

   switch(packets[select].number)
   {
      case ACTION_FREE_LOCK:
      {
         struct Window *tmpw;
         tmpw = STToWind(BADDR(args[0]));
         NameST(tmpw, NULL, NULL);
         UnlinkST(tmpw);
         break;
      }

      case ACTION_END:
         NameST(STToWind((APTR)args[0]), NULL, NULL);
         break;

      case ACTION_FINDINPUT:
      case ACTION_FINDOUTPUT:
      case ACTION_FINDUPDATE:
         if(res[0] == DOSTRUE)
            NameST(STToWind(BADDR(args[0])), STR3SIBuff, pid);
         break;

      case ACTION_DISK_INFO:
         DisplayST(STToWind(BADDR(args[0])));
         break;

      case ACTION_EXAMINE_OBJECT:
      case ACTION_EXAMINE_NEXT:
      case ACTION_INFO:
         DisplayST(STToWind(BADDR(args[1])));
         break;

      case ACTION_READ:
      case ACTION_WRITE:
         DisplayST(STToWind(BADDR(args[0])));
         DisplayST(STToWind((APTR)args[1]));
         break;
   }

   return(RC_OK);
}

static struct IntuiText ResText = {
	1,0,JAM2,   /* front and back text pens, drawmode and fill byte */
	0,0,        /* XY origin relative to container TopLeft */
	&TOPAZ80,   /* font pointer or NULL for default */
	NULL,       /* pointer to text */
	NULL        /* next IntuiText structure */
};


static int PutRes(vtype, res, top, pid)
int vtype;
LONG res;
int top;
struct MsgPort *pid;
{
   int rc;
   struct Window *w;
   char data[100];

   BUG(1, ("PutRes: Entry, vtype %d\n"))

   ResText.IText = data;
   ResText.FrontPen = 1;
   ResText.BackPen = 0;
   memset(data, ' ', 50);
   rc = RC_OK;
   switch(vtype)
   {
      case 0:
         break;

      case FLG:
         if(res == DOSFALSE) strcpy(data, "DOSFALSE");
         else if(res == DOSTRUE) strcpy(data, "DOSTRUE");
         else sprintf(data, "??? %ld ???", res);
         break;

      case LCK:
         if(res)
         {
            if(AllocST(ST_LOCK, BADDR(res), 0))
            {
               w = STToWind(BADDR(res));
               strcpy(data, w->Title);
               NameST(w, fn1+1, pid);
            }
         }
         else
         {
            strcpy(data, "NULL");
         }
         break;

      case RCNUM:
         sprintf(data, "RC %ld - ", res);
         switch(res)
            {
            case 103: strcat(data, "insufficient free store"); break;
            case 105: strcat(data, "task table full!"); break;
            case 120: strcat(data, "argument line invalid or too long"); break;
            case 121: strcat(data, "file is not an object module"); break;
            case 122: strcat(data, "invalid resident library during load"); break;
            case 202: strcat(data, "object in use"); break;
            case 203: strcat(data, "object already exists"); break;
            case 204: strcat(data, "directory not found"); break;
            case 205: strcat(data, "object not found"); break;
            case 206: strcat(data, "invalid window description"); break;
            case 209: strcat(data, "packet request type unknown"); break;
            case 210: strcat(data, "stream name component invalid"); break;
            case 211: strcat(data, "invalid object lock"); break;
            case 212: strcat(data, "object not of required type"); break;
            case 213: strcat(data, "disk not validated"); break;
            case 214: strcat(data, "disk write-protected"); break;
            case 215: strcat(data, "rename across devices attempted"); break;
            case 216: strcat(data, "directory not empty"); break;
            case 218: strcat(data, "device (or volume) not mounted"); break;
            case 219: strcat(data, "seek failure"); break;
            case 220: strcat(data, "comment too big"); break;
            case 221: strcat(data, "disk full"); break;
            case 222: strcat(data, "file is protected from deletion"); break;
            case 223: strcat(data, "file is write protected"); break;
            case 224: strcat(data, "file is read protected"); break;
            case 225: strcat(data, "not a valid DOS disk"); break;
            case 226: strcat(data, "no disk in drive"); break;
            case 232: strcat(data, "no more entries in directory"); break;
            case   0: break;
            default:  strcat(data, "???????"); break;
            }
         break;

      case NUM:
         sprintf(data, "%ld", res);
         break;

      case VOL:
         rc = RC_ERRBADDATA;
         break;

      default:
         rc = RC_ERRBADDATA;
         break;
   }

   if(rc == RC_OK) 
   {
      data[strlen(data)] = ' ';
      data[42] = 0;
      PrintIText(Window->RPort, &ResText, 80, top);
      BUG(1, ("PutRes: Data value is %s\n", data))
   }
#ifdef DEBUG
   else
      BUG(1, ("PutRes: Bad RC %d\n", rc))
#endif

   return(rc);
}

void status(msg)
char *msg;
{
char data[100];
int len;

len = strlen(msg);
memset(data, ' ', 50);
if (len > 50) len = 50;
memcpy(data, msg, len);
data[50] = 0;
ResText.FrontPen = 0;
ResText.BackPen = (len == 0 ? 0 : 1);
ResText.IText = data;
PrintIText(Window->RPort, &ResText, 19, 148);
}

static int GetArg(vtype, arg, data)
int vtype;
LONG *arg;
char *data;
{
   int rc;
   unsigned char *tmpchar;
   APTR v;

   BUG(1, ("GetArg: Entry, vtype %d data %s\n", vtype, data))

   *arg = 0;

   rc = RC_OK;
   switch(abs(vtype))
   {
      case 0:
         break;

      case STR:
         tmpchar = (unsigned char *)(fnused ? fn2 : fn1);
         strcpy(tmpchar+1, data);
         tmpchar[0] = strlen(data);
         *arg = MKBADDR(tmpchar);
         break;

      case FLG:
         if(stricmp(data, "DOSTRUE")) *arg = DOSTRUE;
         else if(stricmp(data, "DOSFALSE")) *arg = DOSFALSE;
         else rc = RC_ERRBADDATA;
         break;

      case LCK:
         if(data[0] == '0' || data[0] == '\0')
         {
            *arg = NULL;
            break;
         }
         v = FindST(data, ST_LOCK);
         if(!v) rc = RC_ERRBADDATA;
         else *arg = (LONG)MKBADDR(v);
         break;

      case HAN:
         v = FindST(data, ST_HANDLE);
         if(!v) rc = RC_ERRBADDATA;
         else *arg = (LONG)MKBADDR(v);
         break;

      case FIB:
         v = FindST(data, ST_FIB);
         if(!v) rc = RC_ERRBADDATA;
         else *arg = (LONG)MKBADDR(v);
         break;

      case AG1:
         v = FindST(data, ST_HANDLE);
         if(!v) rc = RC_ERRBADDATA;
         else *arg = (LONG)((struct FileHandle *)v)->fh_Arg1;
         break;

      case INF:
         v = FindST(data, ST_INFO);
         if(!v) rc = RC_ERRBADDATA;
         else *arg = (LONG)MKBADDR(v);
         break;

      case NUM:
         stcd_l(data, arg);
         break;

      case VOL:
         rc = RC_ERRBADDATA;
         break;

      case BUF:
         v = FindST(data, ST_DATA);
         if(!v) rc = RC_ERRBADDATA;
         else *arg = (LONG)v;
         break;

      default:
         rc = RC_ERRBADDATA;
         break;
   }

#ifdef DEBUG
   if(rc)
      BUG(1, ("GetArg: Bad RC %d\n", rc))
   else
      BUG(1, ("GetArg: arg %d (0x%08x)\n", *arg, *arg))
#endif

   return(rc);
}