/* Modified to work with Manx 3.6a; probably won't work with Lattice. Based on: */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* |_o_o|\\ Copyright (c) 1986 The Software Distillery. All Rights Reserved */ /* |. o.| || This program may not be distributed without the permission of */ /* | . | || the authors. */ /* | o | || Dave Baker Ed Burnette Stan Chow Jay Denebeim */ /* | . |// Gordon Keener Jack Rouse John Toebes Doug Walker */ /* ====== BBS:(919)-471-6436 VOICE:(919)-469-4210 */ /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ /* * VERY loosely based on the input.device example by Rob Peck, 12/1/85 */ /* * * * * * * * * INCLUDE FILES * * * * * * * * * * * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * I need this kludge because of a bug in functions.h. */ #define ConsoleDevice IDontReallyExist #include #undef ConsoleDevice #include /* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */ #define PORTNAME "Mackie.port" #define TIMEINTERVAL 1L /* in seconds */ #define DEFTIME 300 /* two minute timeout */ #define MAXCMD 200 #define MAXPENDINGSYSTEM 20 #define DEFKEY 0x45 #define DEFCMD "NEWCLI >NIL: ie_NextEvent) { if ((ep->ie_Class == IECLASS_RAWKEY) && (((ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) && (ep->ie_Code == gptr->key)) || (!gptr->helppressed && ep->ie_Code == 0x5f) || (gptr->helppressed && (ep->ie_Code & 0x80) == 0 && /* * All the qualifiers have code = 0x6?; dangerous to take advantage * of? */ (ep->ie_Code & 0xf0) != 0x60 && gptr->frontkey[gptr->frontptr] == 0 && (gptr->helppressed = (keytoasc[ep->ie_Code] != '.'))))) { if ((ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) && (ep->ie_Code == gptr->key)) key = -1 ; else if (gptr->helppressed) { gptr->frontkey[gptr->frontptr] = key = ep->ie_Code ; gptr->frontqual[gptr->frontptr] = ep->ie_Qualifier ; gptr->frontptr++ ; if (gptr->frontptr >= MAXPENDINGSYSTEM) gptr->frontptr = 0 ; gptr->helppressed = 0 ; } else { gptr->helppressed = 1 ; key = 0 ; } /* we can handle this event so take it off the chain */ if (laste == NULL) ev = ep->ie_NextEvent; else laste->ie_NextEvent = ep->ie_NextEvent; /* now tell him to create the new cli */ if (key == -1) Signal(gptr->buddy, gptr->creatclisig); else if (key > 0) Signal(gptr->buddy, gptr->frontsig); } else laste = ep; if (ep->ie_Class != IECLASS_TIMER) { gptr->noevents = 0; if (gptr->blankscreen != NULL) Signal(gptr->buddy, gptr->unblanksig); } } /* pass on the pointer to the event */ return(ev); } /* * * * * * * * * * * EXTERNAL ROUTINES * * * * * * * * * */ struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; struct DosLibrary *DosBase; struct NewScreen NewScreen = { 0, 0, 320, 30, 1, 0, 1, NULL, CUSTOMSCREEN, NULL, NULL, NULL, NULL }; extern struct MsgPort *CreatePort(); struct IOStdReq *CreateIOReq(); void DeleteIOReq(); /************************************************************************/ /* Queue a timer to go off in a given number of seconds */ /************************************************************************/ void QueueTimer(tr,seconds) struct timerequest *tr; ULONG seconds; { tr->tr_node.io_Command = TR_ADDREQUEST; /* add a new timer request */ tr->tr_time.tv_secs = seconds; /* seconds */ tr->tr_time.tv_micro = 0; SendIO( (struct IORequest *)tr ); } /************************************************************************/ /* the main program to do the popcli stuff */ /************************************************************************/ GLOBAL_DATA global; main(argc, argv) int argc ; char *argv[] ; { struct MsgPort *port; int stay = 0; struct OURMSG *msg; int i ; char cmdstr[MAXCMD]; short key, timeout; struct FileHandle *nullfh = NULL ; ULONG sig, timersig; struct timerequest *timerreq; struct MsgPort *timerport; struct MsgPort *inputDevPort; struct IOStdReq *inputRequestBlock; struct Interrupt handlerStuff; char *cmd ; int draw = 0 ; int nextfront = 0 ; SetTaskPri(FindTask(0L), 20L) ; global.creatsignum = -1; global.blanksignum = -1; global.replysignum = -1; global.frontsignum = -1; global.blankscreen = NULL; global.key = DEFKEY ; global.draw = 1 ; timerreq = NULL; timerport = NULL; inputDevPort = NULL; inputRequestBlock = NULL; /* now see if we are already installed */ if ((port = FindPort(PORTNAME)) == NULL) { stay = 1; /* remember to hang around when we are done */ /* not installed, we need to install our own port */ if ((port = CreatePort(PORTNAME,0L)) == NULL) goto abort; } /* * If we are hanging around, initialize our keyboard translation table. * If we have difficulty, exit angry. */ if (stay) if (initkeytoasc()) goto abort ; /* now send the parameter to the waiting program */ if ((msg = (struct OURMSG *) AllocMem((long)sizeof(struct OURMSG), MEMF_CLEAR|MEMF_PUBLIC)) == NULL) goto abort; if ((infoptr = (struct InfoData *) AllocMem((long)sizeof(struct InfoData), MEMF_CLEAR)) == NULL) goto abort ; /* fill in the message information */ msg->msgpart.mn_Length = sizeof(struct OURMSG); strcpy(cmdstr, DEFCMD); timeout = 0 ; key = 0 ; msg->cmd[0] = 0; /* if we were run from CLI then output our banner and process parameters */ if (argc > 0) { /* display our copyright */ if (stay) puts("Mackie 1.1 by Tomas Rokicki - Copyright \xa9 1987, 1988 Radical Eye Software") ; if (argc == 1) puts("Usage: Mackie [-q] [-l] [-b] [-f startup] [time] [\"command\"]") ; argc-- ; argv++ ; while (argc > 0) { cmd = argv[0] ; if (*cmd == '-') { cmd++ ; switch (*cmd) { case 'q' : case 'Q' : key = -1 ; puts("\x9B1mMackie\x9B0m Terminating") ; break ; case 'l' : case 'L' : draw = 1 ; break ; case 'b' : case 'B' : draw = -1 ; break ; case 'f' : case 'F' : if (cmd[1]) startupfile = cmd + 1 ; else { argv++ ; argc-- ; startupfile = argv[0] ; } default : puts("Error in parameter!") ; } } else if ('0' <= *cmd && *cmd <= '9') { timeout = 0; while ((*cmd >= '0') && (*cmd <= '9')) timeout = (timeout*10) + *cmd++ - '0'; if (timeout <= 0) timeout = DEFTIME; } else { strcpy(msg->cmd, cmd) ; } argc-- ; argv++ ; } } msg->interval = timeout; msg->key = key; msg->draw = draw ; if (stay) processstartup(startupfile, msg) ; if (draw) global.draw = draw ; PutMsg(port,(struct Message *)msg); if (!stay) goto abort; if (timeout == 0) timeout = DEFTIME ; global.blankscreen = NULL; global.buddy = FindTask(0L); global.noevents = 0; nullfh = Open("NIL:", MODE_NEWFILE); if (((inputDevPort = CreatePort(0L,0L)) == NULL) || ((inputRequestBlock = CreateIOReq(inputDevPort, (long)sizeof(struct IOStdReq))) == NULL) || ((timerport = CreatePort(0L,0L)) == NULL) || ((timerreq = (struct timerequest *) CreateIOReq(timerport, (long)sizeof(struct timerequest))) == NULL) || ((global.creatsignum = AllocSignal(-1L)) == -1) || ((global.blanksignum = AllocSignal(-1L)) == -1) || ((global.replysignum = AllocSignal(-1L)) == -1) || ((global.frontsignum = AllocSignal(-1L)) == -1) || ((GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L)) == NULL) || ((IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 0L)) == NULL) || OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)timerreq, 0L) || OpenDevice("input.device",0L,(struct IORequest *)inputRequestBlock,0L)) goto abort; handlerStuff.is_Data = (APTR)&global; handlerStuff.is_Code = HandlerInterface; handlerStuff.is_Node.ln_Pri = 51; timersig = (1L << timerport->mp_SigBit); global.creatclisig = 1L << global.creatsignum; global.unblanksig = 1L << global.blanksignum; global.frontsig = 1L << global.frontsignum; inputRequestBlock->io_Command = IND_ADDHANDLER; inputRequestBlock->io_Data = (APTR)&handlerStuff; DoIO((struct IORequest *)inputRequestBlock); QueueTimer(timerreq, TIMEINTERVAL); for(;;) { /* FOREVER */ sig = Wait( global.creatclisig | global.unblanksig | timersig | global.frontsig); /* see if they asked us to change the interval */ if ((msg = (struct OURMSG *)GetMsg(port)) != NULL) { if (msg->cmd[0]) strcpy(cmdstr, msg->cmd); if (msg->key) global.key = msg->key; if (msg->interval) timeout = msg->interval; if (msg->draw) global.draw = msg->draw ; FreeMem((char *)msg, (long)msg->msgpart.mn_Length); if (msg->key == -1) goto abort; } if ((sig & global.unblanksig) && global.blankscreen) screenunblank() ; if (sig & global.creatclisig) { WBenchToFront(); (void)Execute(cmdstr,nullfh,nullfh); } if (sig & global.frontsig) { while (i=global.frontkey[nextfront]) { windowtofront(keytoasc[i], global.frontqual[nextfront]) ; global.frontkey[nextfront] = 0 ; nextfront++ ; if (nextfront >= MAXPENDINGSYSTEM) nextfront = 0 ; } } if (sig & timersig) { /* get rid of the message */ (void)GetMsg(timerport); QueueTimer(timerreq, TIMEINTERVAL); if (task) SetTaskPri(task, 10L) ; if ((global.noevents++ >= timeout) && (global.blankscreen == NULL)) blankscreen() ; } } abort: if (infoptr) { FreeMem(infoptr, (long)sizeof(struct InfoData)) ; infoptr = NULL ; } if (timerreq != NULL) { if (timerreq->tr_node.io_Device != NULL) CloseDevice((struct IORequest *)timerreq); DeleteIOReq((struct IOStdReq *)timerreq); } if (inputRequestBlock != NULL) { if (inputRequestBlock->io_Device != NULL) { inputRequestBlock->io_Command = IND_REMHANDLER; inputRequestBlock->io_Data = (APTR)&handlerStuff; DoIO((struct IORequest *)inputRequestBlock); CloseDevice((struct IORequest *)inputRequestBlock); } DeleteIOReq(inputRequestBlock); } screenunblank() ; if (timerport != NULL) DeletePort(timerport); if (global.creatsignum != -1) FreeSignal(global.creatsignum); if (global.blanksignum != -1) FreeSignal(global.blanksignum); if (global.replysignum != -1) FreeSignal(global.replysignum); if (global.frontsignum != -1) FreeSignal(global.frontsignum); if (IntuitionBase != NULL) CloseLibrary((struct Library *)IntuitionBase); if (GfxBase != NULL) CloseLibrary((struct Library *)GfxBase); if (inputDevPort != NULL) DeletePort(inputDevPort); if (stay && (port != NULL)) DeletePort(port); { struct hotkey *hk ; while (hotkeys) { hk = hotkeys->next ; FreeMem(hotkeys, (long)hotkeys->structlen) ; hotkeys = hk ; } } if (nullfh) Close(nullfh); SetTaskPri(FindTask(0L), 0L) ; } struct IOStdReq * CreateIOReq(port, size) struct MsgPort *port; long size; { struct IOStdReq *ioReq; if ((ioReq = (struct IOStdReq *) AllocMem(size, MEMF_CLEAR | MEMF_PUBLIC)) != NULL) { ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE; ioReq->io_Message.mn_Node.ln_Pri = 0; ioReq->io_Message.mn_Length = size; ioReq->io_Message.mn_ReplyPort = port; } return(ioReq); } void DeleteIOReq(ioReq) struct IOStdReq *ioReq; { ioReq->io_Message.mn_Node.ln_Type = 0xff; ioReq->io_Device = (struct Device *) -1; ioReq->io_Unit = (struct Unit *) -1; FreeMem( (char *)ioReq, (long)ioReq->io_Message.mn_Length); } /* * All of this stuff down here was written by Tomas Rokicki. * (C) Copyright 1987, 1988, Radical Eye Software. */ #include "graphics/gfxbase.h" /* * The maximum number of lines on the screen at once. */ #define MAXLINES (100) /* * The external variables we access. */ struct RastPort *rastport ; short screenheight, screenwidth ; /* * Some locals to this file. */ static struct NewScreen newscreen = { 0, 0, 640, 400, 1, 0, 1, HIRES | LACE | SCREENQUIET, CUSTOMSCREEN, NULL, NULL, NULL, NULL } ; /* * This routine opens a screen and fires off the task if apropriate. */ void taskrout() ; blankscreen() { screenheight = 2 * GfxBase->NormalDisplayRows ; screenwidth = GfxBase->NormalDisplayColumns ; newscreen.Height = screenheight ; newscreen.Width = screenwidth ; if (global.draw == -1 || AvailMem(MEMF_CHIP) < 70000L || (global.blankscreen = OpenScreen(&newscreen)) == NULL) { if ((global.blankscreen = OpenScreen(&NewScreen)) != NULL) { SetRGB4(&(global.blankscreen->ViewPort), 0L, 0L, 0L, 0L); OFF_DISPLAY ; } } else { if (global.blankscreen == NULL && (global.blankscreen = OpenScreen(&newscreen))==NULL) return ; /* * Turning off the sprites is a little bit tricky. A simple OFF_SPRITE * will continue to display the data in the current sprite registers. * This happens most often with the cursor. To fix, we simply clear out * the sprite control registers after turning the sprites off. This * might break all of the sprites when the system comes back up . . . */ OFF_SPRITE ; custom.spr[0].ctl = 0 ; custom.spr[1].ctl = 0 ; custom.spr[2].ctl = 0 ; custom.spr[3].ctl = 0 ; custom.spr[4].ctl = 0 ; custom.spr[5].ctl = 0 ; custom.spr[6].ctl = 0 ; custom.spr[7].ctl = 0 ; SetRGB4(&(global.blankscreen->ViewPort), 0L, 0L, 0L, 0L) ; rastport = &(global.blankscreen->RastPort) ; SetAPen(rastport, 0L) ; Forbid() ; RectFill(rastport, 0L, 0L, (long)screenwidth-1, 30L) ; Permit() ; SetAPen(rastport, 1L) ; task = (struct Task *)AllocMem((long)sizeof(struct Task), MEMF_CLEAR | MEMF_PUBLIC) ; if (task != NULL) { task->tc_Node.ln_Pri = 10 ; task->tc_Node.ln_Type = NT_TASK ; task->tc_Node.ln_Name = "ri.Lines" ; task->tc_SPLower = (APTR)stackmem ; task->tc_SPUpper = task->tc_SPReg = (APTR)(stackmem + STACKSIZE/4 - 8) ; AddTask(task, taskrout, 0L) ; } } } /* * Unblank the screen. We kill the task with the standard ^C kill signal. */ screenunblank() { if (task != NULL) { Signal(task, 1L << SIGBREAKB_CTRL_C) ; SetTaskPri(task, 11L) ; Wait(1L << global.replysignum) ; RemTask(task); FreeMem(task, (long)sizeof(struct Task)) ; task = NULL ; } if (global.blankscreen != NULL) { CloseScreen(global.blankscreen); global.blankscreen = NULL ; ON_DISPLAY ; ON_SPRITE ; } } /* * This routine returns a random value from 0 to n-1. */ int randm(i) int i ; { static long seed ; long rval ; if (seed == 0) seed = 323214521 + global.blankscreen->MouseX + global.blankscreen->MouseY ; seed = seed * 123213 + 121 ; rval = (seed >> 5) & 65535 ; return ((i * rval) >> 16) ; } /* * This routine sets x and y values to a random number. */ static long x, y ; randomxy() { x = randm(screenwidth) ; y = randm(screenheight) ; } /* * Main routines are always fun. */ short x1store[MAXLINES], y1store[MAXLINES] ; short x2store[MAXLINES], y2store[MAXLINES] ; short ptr ; short dx1, dy1, dx2, dy2 ; short ox1, oy1, ox2, oy2 ; short nx1, ny1, nx2, ny2 ; short dr, dg, db ; short or, og, ob ; short nr, ng, nb ; /* * Initialize things for the first lines. */ startlines() { ptr = 0 ; if (dx1 == 0) { ox1 = randm(screenwidth) ; ox2 = randm(screenwidth) ; oy1 = randm(screenheight) ; oy2 = randm(screenheight) ; dx1 = 3 ; dx2 = 4 ; dy1 = 1 ; dy2 = 6 ; nr = 53 ; ng = 33 ; nb = 35 ; dr = -3 ; dg = 5 ; db = 7 ; } SetRGB4(&(global.blankscreen->ViewPort), 0L, 0L, 0L, 0L) ; SetRGB4(&(global.blankscreen->ViewPort), 1L, (long)(nr >> 3), (long)(ng >> 3), (long)(nb >> 3)) ; } /* * Advance the number by the delta, and check the boundaries. */ adv(o, d, n, w) short *o, *d, *n ; short w ; { *n = *o + *d ; if (*n < 0) { *n = 0 ; *d = randm(6) + 1 ; } else if (*n >= w) { *n = w - 1 ; *d = - randm(6) - 1 ; } } /* * Advance the two points which make up the lines. */ advancelines() { adv(&ox1, &dx1, &nx1, screenwidth) ; adv(&ox2, &dx2, &nx2, screenwidth) ; adv(&oy1, &dy1, &ny1, screenheight) ; adv(&oy2, &dy2, &ny2, screenheight) ; } /* * Draw a new set of lines. */ drawnew() { x1store[ptr] = ox1 = nx1 ; x2store[ptr] = ox2 = nx2 ; y1store[ptr] = oy1 = ny1 ; y2store[ptr] = oy2 = ny2 ; Move(rastport, (long)ox1, (long)oy1) ; Draw(rastport, (long)ox2, (long)oy2) ; Draw(rastport, (long)(screenwidth-ox1-1), (long)(screenheight-oy1-1)) ; Draw(rastport, (long)(screenwidth-ox2-1), (long)(screenheight-oy2-1)) ; Draw(rastport, (long)ox1, (long)oy1) ; ptr++ ; if (ptr == MAXLINES) ptr = 0 ; } /* * Erase the old line. */ eraseold() { short oldpen ; oldpen = rastport->FgPen ; SetAPen(rastport, 0L) ; Move(rastport, (long)x1store[ptr], (long)y1store[ptr]) ; Draw(rastport, (long)x2store[ptr], (long)y2store[ptr]) ; Draw(rastport, (long)(screenwidth-x1store[ptr]-1), (long)(screenheight-y1store[ptr]-1)) ; Draw(rastport, (long)(screenwidth-x2store[ptr]-1), (long)(screenheight-y2store[ptr]-1)) ; Draw(rastport, (long)x1store[ptr], (long)y1store[ptr]) ; SetAPen(rastport, (long)oldpen) ; } /* * This routine mucks with the colors. */ colors() { or = nr ; og = ng ; ob = nb ; adv(&or, &dr, &nr, 128) ; adv(&og, &dg, &ng, 128) ; adv(&ob, &db, &nb, 128) ; SetRGB4(&(global.blankscreen->ViewPort), 1L, (long)(nr >> 3), (long)(ng >> 3), (long)(nb >> 3)) ; } /* * Our actual task, in an infinite loop. */ void taskrout() { long i ; struct Task *task ; geta4() ; task = FindTask(0L) ; startlines() ; for (i=0; itc_Node.ln_Pri == 10) SetTaskPri(task, -20L) ; eraseold() ; advancelines() ; drawnew() ; eraseold() ; advancelines() ; drawnew() ; if (task->tc_Node.ln_Pri == 10) SetTaskPri(task, -20L) ; eraseold() ; advancelines() ; drawnew() ; eraseold() ; advancelines() ; drawnew() ; if (task->tc_Node.ln_Pri == 10) SetTaskPri(task, -20L) ; eraseold() ; advancelines() ; drawnew() ; eraseold() ; advancelines() ; drawnew() ; colors() ; } done: Signal(global.buddy, 1L << global.replysignum) ; Wait(0L) ; } /* * Now we do hotkey magic to activate windows, bring them to front, * etc. * * Now we have a key, so we have to find a process with that name and * bring her to front. For now, we just deal with tasks, since the * CLI stuff is so complicated. */ #define MAXMATCH (20) char simplematch[3] = { ' ', '*', 0 } ; struct Window *matchwindows[MAXMATCH] ; extern long LockIBase() ; windowtofront(key, qual) char key ; { long foo ; int i, j ; int n ; struct Window *w ; struct Screen *s ; struct Process *p ; struct MsgPort **mp ; struct CommandLineInterface *CLI ; int cli ; char *nameptr, *matchptr ; extern struct DosLibrary *DOSBase ; struct hotkey *hk ; int shift, ctrl ; struct Window *activewindow ; /* * First we look for a matching record. */ if (key == '.') goto goner ; shift = ((qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0) ; ctrl = ((qual & IEQUALIFIER_CONTROL) != 0) ; activewindow = NULL ; for (hk=hotkeys; hk; hk=hk->next) if (hk->key == key && (hk->flags & SHIFT) == shift) break ; cli = 0 ; if (hk && hk->matchstring) matchptr = hk->matchstring ; else { matchptr = simplematch ; if (key == ' ') matchptr++ ; else if ('A' <= key && key <= 'Z') simplematch[0] = key ; else if ('0' <= key && key <= '9') { cli = key ; if (cli == '0') cli += 10 ; matchptr++ ; } else goto goner ; } n = 0 ; foo = LockIBase(0L) ; if (! ctrl && !(hk && (hk->flags & NOTINTUITION)) && !cli) { for (s=IntuitionBase->FirstScreen; s; s=s->NextScreen) for (w=s->FirstWindow; w; w=w->NextWindow) { if (w->UserPort) { p = (struct Process *)(w->UserPort->mp_SigTask) ; if (((struct Task *)p)->tc_Node.ln_Type == NT_PROCESS) { if (p->pr_CLI) { CLI = (struct CommandLineInterface *)BSTRtoS(p->pr_CLI) ; if (bstrcmp(BSTRtoS((CLI)->cli_CommandName), matchptr) && n < MAXMATCH) { if (w==IntuitionBase->ActiveWindow) activewindow = w ; matchwindows[n++] = w ; } } else { if (sstrcmp(((struct Task *)p)->tc_Node.ln_Name, matchptr) && n < MAXMATCH) { if (w==IntuitionBase->ActiveWindow) activewindow = w ; matchwindows[n++] = w ; } } } } } } /* * Folks, there are still several/many windows of vulnerability * here; I'll have to plug them. For instance, what happens if a * CLI goes away while we are doing this? Or what happens if a * window goes away later, when we are looking at IntuitionBase? */ if (! ctrl && !(hk && (hk->flags & NOTCLI))) { mp = (struct MsgPort **)BSTRtoS(*(DOSBase->dl_Root)) ; for (j=1; j<(long)(mp[0]); j++) if (mp[j] && (cli == 0 || j == cli - '0')) { p = (struct Process *)(mp[j]->mp_SigTask) ; CLI = (struct CommandLineInterface *)BSTRtoS(p->pr_CLI) ; if (!CLI->cli_Background && bstrcmp(BSTRtoS((CLI)->cli_CommandName), matchptr)) { infoptr->id_VolumeNode = NULL ; dos_packet(p->pr_ConsoleTask, ACTION_DISK_INFO, ((long)(infoptr)) >> 2, 0L, 0L, 0L, 0L, 0L, 0L) ; if (w=(struct Window *)infoptr->id_VolumeNode) if (n < MAXMATCH) { if (w==IntuitionBase->ActiveWindow) activewindow = w ; matchwindows[n++] = w ; } } } } if (shift) key += 100 ; if (ctrl || n==0) { UnlockIBase(foo) ; if (hk == NULL || hk->startstring == NULL) goto goner ; Execute(hk->startstring, 0L, 0L) ; } else { if (n == 1) { w = matchwindows[0] ; } else { /* * This is some real neat code. We want to find the next window, * that is, the window with the least address greater than the * currently active window, unless the currently active window * has the highest address, in which case we want to find the * window with the least address. Why this works is left as a * puzzle for the reader. */ if (activewindow) { w = activewindow ; for (j=0; j activewindow) ^ (w > matchwindows[j]) ^ (matchwindows[j] > activewindow)) w = matchwindows[j] ; } else { w = NULL ; for (j=0; jWScreen ; UnlockIBase(foo) ; ScreenToFront(s) ; /* * If only one window on screen, don't bring it to front * (mostly for DPaint, but for other progs as well.) * (Anyone know an easy way to see if this window is fully * exposed?) */ if (s->FirstWindow != w || w->NextWindow) WindowToFront(w) ; ActivateWindow(w) ; } return ; goner: DisplayBeep(0L) ; } /* * These two functions compare a given string `s' with a `key' string. * The key string should be all upper case; this is a case insensitive * match. If the key string contains `*', this character is assumed to * match the rest of the string (and it can only come at the end.) We * have a routine for BSTR's, and a routine for regular strings. */ int sstrcmp(s, key) register char *s, *key ; { while (1) { if (*key == '*') return(1) ; if (*key == 0) return(*s == 0) ; if (*s == 0) return(0) ; if (*s != *key && (*s != *key + 32 || *s < 'a' || *s > 'z')) return(0) ; s++ ; key++ ; } } /* * This is the same as above, only instead of using a null to * end the string, we keep track of the number of characters. */ int bstrcmp(s, key) char *s, *key ; { int n ; n = *(unsigned char *)s++ ; while (1) { if (*key == '*') return(1) ; if (*key == 0) return(n == 0) ; if (n == 0) return(0) ; if (*s != *key && (*s != *key + 32 || *s < 'a' || *s > 'z')) return(0) ; s++ ; key++ ; n-- ; } } /* * A place to hold an input line. */ #define MAXSTARTUPLINE (100) char startbuf[MAXSTARTUPLINE] ; char upline[MAXSTARTUPLINE] ; /* * Is a legit separator of some sort. */ int issep(s) register char s ; { return (s <= ' ' || s == '=' || s == ':' || s == ',' || s == '-') ; } /* * Go to next `word' in the startup file. */ char *getword(s) register char *s ; { while (*s && issep(*s)) s++ ; return(s) ; } /* * Upper case a string. */ char *upcase(dest, s) char *dest ; register char *s ; { register char *d = dest ; while (*s) { if ('a' <= *s && *s <= 'z') *d++ = *s++ - 32 ; else *d++ = *s++ ; } *d = 0 ; return(dest) ; } /* * Say we got a bad line. */ badline() { puts("Error in startup file!") ; puts(startbuf) ; } /* * Copies a string from one place to another; string delimited by * double quotes. */ char *cpystr(dest, src) register char *dest, *src ; { if (*src != '"') badline() ; else { src++ ; while (*src != '"' && *src != 0) { if (*src == '\\' && src[1] != 0) src++ ; *dest++ = *src++ ; } if (*src) src++ ; } *dest = 0 ; return(getword(src)) ; } /* * Handle a single startup line that's not a comment and non-empty * and been converted to all upper case. */ parseline(s, msg) register char *s ; struct OURMSG *msg ; { int flags ; short t ; int key ; char *p ; register struct hotkey *hk ; flags = 0 ; if (strncmp(s, "COMMAND", 7)==0) { s = getword(s+7) ; cpystr(msg->cmd, s) ; } else if (strncmp(s, "TIMEOUT", 7)==0) { s = getword(s+7) ; t = 0 ; while ('0' <= *s && *s <= '9') t = t * 10 + *s++ - '0' ; if (t <= 0) t = DEFTIME ; msg->interval = t ; } else if (strncmp(s, "LINES", 5)==0) { msg->draw = 1 ; } else if (strncmp(s, "BLANK", 5)==0) { msg->draw = -1 ; } else { if (strncmp(s, "SHIFT", 5)==0) { flags = SHIFT ; s = getword(s+5) ; } if (*s == 0) badline() ; else { if (issep(s[1]) && (('A' <= *s && *s <= 'Z') || ('0' <= *s && *s <= '9'))) { key = *s ; s = getword(s+1) ; } else if (strncmp(s, "SPACE", 5)==0) { key = ' ' ; s = getword(s+5) ; } else if (*s == 'F' && ('1' <= s[1] && s[1] <= '9')) { s++ ; t = *s++ - '0' ; if (t == 1 && *s == '0') { t = 10 ; s++ ; } s = getword(s) ; } else { badline() ; return ; } if (strncmp(s, "INTUITION", 9)==0) { flags |= NOTCLI ; s = getword(s+9) ; } else if (strncmp(s, "CLI", 3)==0) { flags |= NOTINTUITION ; s = getword(s+3) ; } s = cpystr(upline, s) ; p = upline + strlen(upline) + 1 ; if (*s) cpystr(p, startbuf + (s-upline)) ; else *p = 0 ; t = sizeof(struct hotkey) + strlen(p) + strlen(upline) ; hk = AllocMem((long)t, MEMF_CLEAR | MEMF_PUBLIC) ; if (hk) { hk->key = key ; hk->flags = flags ; hk->next = hotkeys ; hk->structlen = t ; hk->matchstring = strcpy(hk->strings, upline) ; hk->startstring = strcpy(hk->strings + strlen(upline) + 1, p) ; if (hk->startstring[0]==0) hk->startstring = NULL ; hotkeys = hk ; } else puts("Out of memory in startup") ; } } } /* * Handle the startup file. */ processstartup(s, msg) char *s ; struct OURMSG *msg ; { FILE *f ; char *p ; if (f=fopen(s, "r")) { while (fgets(startbuf, MAXSTARTUPLINE, f)) { p = getword(startbuf) ; if (*p != '*' && *p != '#' && *p != ';' && *p != 0) { upcase(upline, p) ; parseline(upline, msg) ; } } } else { puts("Couldn't open startup file:") ; puts(s) ; } } /* * This stuff down here handles the raw key conversion stuff * properly. Thanks to Willy Langeveld and Carolyn Scheppner. */ char *dos_rkcv(); int dos_rkcvinit(), dos_rkcvexit(); struct IOStdReq ConStdReq; /* * This code won't compile under Manx unless you delete the * `ConsoleDevice' function in functions.h, or perform a kludge * like the one I did when I included it. Why the hell does * Manx have that in there? If you try to use it, it comes out * undefined, but if you rename the following, it won't link * because it needs the function `ConsoleDevice'. */ long ConsoleDevice ; /** * * Calling sequence: * ================= * * result = (char *) dos_rkcv(code, buffer, length); * * Description: * ============ * * Covert raw key number to array of console device ascii text * using the default keymap. * * Inputs: * ======= * * int code Raw key number. * int qual Qualifier. * char *buffer Pointer to an array of char to receive the * conversion. * int length length of buffer. * * Outputs: * ======== * * F. value: NULL on conversion failure, or pointer to * buffer on success. * **/ char *dos_rkcv(code, qual, buffer, length) int code; int qual; char *buffer; int length; { static struct InputEvent event; event.ie_Class = IECLASS_RAWKEY; event.ie_Code = code; event.ie_Qualifier = qual; if (RawKeyConvert(&event, buffer, (long) length, NULL) == 0L) return(0L); return(buffer); } /** * * Calling sequence: * ================= * * error = dos_rkcvinit(); * * Description: * ============ * * Open the Console device for later use with dos_rkcv(). * * Inputs: * ======= * * None * * Outputs: * ======== * * F. value: 1 on failure, zero otherwise. * * **/ int dos_rkcvinit() { if (OpenDevice("console.device", -1L, &ConStdReq, 0L) != NULL) { ConsoleDevice = 0L; return(1); } else { ConsoleDevice = (long) ConStdReq.io_Device; return(0); } } /** * * Calling sequence: * ================= * * error = dos_rkcvexit(); * * Description: * ============ * * Close the Console device after use with dos_rkcv(). * * Inputs: * ======= * * None * * Outputs: * ======== * * F. value: Always zero; * **/ int dos_rkcvexit() { if (ConsoleDevice) CloseDevice(&ConStdReq); return(0); } /* * Set up the key conversion table. Note that the buffer has to be * long word aligned! */ initkeytoasc() { register int i ; char buf[100] ; for (i=0; i<128; i++) keytoasc[i] = '.' ; if (dos_rkcvinit()) return(1) ; for (i=0; i<128; i++) { buf[1] = 0 ; if (dos_rkcv(i, 0, buf, 100) && buf[1] == 0 && (buf[0] == ' ' || ('a' <= buf[0] && buf[0] <= 'z' && (buf[0] -= 32)) || ('0' <= buf[0] && buf[0] <= '9'))) { keytoasc[i] = buf[0] ; } } /* * Have to handle the function keys separately */ for (i=80; i<90; i++) keytoasc[i] = i-79 ; dos_rkcvexit() ; return(0) ; }