/***************************************************************** * * * XICON V2.01 * * * * Runs Command Script Files from an Icon * * * * copyright 1986, 1987, 1988 by Pete Goodeve * * -- All Rights Reserved * * * * Compile with pass2 -v option (Lattice) * * Link with c.o, amiga.lib, lc.lib * * * * vers 88:2:14 * *****************************************************************/ #include "exec/types.h" #include "exec/exec.h" #include "workbench/startup.h" #include "workbench/workbench.h" #include "workbench/icon.h" #include "libraries/dosextens.h" LONG IntuitionBase; short V1_2 = FALSE; LONG IconBase; extern struct Window *findwindow(); extern struct WBStartup *WBenchMsg; struct WBArg *argptr; short nargs; short autoclose=TRUE, /* will be FALSEified by non-use of 'closewindow' */ usescript=TRUE, usewindow = TRUE, istext = FALSE; short abortmark = FALSE; #define MAXDESCR 120 char ConDescr[MAXDESCR+4] = "CON:0/10/640/185/XICON 2.01"; /* available for later fiddling */ #define MAXTITLE 100 char Title[MAXTITLE]; LONG outfile = NULL; extern struct Window *conWindow; extern struct ConUnit *conUnit; LONG windowsig; /** Close Gadget structure */ LONG Close_Data[] = { /* move to chip ram before use */ 0x3FFFFC80, 0x30000C80, 0x33FFCC80, 0x33FFCC80, 0x33C3CC80, 0x33C3CC80, 0x33FFCC80, 0x33FFCC80, 0x30000C80, 0x3FFFFC80, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x003C0000, 0x003C0000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }; struct Image Close_Image = { 0, 0, /* Left, Top */ 0x0019, 0x000A, 2, /* Width, Height, Depth */ NULL, /* filled in to point to image in chip ram */ 3, 0, NULL }; struct Gadget Close_Gadg = { NULL, /* pointer to Next Gadget */ 4, 0, 0x019, 0x0A, /* (Left Top Width Height) Hit Box */ GADGHCOMP | GADGIMAGE, /* Flags */ /* Activation flags */ RELVERIFY, SYSGADGET | CLOSE, /* Type (!) */ (APTR)&Close_Image, /* pointer to GadgetRender */ NULL, /* no pointer to SelectRender */ NULL, /* no pointer to GadgetText */ 0, /* no MutualExclude */ NULL, /* no pointer to SpecialInfo */ 0, /* no ID */ NULL /* no pointer to special data */ }; /* Continue Gadget structure */ struct IntuiText Cont_Text = { 3,0, /* front, back pens */ JAM2, /* draw mode */ 10,1, /* left, top edge */ NULL, /* default font */ NULL, /* text string -- filled in before use */ NULL /* no next */ }; struct Gadget Cont_Gadg = { NULL, /* pointer to Next Gadget */ 0, -9, 0, 9, /* (Left Top Full-Width Height) Hit Box */ GADGHCOMP | GRELWIDTH | GRELBOTTOM , /* Flags */ /* Activation flags */ RELVERIFY, BOOLGADGET, /* Type */ NULL, /* no pointer to GadgetRender */ NULL, /* no pointer to SelectRender */ &Cont_Text, /* pointer to GadgetText */ 0, /* no MutualExclude */ NULL, /* no pointer to SpecialInfo */ 0, /* no ID */ NULL /* no pointer to special data */ }; _main() /* bypasses standard C startup code */ { if (!WBenchMsg) return 0; if (IntuitionBase = OpenLibrary("intuition.library",33)) V1_2 = TRUE; else IntuitionBase = OpenLibrary("intuition.library",0); IconBase = OpenLibrary(ICONNAME,1); /* doesn't matter much if not there */ argptr = WBenchMsg->sm_ArgList; nargs = WBenchMsg->sm_NumArgs; /* Skip the first arg (the program itself) and process the rest */ for(argptr++, nargs--; nargs; argptr++, nargs--) if (!doito(argptr)) goto clean_exit; /* sometimes a goto is good */ SetSignal(0, SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | windowsig); if (usewindow && !autoclose) { Wait(SIGBREAKF_CTRL_C | SIGBREAKF_CTRL_D | windowsig); } clean_exit: dump_window(); if (outfile) Close(outfile); if (IconBase) CloseLibrary(IconBase); CloseLibrary(IntuitionBase); /* this is in "ROM" (so no check needed) */ } /*** end main ***/ /************************************************************ * In the code below, I don't follow the usual method of * * passing each command string in turn to Execute. Instead * * I pass the entire command file as the new input stream, * * which Execute accepts after processing the null string * * it gets as a "command". This avoids the system having * * to reload the DOS "RUN" module for every line of the * * command file, though on the other hand it does lock out * * the possibility of redirecting keyboard input through * * the "current window" to the command. I thought the * * trade-off was worth it. * ************************************************************/ doito(argp) struct WBArg *argp; { LONG oldir; oldir = CurrentDir(argp->wa_Lock); if (!readtt(argp) || abortmark) return FALSE; if (istext) dispfile(argp->wa_Name); else if (usescript) if (!execfile(argp->wa_Name)) return FALSE; /* I don't see how that could happen, but...*/ CurrentDir(oldir); return TRUE; } execfile(fname) char *fname; { LONG infile; infile = Open(fname, MODE_OLDFILE); if (!infile) return FALSE; Execute("", infile, outfile); Close(infile); return TRUE; } /* Read ToolTypes of current icon */ readtt(argp) struct WBArg *argp; { struct DiskObject *iconobj=NULL, *GetDiskObject(); char **toolarray, *FindToolType(); char *modes, *windowstring, *titlestring, *locdir; LONG dirfile; if (!IconBase) { if (!get_window(ConDescr)) return FALSE; display("Icon Library not found -- ignoring ToolTypes\n"); return TRUE; /* just soldier on...*/ } /* we don't do any checks here for icon type -- probably should...*/ if (!(iconobj = GetDiskObject(argp->wa_Name))) { display("COULDN'T GET INFO FOR ICON!!\n"); return TRUE; } toolarray = iconobj->do_ToolTypes; modes = FindToolType(toolarray,"MODE"); autoclose &= MatchToolValue(modes,"closewindow"); /* ALL must agree to close the window automatically */ usescript = !MatchToolValue(modes,"noscript"); istext = MatchToolValue(modes,"text"); if (windowstring = FindToolType(toolarray,"WINDOW")) strncpy(&ConDescr[4], windowstring, MAXDESCR); /* append to 'CON:' */ /* the above is probably a Lattice special...*/ if (!outfile) { usewindow = !MatchToolValue(modes,"nowindow"); if (usewindow) get_window(ConDescr); else outfile = Open("NIL:", MODE_OLDFILE); } if (!outfile) return FALSE; if (conWindow && (titlestring = FindToolType(toolarray,"TITLE"))) { strncpy(Title, titlestring, MAXTITLE); /* Note that SetWindowTitles does NOT copy the string! */ SetWindowTitles(conWindow, Title, -1); } if ((locdir = FindToolType(toolarray,"LOCDIR")) && (dirfile = Open(locdir,MODE_NEWFILE))) { Write(dirfile,"\"",1); traverse(argp->wa_Lock, dirfile); Write(dirfile,"\"\n",2); Close(dirfile); } dotoolcmds(toolarray); /* some tooltypes may be commands */ FreeDiskObject(iconobj); return TRUE; } /* Execute any commands specified in the ToolTypes */ dotoolcmds(toolarray) char **toolarray; { char *holdnext, *toolstr, *FindToolType(); LONG lock; while (*toolarray) { holdnext = toolarray[1]; toolarray[1] = NULL; if (!abortmark) { if (toolstr=FindToolType(toolarray,"REM")) { display(toolstr); display("\n"); } else if (toolstr=FindToolType(toolarray,"TEXT")) dispfile(toolstr); else if (toolstr=FindToolType(toolarray,"CMD")) Execute(toolstr,0,outfile); else if (toolstr=FindToolType(toolarray,"SCRIPT")) execfile(toolstr); else if (!strcmp(*toolarray,"PAUSE")) /*FindT-T- needs "=" */ abortmark = pausekey(); else if (toolstr=FindToolType(toolarray,"EXISTS")) { if (lock = Lock(toolstr,ACCESS_READ)) UnLock(lock); else abortmark = TRUE; } } /* end !abortmark */ else /* abort has been signalled */ { if (toolstr=FindToolType(toolarray,"ABORT-REM")) { display(toolstr); display("\n"); } else if (toolstr=FindToolType(toolarray,"ABORT-TEXT")) dispfile(toolstr); else if (toolstr=FindToolType(toolarray,"ABORT-CMD")) Execute(toolstr,0,outfile); else if (toolstr=FindToolType(toolarray,"ABORT-SCRIPT")) execfile(toolstr); else if (!strcmp(*toolarray,"ABORT-PAUSE")) abortmark = pausekey(); else if (!strcmp(*toolarray,"RESTORE")) abortmark = FALSE; } *++toolarray = holdnext; /* restore next item & move to it */ } } traverse(lock, dirfile) ULONG lock, dirfile; { short level; ULONG pdlock; struct DeviceList *volp; struct FileLock *lockp; char *namep; struct FileInfoBlock *fib; if (lock) { fib = AllocMem(sizeof(struct FileInfoBlock),MEMF_PUBLIC | MEMF_CLEAR); if (!fib) return 2; /* ...being lazy */ level = traverse(pdlock=ParentDir(lock), dirfile); UnLock(pdlock); if (level > 1) /* there is a superior non-root directory */ Write(dirfile, "/", 1); if (level == 0) /* this was the root directory */ { /* all this to overcome RAM: handler bug...*/ lockp = (struct FileLock *)BADDR(lock); volp = (struct DeviceList *)BADDR(lockp->fl_Volume); namep = (char *)BADDR(volp->dl_Name); Write(dirfile, namep+1, *namep); Write(dirfile, ":", 1); } else { if (Examine(lock,fib)) Write(dirfile,fib->fib_FileName,strlen(fib->fib_FileName)); } FreeMem(fib,sizeof(struct FileInfoBlock)); return level+1; } else return 0; } get_window(windescr) char *windescr; { if (outfile) /* already open */ return TRUE; outfile = Open(windescr, MODE_OLDFILE); if (!outfile) return FALSE; if (!findWindow(outfile)) return FALSE; if (!(Close_Image.ImageData = AllocMem(sizeof(Close_Data), MEMF_CHIP))) return TRUE; /* just ignore close gadget */ /* the following may be a Lattice special..?*/ movmem(Close_Data, Close_Image.ImageData, sizeof(Close_Data)); ModifyIDCMP(conWindow, CLOSEWINDOW); /* Heh..again*/ windowsig = 1<<(conWindow->UserPort->mp_SigBit); conWindow->Flags |= WINDOWCLOSE; /* Heh heh! */ AddGadget(conWindow, &Close_Gadg, 0); /* Must be on TOP of drag gadget */ if (V1_2) RefreshWindowFrame(conWindow); else { SetWindowTitles(conWindow, conWindow->Title, -1); RefreshGadgets(&Close_Gadg, conWindow, NULL); } return TRUE; } /* get_window */ dump_window() { if (!Close_Image.ImageData) return; ModifyIDCMP(conWindow, 0); RemoveGadget(conWindow, &Close_Gadg); FreeMem(Close_Image.ImageData, sizeof(Close_Data)); /* file & window are closed at a higher level */ } display(msg) char *msg; { Write(outfile, msg, strlen(msg)); } /**************************************/ #define BUFSIZE 200 LONG textfile; static short curmax = 0; dispfile(fname) char *fname; { char inbuf[BUFSIZE], outbuf[BUFSIZE], ansbuf[2]; short inpos = 0, lcount = 20; curmax = 0; textfile = Open(fname, MODE_OLDFILE); if (!textfile || !conWindow) return FALSE; ModifyIDCMP(conWindow, conWindow->IDCMPFlags | RAWKEY); while (copyline(inbuf, &inpos, outbuf)) { if (!lcount-- || *outbuf == '\014' /*Formfeed*/) { if (pausekey()) goto cutit; /* just continues unless CLOSE */ display(outbuf); lcount = 15; /* leave some overlap with previous page */ } else display(outbuf); } cutit: Close(textfile); ModifyIDCMP(conWindow, conWindow->IDCMPFlags & ~RAWKEY); } copyline(in, pos, out) char *in, *out; short *pos; { char ch, copych(); short trunc=BUFSIZE-1; while ((*out++ = ch = copych(in, pos)) && ch != '\n' && --trunc) /*loop*/; *out = '\0'; return (int) ch /* FALSE if EOF */; } char copych(in, pos) char *in; short *pos; { if (*pos >= curmax) { curmax = Read(textfile,in,BUFSIZE); *pos = 0; if (!curmax) return '\0'; } return in[(*pos)++]; } pausekey() { int code; Cont_Text.IText = "to CONTINUE -- Click here or Type any key"; AddGadget(conWindow, &Cont_Gadg, -1); RefreshGadgets(&Cont_Gadg, conWindow, NULL); code = pause(RAWKEY | GADGETUP); Cont_Text.IText = " "; /* seems crude, but it's all I can figger.. */ RefreshGadgets(&Cont_Gadg, conWindow, NULL); RemoveGadget(conWindow, &Cont_Gadg); return code; } #define CODE_C 0x033 pause(evmask) ULONG evmask; /* waits for a relevant event from the window */ /* if it is a CLOSEWINDOW or cntrl-C it returns TRUE, otherwise FALSE */ { struct IntuiMessage *eventmsg, *GetMsg(); ULONG oldIDCMP, class, mark = FALSE; USHORT code, qual; if (!conWindow) return FALSE; /* only wait if there's a window */ oldIDCMP = conWindow->IDCMPFlags; if (evmask) ModifyIDCMP(conWindow, conWindow->IDCMPFlags | evmask); do { Wait(windowsig); while(eventmsg = GetMsg(conWindow->UserPort)) { class = eventmsg->Class; code = eventmsg->Code; qual = eventmsg->Qualifier; ReplyMsg(eventmsg); if((class == CLOSEWINDOW) || (class == RAWKEY && (qual & IEQUALIFIER_CONTROL) && code == CODE_C )) { mark = TRUE; break; } } } while ((class == RAWKEY) && (code & IECODE_UP_PREFIX)); /* ignore left-over key-ups */ if (evmask) ModifyIDCMP(conWindow, oldIDCMP); return mark; } /**************************************/