#ifdef This_Is_A_Big_Comment Have you ever wanted CLI on a custom screen with 25 lines of 80 characters? Here it is! By Paul Kienitz, 11/27/88. When compiling with Aztec C, DO NOT use the +M option (stack checking). There are some provisions for compiling it without Aztec, but they are UNTESTED AND PROBABLY INCOMPLETE. Last revision date: 3/26/89. The major question is, how do we get EndCLI to wait for filehandles on the window to close? Is it a ConMan problem? YES. If I use an ordinary window, the CON handler waits; only with a strange Wnnnnnn window does the handler close the window when I Close the file handle without seeing if anyone else is still using it. And how do I tell whether Shell-Seg is resident? Scan the resident list for something the right size? No, don't bother. How do you make a failing Workbench program beep the screen and set "last error"? With the startup message reply somehow? I don't think so. Improvements needed: => o Make it work without ConMan. => o Make it wait for other things with window filehandles to quit. I guess this comes down to getting rid of ConMan dependency. o Make it not need to be "Run CLImax". Create global permanent piece of cleanup code and patch it into file handle's closefunc field? o hot key to bring to front and activate? Make your own, I don't need one. o Invisible full size screen depth gadgets? Nah. o Command line options for colors, wbenchscreen?, overscanmargin?, startup command?. ToolTypes for all those plus CD. o After I've got FastExNext down, how about FastExecute? o There's not much I can do to reduce the memory consumption. Aside from the 33K of chip ram for the screen, it uses no more than a Workbench Shell does, which is a lot (22K). It's only about 10K for a NewCLI. That's with ConMan; it's probably less with vanilla CON:. The experimental cli-cleans-itself-up version would probably use less memory that the waiting-process version. #endif /* big comment */ #define INTUITIONPRIVATE /* So IntuitionBase->Preferences is visible. We're examining only. */ #include #include #include #include #include #include #include #ifdef AZTEC_C #include /* modified so BPTR () functions are declared so */ #endif #include /* screen/window stuff based on copied leo schwab code */ #define XSIZE 640 #define GREENISHNESS {0x484, 0x000, 0x0b0, 0xcc0} #define OverscanMargin 4 /* we overscan so there's a small space at the top to pull the screen down with; lets you see part of the screen depth gadgets */ #define SCLI struct CommandLineInterface struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct Screen *scr; struct Window *win; extern struct WBStartup *WBenchMsg; adr IconBase; adr wopter; struct Process *me; bool lace = false, unshelled = false, greenify = false, baloney = false; UBYTE scr_tit[] = " CLImax screen "; /* won't actually show */ struct NewScreen scrdef = { 0, 0, XSIZE, 47L, /* YSIZE will be set later */ 2, /* 4 colors */ 0, 0, /* detail pen = background so no white stripe at top */ HIRES, CUSTOMSCREEN, null, scr_tit, null, null /* no special font, gadget, or bitmap */ }; struct NewWindow windef = { 0, OverscanMargin, XSIZE, 44L, /* YSISE will be set later */ 0, 1, 0L, ACTIVATE | BACKDROP | BORDERLESS, null, null, null, /* no special gadget or checkmark, no title */ 69L, /* screen pointer; will get set later */ null, /* no custom bitmap */ 0, 0, 0, 0, /* ignored */ CUSTOMSCREEN }; /* #define puf(S, N) (sprintf(buf, S, N), spew(buf)) #define puff(S, N, NN) (sprintf(buf, S, N, NN), spew(buf)) char buf[256]; */ void spew(s) str s; { register BPTR o = Output(); register long l = strlen(s); if (o) Write(o, s, l); } openstuff () { ushort *wbcolor, tallth; static ushort lacecolor[4] = GREENISHNESS; long collor; /* that's how Joan spelled it once */ struct ViewPort *vp; IntuitionBase = (adr) OpenLibrary ("intuition.library", 1L); GfxBase = (adr) OpenLibrary ("graphics.library", 1L); /* Look Ma, no error check! */ tallth = IntuitionBase->MaxDisplayHeight & ~15; if (lace) scrdef.ViewModes = HIRES | LACE; else tallth >>= 1; windef.Height = tallth; scrdef.Height = tallth + OverscanMargin; if (!(scr = OpenScreen (&scrdef))) { spew ("Can't open screen.\n"); closestuff(); exit (10); } windef.Screen = scr; if (!(win = OpenWindow (&windef))) { spew ("Can't open window.\n"); closestuff(); exit (10); } ShowTitle(scr, FALSE); vp = &(scr -> ViewPort); /* set colors according to Preferences */ if (greenify) wbcolor = lacecolor; /* except when G option */ else wbcolor = &IntuitionBase->Preferences->color0; /* nothing multitasking-unsafe about examining in place, right? */ for (collor = 0; collor <= 3; collor++, wbcolor++) SetRGB4(vp, collor, (*wbcolor >> 8) & 15L, (*wbcolor >> 4) & 15L, *wbcolor & 15L); } closestuff () { register struct Window *w; me->pr_WindowPtr = wopter; /* ConMan 1.3 closes the window when you close the file handle. Older ConMen don't. We have to handle both cases, so we see if the window is still attached to the screen: */ if (scr && win) for (w = scr->FirstWindow; w; w = w->NextWindow) if (w == win) { CloseWindow(win); break; } if (scr) CloseScreen (scr); if (GfxBase) CloseLibrary (GfxBase); if (IntuitionBase) CloseLibrary (IntuitionBase); } /* strlen that doesn't look past length 255 */ int blen(m) register str m; { register int l; for(l = 0; l < 255; l++,m++) if (!*m) break; return (l); } BPTR bstr(s) str s; { int l = blen(s); long al = (l + 8) & ~3; str b; if (!(b = AllocPZ(al))) return (null); *(long *) b = al; b[4] = l; strncpy(b + 5, s, l); return (((long) b + 4) >> 2); } void freebeast(b) BPTR b; { long *p = bip(long, b); FreeMem(p - 1, p[-1]); } BPTR CopyWBPath() { struct Process *wb = (adr) FindTask("Workbench"); SCLI *wbclap; BPTR *wext, *mext, *lastmext, newpath = null; lastmext = &newpath; if (!wb) return (null); if (!(wbclap = gbip(wb->pr_CLI))) return (null); for (wext = gbip(wbclap->cli_CommandDir); wext; wext = gbip(*wext)) { if (!(mext = AllocP(2 * sizeof(BPTR)))) break; *lastmext = (long) mext >> 2; lastmext = mext; mext[1] = DupLock(wext[1]); mext[0] = null; } return (newpath); } void FakeCLI() { SCLI *clap; if (!(clap = NewPZ(SCLI))) /* clear|public */ return; baloney = true; me->pr_CLI = (long) clap >> 2; clap->cli_SetName = bstr("SYS:"); clap->cli_Prompt = bstr("%N> "); clap->cli_DefaultStack = 1000L; CurrentDir(RLock("SYS:")); /* old CD was zero */ clap->cli_CommandDir = CopyWBPath(); } void NukePath(path) BPTR path; { BPTR *next, *p; for (p = gbip(path); p; p = next) { next = gbip(p[0]); if (p[1]) UnLock(p[1]); FreeMem(p, 2L * sizeof(BPTR)); } } void StopFakery() { BPTR cd = CurrentDir(null); SCLI *clap = gbip(me->pr_CLI); if (cd) UnLock(cd); if (!clap) return; freebeast(clap->cli_SetName); freebeast(clap->cli_Prompt); NukePath(clap->cli_CommandDir); me->pr_CLI = null; Free(SCLI, clap); } void wandle() { struct DiskObject *bob; str toop; register char c; if (!(IconBase = OpenLibrary("icon.library", 0L))) return; CurrentDir(WBenchMsg->sm_ArgList->wa_Lock); if (bob = GetDiskObject(WBenchMsg->sm_ArgList->wa_Name)) { if (toop = FindToolType(bob->do_ToolTypes, "OPTION")) for (c = tolower(*toop); c; c = tolower(*++toop)) { if (c == 'v') unshelled = true; else if (c == 'g') greenify = true; else if (c == 'i') lace = true; } FreeDiskObject(bob); } CurrentDir(null); CloseLibrary(IconBase); IconBase = null; } int word, chair, ac; str *av; char nerg() { #ifdef AZTEC_C if (((str) av)[chair]) return (((str) av)[chair++]); else return (0); #else if (av[word][chair]) return (av[word][chair++]); else if (av[++word]) return (av[word][chair = 0]); else return (0); #endif } void handle(argc, argv) int argc; str argv[]; { char c; bool kelp = false; ac = argc; av = argv; word = 1; chair = 0; lace = false; for (c = tolower(nerg()); c; c = tolower(nerg())) { if (c == 'v') unshelled = true; if (c == 'i') lace = true; if (c == 'g') greenify = true; if (c == '?' | c == 'h') kelp = true; } if (kelp) { spew( "\nCLImax by Paul Kienitz -- usage:\n\n" " Run > nil: CLImax [V] [I] [G]\n\n" "Spaces and letter cases and order of appearence never matter.\n"); spew( "V (vanilla) means start with s:CLI-Startup instead of s:Shell-Startup.\n" "I means make an interlace screen.\n"); spew( "G means use black-on-greenish (good for interlace) instead of\n" " the Workbench colors (maybe someday there'll be an RGB option).\n" "? or H means show this message.\n\n"); spew( "For Workbench, use a tooltype OPTION= followed by V, I, and/or G.\n\n"); closestuff(); exit(0); } } main(argc, argv) int argc; stray argv; { char boof[50]; str command; BPTR window_handle, L, Seg = 1; #ifndef AZTEC_C me = (adr) FindTask(null); === do something to set WBenchMsg === #endif if (WBenchMsg) wandle(); else handle(argc, argv); /* spew("Maximum CLI for you, from Paul Kienitz. Public Domain.\n"); */ openstuff(); wopter = me->pr_WindowPtr; me->pr_WindowPtr = -1L; #ifdef EXPERIMENTAL window_handle = OOpen("nil:"); if (!unshelled && (L = RLock("C:NewShell"))) { strcpy(boof, "c:newshell >nil: "); UnLock(L); } else if (L = RLock("C:NewCLI")) { strcpy(boof, "c:newcli >nil: "); UnLock(L); } speck(boof, win); me->pr_WindowPtr = (adr) win; /* setting gets passed to child cli */ /* if (Seg = LoadSeg("L:CLImax-Cleanup")) */ if (!Execute(boof, null, window_handle)) spew("Can't start CLI. ConMan not present?\n"); else { win = null; scr = null; } /* prevent closure */ /* else spew("Can't find L:CliMAX-Cleanup.\n"); */ #else if (!unshelled && (L = RLock("S:Shell-Startup"))) { command = "Execute S:Shell-Startup"; UnLock(L); } else if (L = RLock("S:CLI-Startup")) { command = "Execute S:CLI-Startup"; UnLock(L); } else command = ""; if (!me->pr_CLI) FakeCLI(); boof[0] = 0; speck(boof, win); window_handle = NOpen(boof); me->pr_WindowPtr = (adr) win; /* setting gets passed to child cli */ if (window_handle) { Execute(command, window_handle, null); /* wait for other things using window_handle to stop! */ Close(window_handle); } else spew("Can't open the CON: for the window. ConMan absent?\n"); if (baloney) StopFakery(); #endif closestuff(); } speck(b, a) str b; long a; { short hid, nyb, blem; strcat(b, "CON:Wxxxxxx"); /* uses ConMan */ blem = strlen(b) - 1; for (hid = 0; hid <= 5; hid++) { nyb = (a >> (4*hid)) & 15; b[blem - hid] = (nyb >= 10 ? (char) nyb + 'A' - 10 : (char) nyb + '0'); } } /* reduce size by a few K: */ #ifdef AZTEC_C char arg[256]; void _cli_parse(alen, aptr) long alen; str aptr; { strncpy(arg, aptr, (int) alen); arg[alen - 1] = 0; } _main(alen, aptr) long alen; str aptr; /* simplified startup code */ { me = (struct Process *) FindTask(null); if (me->pr_CLI) { _cli_parse(alen, aptr); WBenchMsg = null; } else { WaitPort(&me->pr_MsgPort); WBenchMsg = (adr) GetMsg(&me->pr_MsgPort); } main(1, arg); exit(0); } exit(code) int code; { if (WBenchMsg) { Forbid(); ReplyMsg(WBenchMsg); } Exit((long) code); } #endif