#ifdef This_Is_A_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 (3.6) or -BD (5.0) stack checking option. There are some provisions for compiling it without Aztec, but they are UNTESTED AND INCOMPLETE. Last revision date: 12/31/90. Use the +A flag on the Aztec linker. Improvements needed: => o Make it work without ConMan. o Make it Pure someday. o B option for inactive window on screen opened in back? o Cn xxx option to set RGB colors. o Mn option to set overscanmargin? o Someday, P option for "productivity mode" screen. o Dn option for screen depth. o hot key to bring to front and activate? Make your own, I don't need one. o Invisible screen gadgets? Nah, too difficult to make text show through. #endif #include #include #include #include #include #include #include #define GREENISHNESS {0x484, 0x000, 0x0b0, 0xcc0} #define DEFAULTISHNESS {0x05a, 0xfff, 0x002, 0xf80} #define SCLI struct CommandLineInterface typedef struct { adr ibase, gbase, dosbase; struct TextFont *fawnt; struct Screen *scr; struct Window *win; BPTR wandle, ceedee; } stuffy; adr IntuitionBase, DOSBase, IconBase, DiskfontBase; struct GfxBase *GfxBase; struct WBStartup *WBenchMsg; struct Process *me; struct Preferences *prufs; #define PREFSIZE (long) ( (str) &prufs->color3 + 2 - (str) prufs) SCLI *fakli = null; str prompt, setname; str command, processname; BPTR oriout, fakeseglist; bool lace = false, unshelled = false, greenify = false, frum = false, newfont = false, closeori = false;; str fontname = "topaz.font"; /* no other choices for now */ long fontsize = 11; stuffy *stuff; struct NewScreen scrdef = { 0, 0, 640, 204, /* Width and Height will be set later */ 2, /* 4 colors */ 0, 0, /* detail pen = background so no white stripe at top */ HIRES, /* inventor of root beer */ CUSTOMSCREEN, null, null, /* title (won't actually show) filled in later */ null, null }; struct NewWindow windef = { 0, 4, 640, 200, /* TopEdge and Height will be set later */ 0, 1, 0L, ACTIVATE | BACKDROP | BORDERLESS, null, null, null, /* no special gadget or checkmark, no title */ null, /* screen pointer; will get set later */ null, /* no custom bitmap */ 0, 0, 0, 0, /* ignored */ CUSTOMSCREEN }; /* these are all in bud.a */ extern void beginning(), ending(), CloseStuff(); extern short StuffOffs, CommandOffs, NameOffs, FakeOffs; /* for debugging: #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 exit(); void spew(s) str s; { register long l = strlen(s); if (!oriout && !closeori) { closeori = true; oriout = OOpen("CON:60/40/450/80/ CLImax error: "); } if (oriout) Write(oriout, s, l); } void Die() { BPTR *p, *pp; UnLoadSeg(fakeseglist); if (stuff->ceedee) UnLock(stuff->ceedee); if (fakli && fakli->cli_CommandDir) { p = gbip(fakli->cli_CommandDir); while (p) { UnLock(p[1]); pp = gbip(*p); FreeMem(p, 8); p = pp; } } CloseStuff(stuff); exit(10); } void OpenStuff () { ushort *wbcolor, tallth; static ushort lacecolor[4] = GREENISHNESS, unlacecolor[4] = DEFAULTISHNESS; long collor; /* that's how Joan spelled it once */ struct ViewPort *vp; short margin = (lace ? 10 : 4); tallth = (GfxBase->NormalDisplayRows << lace) - margin; if (tallth < (200 << lace)) tallth = 200 << lace; else if (tallth > (246 << lace) && tallth < (256 << lace)) tallth = 256 << lace; if (lace) scrdef.ViewModes = HIRES | LACE; windef.TopEdge = margin; windef.Height = tallth; scrdef.Height = tallth + margin; scrdef.Width = windef.Width = GfxBase->NormalDisplayColumns; scrdef.DefaultTitle = (ubyte *) processname; if (!(stuff->scr = OpenScreen(&scrdef))) { spew("\nCLImax: can't open screen.\n"); Die(); } windef.Screen = stuff->scr; if (!(stuff->win = OpenWindow(&windef))) { spew("\nCLImax: can't open backdrop window.\n"); Die(); } ShowTitle(stuff->scr, FALSE); vp = &stuff->scr->ViewPort; prufs = null; if (greenify) wbcolor = lacecolor; else if (prufs = Alloc(PREFSIZE)) { GetPrefs(prufs, PREFSIZE); wbcolor = &prufs->color0; } else wbcolor = unlacecolor; for (collor = 0; collor <= 3; collor++, wbcolor++) SetRGB4(vp, collor, (*wbcolor >> 8) & 15L, (*wbcolor >> 4) & 15L, *wbcolor & 15L); if (prufs) FreeMem(prufs, PREFSIZE); } BPTR CopyPath(tass) str tass; { struct Process *wb = (adr) FindTask(tass); SCLI *wbclap; BPTR *wext, *mext, *lastmext, newpath = 0; lastmext = &newpath; if (!wb) return 0; if (!(wbclap = gbip(wb->pr_CLI))) return 0; 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] = 0; } return (newpath); } void bcpy(dest, src, limit) ubyte *dest, *src; short limit; { register ushort l = *(src++); if (l >= limit) l = limit - 1; *(dest++) = l; while (l > 0) { *(dest++) = *(src++); l--; } } void FakeCLI() { if (me->pr_CLI) { SCLI *mec = gbip(me->pr_CLI); fakli->cli_DefaultStack = mec->cli_DefaultStack; /* NewCLI does this */ bcpy(prompt, gbip(mec->cli_Prompt), 64); bcpy(setname, gbip(mec->cli_SetName), 88); /* I just happen to know that the CLI allocates 64 bytes for the prompt and 88 bytes for the setname. On its stack. */ fakli->cli_CommandDir = CopyPath(null); } else { register BPTR p; fakli->cli_DefaultStack = 1000L; if (!(p = CopyPath("Workbench"))) if (!(p = CopyPath("Initial CLI"))) if (!(p = CopyPath("AmigaShell"))) if (!(p = CopyPath("New CLI"))) p = CopyPath("Background CLI"); fakli->cli_CommandDir = p; /* Why, you ask, am I including code that assumes the CLImax process has been launched neither from a CLI nor from Workbench? well, I use MyMenu. and sometimes the path will get set elsewhere after workbench is already under way so it doesn't know it. besides, I just had this lying around in FixCLI. */ } fakli->cli_Prompt = (long) prompt >> 2; fakli->cli_SetName = (long) setname >> 2; /* if (!stuff->ceedee) stuff->ceedee = RLock("SYS:"); */ } void DooFont() { struct TextAttr f; f.ta_Name = (adr) fontname; f.ta_YSize = fontsize; f.ta_Style = f.ta_Flags = 0; stuff->fawnt = OpenFont(&f); if (stuff->fawnt && fontsize != stuff->fawnt->tf_YSize) { CloseFont(stuff->fawnt); stuff->fawnt = null; } if (!stuff->fawnt) if (DiskfontBase = (adr) OpenLibrary("diskfont.library", 0L)) { stuff->fawnt = OpenDiskFont(&f); CloseLibrary(DiskfontBase); } if (stuff->fawnt) SetFont(stuff->win->RPort, stuff->fawnt); } 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; else if (c == 'e') newfont = true; } if (toop = FindToolType(bob->do_ToolTypes, "CD")) { while (*toop && *toop <= ' ') toop++; if (stuff->ceedee = RLock(toop)) { register int l = strlen(toop); if (l >= 88) l = 87; *setname = l; strncpy(setname + 1, toop, l); } } if (toop = FindToolType(bob->do_ToolTypes, "FROM")) { while (*toop && *toop <= ' ') toop++; if (*toop) { strcpy(command, "execute "); strcpy(command + 8, toop); } else *command = 0; frum = true; } FreeDiskObject(bob); } CurrentDir(stuff->ceedee); CloseLibrary(IconBase); IconBase = null; } int word, chair, ac; stray av; char nerg() { if (word > ac) return (0); else if (av[word][chair]) return (tolower(av[word][chair++])); else if (++word <= ac) return (tolower(av[word][chair = 0])); else return (0); } 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 = nerg(); c; c = nerg()) { if (c == 'v') unshelled = true; else if (c == 'i') lace = true; else if (c == 'g') greenify = true; else if (c == 'e') newfont = true; else if (c == '?' || c == 'h') kelp = true; else if (c == 'f' && nerg() == 'r' && nerg() == 'o' && nerg() == 'm') { for (c = nerg(); c && c <= ' '; c = nerg()) ; frum = true; if (!c) *command = 0; else { register str cc = command + 8; strcpy(command, "execute "); while (c >= ' ') { *(cc++) = c; c = nerg(); } } } } if (kelp) { spew( "\nCLImax by Paul Kienitz -- in the public domain -- usage:\n\n" " CLIMAX [ V ] [ I ] [ G ] [ E ] [ FROM [ scriptfile ] ]\n\n" "The letters V, I, G, and E can be in any order, case, or spacing.\n" " V (vanilla) means use s:CLI-Startup instead of s:Shell-Startup.\n" " I means make an interlace screen.\n" " G means use black-on-greenish (good for interlace) instead of\n" " the Workbench colors (maybe someday there'll be an RGB option).\n" " E means use the topaz 11 font instead of the system default font.\n" " FROM scriptfile means execute the named file (instead of S:Shell-Startup)\n" " before giving the first prompt. Must be the LAST option on the line.\n" " Use FROM with nothing after it to use no script.\n" "? or H means show this message.\n\n" "For Workbench, use a tooltype OPTION= followed by V, I, G, and/or E.\n" "Also you can use tooltype CD= to specify its current directory.\n" "And use FROM= to specify a startup scriptfile.\n\n"); Die(); } stuff->ceedee = DupLock(me->pr_CurrentDir); } void Bud() /* grow a "bud" which can detach as a child process */ { long tize = ((str) &ending - (str) &beginning) + 8; register str taskspace = AllocP(tize); if (!taskspace || !IntuitionBase || !GfxBase) { spew("\nGaaah! Not enough memory for CLImax!\n"); exit(20); } CopyMemQuick((str) &beginning, taskspace + 8, tize - 8); *((long *) taskspace) = (tize + 3) & ~3; ((long *) taskspace)[1] = 0; /* fakeseglist next bptr */ fakeseglist = (((long) taskspace) >> 2) + 1; taskspace += 8; command = (adr) (taskspace + CommandOffs); processname = (adr) (taskspace + NameOffs); fakli = (adr) (taskspace + FakeOffs); prompt = (str) fakli + sizeof(SCLI); setname = prompt + 64; stuff = (adr) (taskspace + StuffOffs); stuff->wandle = stuff->ceedee = 0; stuff->scr = (adr) stuff->win = stuff->fawnt = null; stuff->ibase = IntuitionBase; stuff->gbase = GfxBase; stuff->dosbase = DOSBase; } void speck(b, a) str b; long a; { short hid, nyb, end; strcat(b, "CON:Wxxxxxx"); /* uses ConMan */ end = strlen(b) - 1; for (hid = 0; hid <= 5; hid++) { nyb = (a >> (4*hid)) & 15; b[end - hid] = (nyb >= 10 ? (char) nyb + 'A' - 10 : (char) nyb + '0'); } } void main(argc, argv) int argc; stray argv; { char boof[50]; BPTR L, Seg = 1; APTR mywptr; oriout = Output(); #ifndef AZTEC_C me = ThisProcess(); === do something to get WBenchMsg === #endif IntuitionBase = (adr) OpenLibrary ("intuition.library", 0L); GfxBase = (adr) OpenLibrary ("graphics.library", 0L); Bud(); if (WBenchMsg) wandle(); else handle(argc, argv); OpenStuff(); mywptr = me->pr_WindowPtr; me->pr_WindowPtr = (APTR) -1L; if (!frum) if (!unshelled && (L = RLock("s:shell-startup"))) { strcpy(command, "execute s:shell-startup"); UnLock(L); } else if (L = RLock("s:cli-startup")) { strcpy(command, "execute s:cli-startup"); UnLock(L); } else *command = 0; me->pr_WindowPtr = mywptr; FakeCLI(); boof[0] = 0; speck(boof, stuff->win); if (newfont) DooFont(); if (stuff->wandle = OOpen(boof)) { Write(stuff->wandle, "CLImax by Paul Kienitz maximizes your CLI.\n", 43L); CreateProc(processname, 0L, fakeseglist, 2000L); } else { spew("\nCLImax can't open the CON: for the window.\n" "If you do not have ConMan installed, you\n" "have to do that first!\n"); Die(); } } /* reduce size by a few K: */ #ifdef AZTEC_C char arg[256]; str argp[3] = { "CLImax", arg, null }; void _main(alen, aptr) long alen; str aptr; /* simplified startup code */ { int al = alen; me = ThisProcess(); if (me->pr_CLI) { if (al > 255) al = 255; strncpy(arg, aptr, al); arg[al - 1] = 0; WBenchMsg = null; } else { WaitPort(&me->pr_MsgPort); WBenchMsg = (adr) GetMsg(&me->pr_MsgPort); } main(1, argp); /* pack all args into argv[1] */ exit(0); } void exit(code) int code; { char c; if (oriout && closeori) { spew("\n - press return - "); Read(oriout, &c, 1L); Close(oriout); } if (WBenchMsg) { Forbid(); ReplyMsg((struct Message *) WBenchMsg); } Exit((long) code); } #endif