home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 2: PC / frozenfish_august_1995.bin / bbs / d01xx / d0161.lha / Mackie / Mackie.c < prev    next >
C/C++ Source or Header  |  1988-10-02  |  37KB  |  1,311 lines

  1. /*
  2.     Modified to work with Manx 3.6a; probably won't work with Lattice.
  3.                                 Based on:
  4.                                                                              */
  5. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  6. /* |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved */
  7. /* |. o.| || This program may not be distributed without the permission of   */
  8. /* | .  | || the authors.                                                    */
  9. /* | o  | ||    Dave Baker     Ed Burnette  Stan Chow    Jay Denebeim        */
  10. /* |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         */
  11. /* ======          BBS:(919)-471-6436      VOICE:(919)-469-4210              */ 
  12. /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
  13. /*
  14.  * VERY loosely based on the input.device example by Rob Peck, 12/1/85
  15.  */
  16. /* * * * * * * * * INCLUDE FILES * * * * * * * * * * * */
  17. #include <exec/types.h>
  18. #include <exec/nodes.h>
  19. #include <exec/lists.h>
  20. #include <exec/memory.h>
  21. #include <exec/interrupts.h>
  22. #include <exec/ports.h>
  23. #include <exec/libraries.h>
  24. #include <exec/io.h>
  25. #include <exec/tasks.h>
  26. #include <exec/execbase.h>
  27. #include <exec/devices.h>
  28. #include <devices/timer.h>
  29. #include <devices/input.h>
  30. #include <devices/inputevent.h>
  31. #include <devices/console.h>
  32. #include <intuition/intuition.h>
  33. #include <intuition/intuitionbase.h>
  34. #include <libraries/dos.h>
  35. #include <libraries/dosextens.h>
  36. #include <graphics/gfxmacros.h>
  37. #include <hardware/custom.h>
  38. #include <hardware/dmabits.h>
  39. /*
  40.  *   I need this kludge because of a bug in functions.h.
  41.  */
  42. #define ConsoleDevice IDontReallyExist
  43. #include <functions.h>
  44. #undef ConsoleDevice
  45. #include <stdio.h>
  46.  
  47. /* * * * * * * * * * * CONSTANTS * * * * * * * * * * * * */
  48. #define PORTNAME     "Mackie.port"
  49. #define TIMEINTERVAL 1L      /* in seconds */
  50. #define DEFTIME      300     /* two minute timeout */
  51. #define MAXCMD       200
  52. #define MAXPENDINGSYSTEM 20
  53. #define DEFKEY    0x45
  54. #define DEFCMD    "NEWCLI >NIL: <NIL:"
  55. #define STARTUPFILE "s:.mackierc"
  56. /*
  57.  *   Macro to make BPTR things easier to work with.
  58.  */
  59. #define BSTRtoS(a) ((char *)(((long)(a))<<2))
  60. /* * * * * * * * * * * GLOBAL VARIABLES * * * * * * * * * */
  61. /*
  62.  *   Detach stuff (doesn't work, somehow!)
  63.  */
  64. typedef struct
  65.    {
  66.    struct Task          *buddy ;
  67.    ULONG                 creatclisig ;
  68.    ULONG                 unblanksig ;
  69.    ULONG                 frontsig ;
  70.    ULONG                 noevents ;
  71.    short                 creatsignum ;
  72.    short                 blanksignum ;
  73.    short                 replysignum ;
  74.    short                 frontsignum ;
  75.    short                 key ;
  76.    char                  frontkey[MAXPENDINGSYSTEM] ;
  77.    char                  frontqual[MAXPENDINGSYSTEM] ;
  78.    short                 frontptr ;
  79.    short                 draw ;
  80.    short                 helppressed ;
  81.    struct Screen        *blankscreen ;
  82.    } GLOBAL_DATA;
  83. #define SHIFT 1
  84. #define NOTCLI 2
  85. #define NOTINTUITION 4
  86. struct hotkey {
  87.    struct hotkey*next ;
  88.    char key, flags ;
  89.    int structlen ;
  90.    char *matchstring, *startstring ;
  91.    char strings[2] ;
  92. } *hotkeys ;
  93. struct Window *lastwindows[200] ;
  94. struct Task *task ;
  95. long taskreply ; /* the signal the line drawing task will return */
  96. #define STACKSIZE (1000)
  97. long stackmem[STACKSIZE/4] ;
  98. struct InfoData *infoptr ;
  99. struct MsgPort *FindPort(), *CreatePort();
  100. void DeletePort();
  101. char *startupfile = STARTUPFILE ;
  102. struct OURMSG {
  103.  struct Message msgpart;
  104.  short key;
  105.  short interval;
  106.  short draw ;
  107.  char cmd[MAXCMD];
  108.  };
  109.  
  110. extern char *strcpy() ;
  111.  
  112. /************************************************************************/
  113. /* the handler subroutine - called through the handler stub             */
  114. /************************************************************************/
  115. extern void HandlerInterface();
  116. void foobar() {
  117. #asm
  118. _HandlerInterface:
  119.     movem.l a4,-(a7)
  120.     movem.L    A0/A1,-(A7)
  121.     jsr    _geta4#
  122.     jsr    _myhandler
  123.     addq.L    #8,A7
  124.     movem.L    (a7)+,a4
  125.     rts
  126. #endasm
  127. }
  128. char keytoasc[128] ;
  129. struct InputEvent *myhandler(ev, gptr)
  130. struct InputEvent *ev;      /* and a pointer to a list of events */
  131. register GLOBAL_DATA *gptr;      /* Everything we need to know about */
  132. {
  133.    register struct InputEvent *ep, *laste;
  134.    int key ;
  135.    /*
  136.     * run down the list of events
  137.     * to see if they pressed
  138.     * one of the magic buttons
  139.     */
  140.    for (ep = ev, laste = NULL; ep != NULL; ep = ep->ie_NextEvent) {
  141.       if ((ep->ie_Class == IECLASS_RAWKEY)    &&
  142.              (((ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) &&
  143.                (ep->ie_Code == gptr->key)) ||
  144.               (!gptr->helppressed && ep->ie_Code == 0x5f) ||
  145.               (gptr->helppressed &&
  146.                (ep->ie_Code & 0x80) == 0 &&
  147. /*
  148.  *   All the qualifiers have code = 0x6?; dangerous to take advantage
  149.  *   of?
  150.  */
  151.                (ep->ie_Code & 0xf0) != 0x60 &&
  152.                gptr->frontkey[gptr->frontptr] == 0 &&
  153.                (gptr->helppressed = (keytoasc[ep->ie_Code] != '.'))))) {
  154.          if ((ep->ie_Qualifier & IEQUALIFIER_LCOMMAND) &&
  155.               (ep->ie_Code == gptr->key))
  156.             key = -1 ;
  157.          else if (gptr->helppressed) {
  158.             gptr->frontkey[gptr->frontptr] = key = ep->ie_Code ;
  159.             gptr->frontqual[gptr->frontptr] = ep->ie_Qualifier ;
  160.             gptr->frontptr++ ;
  161.             if (gptr->frontptr >= MAXPENDINGSYSTEM)
  162.                gptr->frontptr = 0 ;
  163.             gptr->helppressed = 0 ;
  164.          } else {
  165.             gptr->helppressed = 1 ;
  166.             key = 0 ;
  167.          }
  168.          /* we can handle this event so take it off the chain */
  169.          if (laste == NULL)
  170.             ev = ep->ie_NextEvent;
  171.          else
  172.             laste->ie_NextEvent = ep->ie_NextEvent;
  173.          /* now tell him to create the new cli */
  174.          if (key == -1)
  175.             Signal(gptr->buddy, gptr->creatclisig);
  176.          else if (key > 0)
  177.             Signal(gptr->buddy, gptr->frontsig);
  178.       } else
  179.          laste = ep;
  180.       if (ep->ie_Class != IECLASS_TIMER) {
  181.          gptr->noevents = 0;
  182.          if (gptr->blankscreen != NULL)
  183.             Signal(gptr->buddy, gptr->unblanksig);
  184.       }
  185.    }
  186.    /* pass on the pointer to the event */
  187.    return(ev);
  188. }
  189.  
  190. /* * * * * * * * * * * EXTERNAL ROUTINES * * * * * * * * * */
  191. struct IntuitionBase *IntuitionBase;
  192. struct GfxBase       *GfxBase;
  193. struct DosLibrary    *DosBase;
  194. struct NewScreen      NewScreen = 
  195.    { 0, 0, 320, 30, 1, 0, 1, NULL, CUSTOMSCREEN, NULL, NULL, NULL, NULL };
  196.  
  197. extern struct MsgPort  *CreatePort();
  198. struct IOStdReq *CreateIOReq();
  199. void DeleteIOReq();
  200.  
  201. /************************************************************************/
  202. /* Queue a timer to go off in a given number of seconds                 */
  203. /************************************************************************/
  204. void QueueTimer(tr,seconds)
  205. struct timerequest *tr;
  206. ULONG seconds;
  207. {
  208.    tr->tr_node.io_Command = TR_ADDREQUEST;   /* add a new timer request */
  209.    tr->tr_time.tv_secs =  seconds;            /* seconds */
  210.    tr->tr_time.tv_micro = 0;
  211.    SendIO( (struct IORequest *)tr );
  212. }
  213. /************************************************************************/
  214. /* the main program to do the popcli stuff                              */
  215. /************************************************************************/
  216. GLOBAL_DATA global;
  217. main(argc, argv)
  218. int argc ;
  219. char *argv[] ;
  220. {
  221.    struct MsgPort *port;
  222.    int stay = 0;
  223.    struct OURMSG *msg;
  224.    int i ;
  225.    char cmdstr[MAXCMD];
  226.    short key, timeout;
  227.    struct FileHandle *nullfh = NULL ;
  228.    ULONG sig, timersig;
  229.    struct timerequest *timerreq;
  230.    struct MsgPort     *timerport;
  231.    struct MsgPort     *inputDevPort;
  232.    struct IOStdReq    *inputRequestBlock;
  233.    struct Interrupt      handlerStuff;
  234.    char *cmd ;
  235.    int draw = 0 ;
  236.    int nextfront = 0 ;
  237.  
  238.    SetTaskPri(FindTask(0L), 20L) ;
  239.    global.creatsignum  = -1;
  240.    global.blanksignum  = -1;
  241.    global.replysignum  = -1;
  242.    global.frontsignum  = -1;
  243.    global.blankscreen  = NULL;
  244.    global.key          = DEFKEY ;
  245.    global.draw         = 1 ;
  246.    timerreq            = NULL;
  247.    timerport           = NULL;
  248.    inputDevPort        = NULL;
  249.    inputRequestBlock   = NULL;
  250.    /* now see if we are already installed */
  251.    if ((port = FindPort(PORTNAME)) == NULL) {
  252.       stay = 1; /* remember to hang around when we are done */
  253.       /* not installed, we need to install our own port */
  254.       if ((port = CreatePort(PORTNAME,0L)) == NULL)
  255.          goto abort;
  256.    }
  257. /*
  258.  *   If we are hanging around, initialize our keyboard translation table.
  259.  *   If we have difficulty, exit angry.
  260.  */
  261.    if (stay)
  262.       if (initkeytoasc())
  263.          goto abort ;
  264.    /* now send the parameter to the waiting program */
  265.    if ((msg = (struct OURMSG *)
  266.        AllocMem((long)sizeof(struct OURMSG), MEMF_CLEAR|MEMF_PUBLIC)) == NULL)
  267.       goto abort;
  268.    if ((infoptr = (struct InfoData *)
  269.       AllocMem((long)sizeof(struct InfoData), MEMF_CLEAR)) == NULL)
  270.       goto abort ;
  271.    /* fill in the message information */
  272.    msg->msgpart.mn_Length = sizeof(struct OURMSG);
  273.    strcpy(cmdstr, DEFCMD);
  274.    timeout = 0 ;
  275.    key = 0 ;
  276.    msg->cmd[0] = 0;
  277.    /* if we were run from CLI then output our banner and process parameters */
  278.    if (argc > 0) {
  279.       /* display our copyright */
  280.       if (stay)
  281.          puts("Mackie 1.1 by Tomas Rokicki - Copyright \xa9 1987, 1988 Radical Eye Software") ;
  282.       if (argc == 1)
  283.          puts("Usage: Mackie [-q] [-l] [-b] [-f startup] [time] [\"command\"]") ;
  284.       argc-- ;
  285.       argv++ ;
  286.       while (argc > 0) {
  287.          cmd = argv[0] ;
  288.          if (*cmd == '-') {
  289.             cmd++ ;
  290.             switch (*cmd) {
  291. case 'q' : case 'Q' :
  292.                key = -1 ;
  293.                puts("\x9B1mMackie\x9B0m Terminating") ;
  294.                break ;
  295. case 'l' : case 'L' :
  296.                draw = 1 ;
  297.                break ;
  298. case 'b' : case 'B' :
  299.                draw = -1 ;
  300.                break ;
  301. case 'f' : case 'F' :
  302.                if (cmd[1])
  303.                   startupfile = cmd + 1 ;
  304.                else {
  305.                   argv++ ;
  306.                   argc-- ;
  307.                   startupfile = argv[0] ;
  308.                }
  309. default :
  310.                puts("Error in parameter!") ;
  311.             }
  312.          } else if ('0' <= *cmd && *cmd <= '9') {
  313.             timeout = 0;
  314.             while ((*cmd >= '0') && (*cmd <= '9'))
  315.                timeout = (timeout*10) + *cmd++ - '0';
  316.             if (timeout <= 0)
  317.                timeout = DEFTIME;
  318.          } else {
  319.             strcpy(msg->cmd, cmd) ;
  320.          }
  321.          argc-- ;
  322.          argv++ ;
  323.       }
  324.    }
  325.    msg->interval = timeout;
  326.    msg->key = key;
  327.    msg->draw = draw ;
  328.    if (stay)
  329.       processstartup(startupfile, msg) ;
  330.    if (draw)
  331.       global.draw = draw ;
  332.    PutMsg(port,(struct Message *)msg);
  333.    if (!stay) goto abort;
  334.    if (timeout == 0)
  335.       timeout = DEFTIME ;
  336.    global.blankscreen = NULL;
  337.    global.buddy = FindTask(0L);
  338.    global.noevents = 0;
  339.    nullfh = Open("NIL:", MODE_NEWFILE);
  340.    if (((inputDevPort = CreatePort(0L,0L)) == NULL) ||
  341.       ((inputRequestBlock =
  342.           CreateIOReq(inputDevPort, (long)sizeof(struct IOStdReq))) == NULL) ||
  343.       ((timerport = CreatePort(0L,0L)) == NULL) ||
  344.       ((timerreq  = (struct timerequest *)
  345.           CreateIOReq(timerport, (long)sizeof(struct timerequest))) == NULL) ||
  346.       ((global.creatsignum = AllocSignal(-1L)) == -1) ||
  347.       ((global.blanksignum = AllocSignal(-1L)) == -1) ||
  348.       ((global.replysignum = AllocSignal(-1L)) == -1) ||
  349.       ((global.frontsignum = AllocSignal(-1L)) == -1) ||
  350.       ((GfxBase = (struct GfxBase *)
  351.                   OpenLibrary("graphics.library", 0L)) == NULL) ||
  352.       ((IntuitionBase = (struct IntuitionBase *)
  353.                         OpenLibrary("intuition.library", 0L)) == NULL) ||
  354.       OpenDevice(TIMERNAME, UNIT_VBLANK, (struct IORequest *)timerreq, 0L) ||
  355.       OpenDevice("input.device",0L,(struct IORequest *)inputRequestBlock,0L))
  356.          goto abort;
  357.    handlerStuff.is_Data = (APTR)&global;
  358.    handlerStuff.is_Code = HandlerInterface;
  359.    handlerStuff.is_Node.ln_Pri = 51;
  360.    timersig            = (1L << timerport->mp_SigBit);
  361.    global.creatclisig  = 1L << global.creatsignum;
  362.    global.unblanksig   = 1L << global.blanksignum;
  363.    global.frontsig     = 1L << global.frontsignum;
  364.    inputRequestBlock->io_Command = IND_ADDHANDLER;
  365.    inputRequestBlock->io_Data    = (APTR)&handlerStuff;
  366.    DoIO((struct IORequest *)inputRequestBlock);
  367.    QueueTimer(timerreq, TIMEINTERVAL);
  368.    for(;;) {         /* FOREVER */
  369.       sig = Wait( global.creatclisig | global.unblanksig | timersig |
  370.                   global.frontsig);
  371.       /* see if they asked us to change the interval */
  372.       if ((msg = (struct OURMSG *)GetMsg(port)) != NULL) {
  373.          if (msg->cmd[0]) strcpy(cmdstr, msg->cmd);
  374.          if (msg->key)
  375.             global.key = msg->key;
  376.          if (msg->interval)
  377.             timeout    = msg->interval;
  378.          if (msg->draw)
  379.             global.draw = msg->draw ;
  380.          FreeMem((char *)msg, (long)msg->msgpart.mn_Length);
  381.          if (msg->key == -1) goto abort;
  382.       }
  383.       if ((sig & global.unblanksig) && global.blankscreen)
  384.          screenunblank() ;
  385.       if (sig & global.creatclisig) {
  386.          WBenchToFront();
  387.          (void)Execute(cmdstr,nullfh,nullfh);
  388.       }
  389.       if (sig & global.frontsig) {
  390.          while (i=global.frontkey[nextfront]) {
  391.             windowtofront(keytoasc[i], global.frontqual[nextfront]) ;
  392.             global.frontkey[nextfront] = 0 ;
  393.             nextfront++ ;
  394.             if (nextfront >= MAXPENDINGSYSTEM)
  395.                nextfront = 0 ;
  396.          }
  397.       }
  398.       if (sig & timersig) {
  399.          /* get rid of the message */
  400.          (void)GetMsg(timerport);
  401.          QueueTimer(timerreq, TIMEINTERVAL);
  402.          if (task)
  403.             SetTaskPri(task, 10L) ;
  404.          if ((global.noevents++ >= timeout) && (global.blankscreen == NULL))
  405.             blankscreen() ;
  406.       }
  407.    }
  408. abort:
  409.    if (infoptr) {
  410.       FreeMem(infoptr, (long)sizeof(struct InfoData)) ;
  411.       infoptr = NULL ;
  412.    }
  413.    if (timerreq != NULL) {
  414.       if (timerreq->tr_node.io_Device != NULL)
  415.          CloseDevice((struct IORequest *)timerreq);
  416.       DeleteIOReq((struct IOStdReq *)timerreq);
  417.    }
  418.    if (inputRequestBlock != NULL) {
  419.       if (inputRequestBlock->io_Device != NULL) {
  420.          inputRequestBlock->io_Command = IND_REMHANDLER;
  421.          inputRequestBlock->io_Data = (APTR)&handlerStuff;
  422.          DoIO((struct IORequest *)inputRequestBlock);
  423.          CloseDevice((struct IORequest *)inputRequestBlock);
  424.       }
  425.       DeleteIOReq(inputRequestBlock);
  426.    }
  427.    screenunblank() ;
  428.    if (timerport != NULL)          DeletePort(timerport);
  429.    if (global.creatsignum != -1)   FreeSignal(global.creatsignum);
  430.    if (global.blanksignum != -1)   FreeSignal(global.blanksignum);
  431.    if (global.replysignum != -1)   FreeSignal(global.replysignum);
  432.    if (global.frontsignum != -1)   FreeSignal(global.frontsignum);
  433.    if (IntuitionBase != NULL)      CloseLibrary((struct Library *)IntuitionBase);
  434.    if (GfxBase != NULL)            CloseLibrary((struct Library *)GfxBase);
  435.    if (inputDevPort != NULL)       DeletePort(inputDevPort);
  436.    if (stay && (port != NULL))     DeletePort(port);
  437.    {
  438.       struct hotkey *hk ;
  439.  
  440.       while (hotkeys) {
  441.          hk = hotkeys->next ;
  442.          FreeMem(hotkeys, (long)hotkeys->structlen) ;
  443.          hotkeys = hk ;
  444.       }
  445.    }
  446.    if (nullfh)                     Close(nullfh);
  447.    SetTaskPri(FindTask(0L), 0L) ;
  448. }
  449.  
  450. struct IOStdReq *
  451. CreateIOReq(port, size)
  452. struct MsgPort *port;
  453. long size;
  454. {
  455.    struct IOStdReq *ioReq;
  456.  
  457.    if ((ioReq = (struct IOStdReq *)
  458.                 AllocMem(size, MEMF_CLEAR | MEMF_PUBLIC)) != NULL) {
  459.       ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  460.       ioReq->io_Message.mn_Node.ln_Pri  = 0;
  461.       ioReq->io_Message.mn_Length       = size;
  462.       ioReq->io_Message.mn_ReplyPort    = port;
  463.    }
  464.    return(ioReq);
  465. }
  466.  
  467. void DeleteIOReq(ioReq)
  468. struct IOStdReq *ioReq;
  469. {
  470.    ioReq->io_Message.mn_Node.ln_Type = 0xff;
  471.    ioReq->io_Device = (struct Device *) -1;
  472.    ioReq->io_Unit = (struct Unit *) -1;
  473.    FreeMem( (char *)ioReq, (long)ioReq->io_Message.mn_Length);
  474. }
  475. /*
  476.  *   All of this stuff down here was written by Tomas Rokicki.
  477.  *   (C) Copyright 1987, 1988, Radical Eye Software.
  478.  */
  479. #include "graphics/gfxbase.h"
  480. /*
  481.  *   The maximum number of lines on the screen at once.
  482.  */
  483. #define MAXLINES (100)
  484. /*
  485.  *   The external variables we access.
  486.  */
  487. struct RastPort *rastport ;
  488. short screenheight, screenwidth ;
  489. /*
  490.  *   Some locals to this file.
  491.  */
  492. static struct NewScreen newscreen = {
  493.    0, 0,
  494.    640, 400,
  495.    1,
  496.    0, 1,
  497.    HIRES | LACE | SCREENQUIET,
  498.    CUSTOMSCREEN,
  499.    NULL,
  500.    NULL,
  501.    NULL,
  502.    NULL } ;
  503. /*
  504.  *   This routine opens a screen and fires off the task if apropriate.
  505.  */
  506. void taskrout() ;
  507. blankscreen() {
  508.    screenheight = 2 * GfxBase->NormalDisplayRows ;
  509.    screenwidth = GfxBase->NormalDisplayColumns ;
  510.    newscreen.Height = screenheight ;
  511.    newscreen.Width = screenwidth ;
  512.    if (global.draw == -1 || AvailMem(MEMF_CHIP) < 70000L ||
  513.              (global.blankscreen = OpenScreen(&newscreen)) == NULL) {
  514.       if ((global.blankscreen = OpenScreen(&NewScreen)) != NULL) {
  515.          SetRGB4(&(global.blankscreen->ViewPort), 0L, 0L, 0L, 0L);
  516.          OFF_DISPLAY ;
  517.       }
  518.    } else {
  519.       if (global.blankscreen == NULL &&
  520.           (global.blankscreen = OpenScreen(&newscreen))==NULL)
  521.          return ;
  522. /*
  523.  *   Turning off the sprites is a little bit tricky.  A simple OFF_SPRITE
  524.  *   will continue to display the data in the current sprite registers.
  525.  *   This happens most often with the cursor.  To fix, we simply clear out
  526.  *   the sprite control registers after turning the sprites off.  This
  527.  *   might break all of the sprites when the system comes back up . . .
  528.  */
  529.       OFF_SPRITE ;
  530.       custom.spr[0].ctl = 0 ;
  531.       custom.spr[1].ctl = 0 ;
  532.       custom.spr[2].ctl = 0 ;
  533.       custom.spr[3].ctl = 0 ;
  534.       custom.spr[4].ctl = 0 ;
  535.       custom.spr[5].ctl = 0 ;
  536.       custom.spr[6].ctl = 0 ;
  537.       custom.spr[7].ctl = 0 ;
  538.       SetRGB4(&(global.blankscreen->ViewPort), 0L, 0L, 0L, 0L) ;
  539.       rastport = &(global.blankscreen->RastPort) ;
  540.       SetAPen(rastport, 0L) ;
  541.       Forbid() ;
  542.       RectFill(rastport, 0L, 0L, (long)screenwidth-1, 30L) ;
  543.       Permit() ;
  544.       SetAPen(rastport, 1L) ;
  545.       task = (struct Task *)AllocMem((long)sizeof(struct Task),
  546.                 MEMF_CLEAR | MEMF_PUBLIC) ;
  547.       if (task != NULL) {
  548.          task->tc_Node.ln_Pri = 10 ;
  549.          task->tc_Node.ln_Type = NT_TASK ;
  550.          task->tc_Node.ln_Name = "ri.Lines" ;
  551.          task->tc_SPLower = (APTR)stackmem ;
  552.          task->tc_SPUpper = task->tc_SPReg = (APTR)(stackmem + STACKSIZE/4 - 8) ;
  553.          AddTask(task, taskrout, 0L) ;
  554.       }
  555.    }
  556. }
  557. /*
  558.  *   Unblank the screen.  We kill the task with the standard ^C kill signal.
  559.  */
  560. screenunblank() {
  561.    if (task != NULL) {
  562.       Signal(task, 1L << SIGBREAKB_CTRL_C) ;
  563.       SetTaskPri(task, 11L) ;
  564.       Wait(1L << global.replysignum) ;
  565.       RemTask(task);
  566.       FreeMem(task, (long)sizeof(struct Task)) ;
  567.       task = NULL ;
  568.    }
  569.    if (global.blankscreen != NULL) {
  570.       CloseScreen(global.blankscreen);
  571.       global.blankscreen = NULL ;
  572.       ON_DISPLAY ;
  573.       ON_SPRITE ;
  574.    }
  575. }
  576. /*
  577.  *   This routine returns a random value from 0 to n-1.
  578.  */
  579. int randm(i)
  580. int i ;
  581. {
  582.    static long seed ;
  583.    long rval ;
  584.  
  585.    if (seed == 0)
  586.       seed = 323214521 + global.blankscreen->MouseX +
  587.               global.blankscreen->MouseY ;
  588.    seed = seed * 123213 + 121 ;
  589.    rval = (seed >> 5) & 65535 ;
  590.    return ((i * rval) >> 16) ;
  591. }
  592. /*
  593.  *   This routine sets x and y values to a random number.
  594.  */
  595. static long x, y ;
  596. randomxy() {
  597.    x = randm(screenwidth) ;
  598.    y = randm(screenheight) ;
  599. }
  600. /*
  601.  *   Main routines are always fun.
  602.  */
  603. short x1store[MAXLINES], y1store[MAXLINES] ;
  604. short x2store[MAXLINES], y2store[MAXLINES] ;
  605. short ptr ;
  606. short dx1, dy1, dx2, dy2 ;
  607. short ox1, oy1, ox2, oy2 ;
  608. short nx1, ny1, nx2, ny2 ;
  609. short dr, dg, db ;
  610. short or, og, ob ;
  611. short nr, ng, nb ;
  612. /*
  613.  *   Initialize things for the first lines.
  614.  */
  615. startlines() {
  616.    ptr = 0 ;
  617.    if (dx1 == 0) {
  618.       ox1 = randm(screenwidth) ;
  619.       ox2 = randm(screenwidth) ;
  620.       oy1 = randm(screenheight) ;
  621.       oy2 = randm(screenheight) ;
  622.       dx1 = 3 ;
  623.       dx2 = 4 ;
  624.       dy1 = 1 ;
  625.       dy2 = 6 ;
  626.       nr = 53 ;
  627.       ng = 33 ;
  628.       nb = 35 ;
  629.       dr = -3 ;
  630.       dg = 5 ;
  631.       db = 7 ;
  632.    }
  633.    SetRGB4(&(global.blankscreen->ViewPort), 0L, 0L, 0L, 0L) ;
  634.    SetRGB4(&(global.blankscreen->ViewPort), 1L, (long)(nr >> 3),
  635.                                  (long)(ng >> 3), (long)(nb >> 3)) ;
  636. }
  637. /*
  638.  *   Advance the number by the delta, and check the boundaries.
  639.  */
  640. adv(o, d, n, w)
  641. short *o, *d, *n ;
  642. short w ;
  643. {
  644.    *n = *o + *d ;
  645.    if (*n < 0) {
  646.       *n = 0 ;
  647.       *d = randm(6) + 1 ;
  648.    } else if (*n >= w) {
  649.       *n = w - 1 ;
  650.       *d = - randm(6) - 1 ;
  651.    }
  652. }
  653. /*
  654.  *   Advance the two points which make up the lines.
  655.  */
  656. advancelines() {
  657.    adv(&ox1, &dx1, &nx1, screenwidth) ;
  658.    adv(&ox2, &dx2, &nx2, screenwidth) ;
  659.    adv(&oy1, &dy1, &ny1, screenheight) ;
  660.    adv(&oy2, &dy2, &ny2, screenheight) ;
  661. }
  662. /*
  663.  *   Draw a new set of lines.
  664.  */
  665. drawnew() {
  666.    x1store[ptr] = ox1 = nx1 ;
  667.    x2store[ptr] = ox2 = nx2 ;
  668.    y1store[ptr] = oy1 = ny1 ;
  669.    y2store[ptr] = oy2 = ny2 ;
  670.    Move(rastport, (long)ox1, (long)oy1) ;
  671.    Draw(rastport, (long)ox2, (long)oy2) ;
  672.    Draw(rastport, (long)(screenwidth-ox1-1), (long)(screenheight-oy1-1)) ;
  673.    Draw(rastport, (long)(screenwidth-ox2-1), (long)(screenheight-oy2-1)) ;
  674.    Draw(rastport, (long)ox1, (long)oy1) ;
  675.    ptr++ ;
  676.    if (ptr == MAXLINES)
  677.       ptr = 0 ;
  678. }
  679. /*
  680.  *   Erase the old line.
  681.  */
  682. eraseold() {
  683.    short oldpen ;
  684.  
  685.    oldpen = rastport->FgPen ;
  686.    SetAPen(rastport, 0L) ;
  687.    Move(rastport, (long)x1store[ptr], (long)y1store[ptr]) ;
  688.    Draw(rastport, (long)x2store[ptr], (long)y2store[ptr]) ;
  689.    Draw(rastport, (long)(screenwidth-x1store[ptr]-1),
  690.                   (long)(screenheight-y1store[ptr]-1)) ;
  691.    Draw(rastport, (long)(screenwidth-x2store[ptr]-1), 
  692.                   (long)(screenheight-y2store[ptr]-1)) ;
  693.    Draw(rastport, (long)x1store[ptr], (long)y1store[ptr]) ;
  694.    SetAPen(rastport, (long)oldpen) ;
  695. }
  696. /*
  697.  *   This routine mucks with the colors.
  698.  */
  699. colors() {
  700.    or = nr ;
  701.    og = ng ;
  702.    ob = nb ;
  703.    adv(&or, &dr, &nr, 128) ;
  704.    adv(&og, &dg, &ng, 128) ;
  705.    adv(&ob, &db, &nb, 128) ;
  706.    SetRGB4(&(global.blankscreen->ViewPort), 1L, (long)(nr >> 3),
  707.                                     (long)(ng >> 3), (long)(nb >> 3)) ;
  708. }
  709. /*
  710.  *   Our actual task, in an infinite loop.
  711.  */
  712. void taskrout() {
  713.    long i ;
  714.    struct Task *task ;
  715.  
  716.    geta4() ;
  717.    task = FindTask(0L) ;
  718.    startlines() ;
  719.    for (i=0; i<MAXLINES; i++) {
  720.       advancelines() ;
  721.       drawnew() ;
  722.       if (SetSignal(0L, 0L))
  723.          goto done ;
  724.    }
  725.    colors() ;
  726.    while (SetSignal(0L, 0L)==0) {
  727.       if (task->tc_Node.ln_Pri == 10)
  728.          SetTaskPri(task, -20L) ;
  729.       eraseold() ;
  730.       advancelines() ;
  731.       drawnew() ;
  732.       eraseold() ;
  733.       advancelines() ;
  734.       drawnew() ;
  735.       if (task->tc_Node.ln_Pri == 10)
  736.          SetTaskPri(task, -20L) ;
  737.       eraseold() ;
  738.       advancelines() ;
  739.       drawnew() ;
  740.       eraseold() ;
  741.       advancelines() ;
  742.       drawnew() ;
  743.       if (task->tc_Node.ln_Pri == 10)
  744.          SetTaskPri(task, -20L) ;
  745.       eraseold() ;
  746.       advancelines() ;
  747.       drawnew() ;
  748.       eraseold() ;
  749.       advancelines() ;
  750.       drawnew() ;
  751.       colors() ;
  752.    }
  753. done:
  754.    Signal(global.buddy, 1L << global.replysignum) ;
  755.    Wait(0L) ;
  756. }
  757. /*
  758.  *   Now we do hotkey magic to activate windows, bring them to front,
  759.  *   etc.
  760.  *
  761.  *   Now we have a key, so we have to find a process with that name and
  762.  *   bring her to front.  For now, we just deal with tasks, since the
  763.  *   CLI stuff is so complicated.
  764.  */
  765. #define MAXMATCH (20)
  766. char simplematch[3] = { ' ', '*', 0 } ;
  767. struct Window *matchwindows[MAXMATCH] ;
  768. extern long LockIBase() ;
  769. windowtofront(key, qual)
  770. char key ;
  771. {
  772.    long foo ;
  773.    int i, j ;
  774.    int n ;
  775.    struct Window *w ;
  776.    struct Screen *s ;
  777.    struct Process *p ;
  778.    struct MsgPort **mp ;
  779.    struct CommandLineInterface *CLI ;
  780.    int cli ;
  781.    char *nameptr, *matchptr ;
  782.    extern struct DosLibrary *DOSBase ;
  783.    struct hotkey *hk ;
  784.    int shift, ctrl ;
  785.    struct Window *activewindow ;
  786.  
  787. /*
  788.  *   First we look for a matching record.
  789.  */
  790.    if (key == '.')
  791.       goto goner ;
  792.    shift = ((qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0) ;
  793.    ctrl = ((qual & IEQUALIFIER_CONTROL) != 0) ;
  794.    activewindow = NULL ;
  795.    for (hk=hotkeys; hk; hk=hk->next)
  796.       if (hk->key == key && 
  797.           (hk->flags & SHIFT) == shift)
  798.          break ;
  799.    cli = 0 ;
  800.    if (hk && hk->matchstring)
  801.       matchptr = hk->matchstring ;
  802.    else {
  803.       matchptr = simplematch ;
  804.       if (key == ' ')
  805.          matchptr++ ;
  806.       else if ('A' <= key && key <= 'Z')
  807.          simplematch[0] = key ;
  808.       else if ('0' <= key && key <= '9') {
  809.          cli = key ;
  810.          if (cli == '0')
  811.             cli += 10 ;
  812.          matchptr++ ;
  813.       } else
  814.          goto goner ;
  815.    }
  816.    n = 0 ;
  817.    foo = LockIBase(0L) ;
  818.    if (! ctrl && !(hk && (hk->flags & NOTINTUITION)) && !cli) {
  819.       for (s=IntuitionBase->FirstScreen; s; s=s->NextScreen)
  820.          for (w=s->FirstWindow; w; w=w->NextWindow) {
  821.             if (w->UserPort) {
  822.                p = (struct Process *)(w->UserPort->mp_SigTask) ;
  823.                if (((struct Task *)p)->tc_Node.ln_Type == NT_PROCESS) {
  824.                   if (p->pr_CLI) {
  825.                      CLI = (struct CommandLineInterface *)BSTRtoS(p->pr_CLI) ;
  826.                      if (bstrcmp(BSTRtoS((CLI)->cli_CommandName), matchptr) &&
  827.                          n < MAXMATCH) {
  828.                            if (w==IntuitionBase->ActiveWindow)
  829.                               activewindow = w ;
  830.                            matchwindows[n++] = w ;
  831.                         }
  832.                   } else {
  833.                      if (sstrcmp(((struct Task *)p)->tc_Node.ln_Name, matchptr)
  834.                           && n < MAXMATCH) {
  835.                         if (w==IntuitionBase->ActiveWindow)
  836.                            activewindow = w ;
  837.                         matchwindows[n++] = w ;
  838.                      }
  839.                   }
  840.                }
  841.             }
  842.          }
  843.    }
  844. /*
  845.  *   Folks, there are still several/many windows of vulnerability
  846.  *   here; I'll have to plug them.  For instance, what happens if a
  847.  *   CLI goes away while we are doing this?  Or what happens if a
  848.  *   window goes away later, when we are looking at IntuitionBase?
  849.  */
  850.    if (! ctrl && !(hk && (hk->flags & NOTCLI))) {
  851.       mp = (struct MsgPort **)BSTRtoS(*(DOSBase->dl_Root)) ;
  852.       for (j=1; j<(long)(mp[0]); j++)
  853.          if (mp[j] && (cli == 0 || j == cli - '0')) {
  854.             p = (struct Process *)(mp[j]->mp_SigTask) ;
  855.             CLI = (struct CommandLineInterface *)BSTRtoS(p->pr_CLI) ;
  856.             if (!CLI->cli_Background &&
  857.                   bstrcmp(BSTRtoS((CLI)->cli_CommandName), matchptr)) {
  858.                infoptr->id_VolumeNode = NULL ;
  859.                dos_packet(p->pr_ConsoleTask, ACTION_DISK_INFO,
  860.                          ((long)(infoptr)) >> 2, 0L, 0L, 0L, 0L, 0L, 0L) ;
  861.                if (w=(struct Window *)infoptr->id_VolumeNode)
  862.                   if (n < MAXMATCH) {
  863.                      if (w==IntuitionBase->ActiveWindow)
  864.                         activewindow = w ;
  865.                      matchwindows[n++] = w ;
  866.                   }
  867.             }
  868.          }
  869.    }
  870.    if (shift)
  871.       key += 100 ;
  872.    if (ctrl || n==0) {
  873.       UnlockIBase(foo) ;
  874.       if (hk == NULL || hk->startstring == NULL)
  875.          goto goner ;
  876.       Execute(hk->startstring, 0L, 0L) ;
  877.    } else {
  878.       if (n == 1) {
  879.          w = matchwindows[0] ;
  880.       } else {
  881. /*
  882.  *   This is some real neat code.  We want to find the next window,
  883.  *   that is, the window with the least address greater than the
  884.  *   currently active window, unless the currently active window
  885.  *   has the highest address, in which case we want to find the
  886.  *   window with the least address.  Why this works is left as a
  887.  *   puzzle for the reader.
  888.  */
  889.          if (activewindow) {
  890.             w = activewindow ;
  891.             for (j=0; j<n; j++)
  892.                if ((w > activewindow) ^
  893.                    (w > matchwindows[j]) ^
  894.                    (matchwindows[j] > activewindow))
  895.                   w = matchwindows[j] ;
  896.          } else {
  897.             w = NULL ;
  898.             for (j=0; j<n; j++)
  899.                if (lastwindows[key]==matchwindows[j]) {
  900.                   w = lastwindows[key] ;
  901.                   break ;
  902.                }
  903.             if (w==NULL)
  904.                w = matchwindows[0] ;
  905.          }
  906.       }
  907.       lastwindows[key] = w ;
  908.       s = w->WScreen ;
  909.       UnlockIBase(foo) ;
  910.       ScreenToFront(s) ;
  911. /*
  912.  *   If only one window on screen, don't bring it to front
  913.  *   (mostly for DPaint, but for other progs as well.)
  914.  *   (Anyone know an easy way to see if this window is fully
  915.  *   exposed?)
  916.  */
  917.       if (s->FirstWindow != w || w->NextWindow)
  918.          WindowToFront(w) ;
  919.       ActivateWindow(w) ;
  920.    }
  921.    return ;
  922. goner:
  923.    DisplayBeep(0L) ;
  924. }
  925. /*
  926.  *   These two functions compare a given string `s' with a `key' string.
  927.  *   The key string should be all upper case; this is a case insensitive
  928.  *   match.  If the key string contains `*', this character is assumed to
  929.  *   match the rest of the string (and it can only come at the end.)  We
  930.  *   have a routine for BSTR's, and a routine for regular strings.
  931.  */
  932. int sstrcmp(s, key)
  933. register char *s, *key ;
  934. {
  935.    while (1) {
  936.       if (*key == '*')
  937.          return(1) ;
  938.       if (*key == 0)
  939.          return(*s == 0) ;
  940.       if (*s == 0)
  941.          return(0) ;
  942.       if (*s != *key &&
  943.           (*s != *key + 32 || *s < 'a' || *s > 'z'))
  944.          return(0) ;
  945.       s++ ;
  946.       key++ ;
  947.    }
  948. }
  949. /*
  950.  *   This is the same as above, only instead of using a null to
  951.  *   end the string, we keep track of the number of characters.
  952.  */
  953. int bstrcmp(s, key)
  954. char *s, *key ;
  955. {
  956.    int n ;
  957.  
  958.    n = *(unsigned char *)s++ ;
  959.    while (1) {
  960.       if (*key == '*')
  961.          return(1) ;
  962.       if (*key == 0)
  963.          return(n == 0) ;
  964.       if (n == 0)
  965.          return(0) ;
  966.       if (*s != *key &&
  967.           (*s != *key + 32 || *s < 'a' || *s > 'z'))
  968.          return(0) ;
  969.       s++ ;
  970.       key++ ;
  971.       n-- ;
  972.    }
  973. }
  974. /*
  975.  *   A place to hold an input line.
  976.  */
  977. #define MAXSTARTUPLINE (100)
  978. char startbuf[MAXSTARTUPLINE] ;
  979. char upline[MAXSTARTUPLINE] ;
  980. /*
  981.  *   Is a legit separator of some sort.
  982.  */
  983. int issep(s)
  984. register char s ;
  985. {
  986.    return (s <= ' ' || s == '=' || s == ':' || s == ',' || s == '-') ;
  987. }
  988. /*
  989.  *   Go to next `word' in the startup file.
  990.  */
  991. char *getword(s)
  992. register char *s ;
  993. {
  994.    while (*s && issep(*s))
  995.       s++ ;
  996.    return(s) ;
  997. }
  998. /*
  999.  *   Upper case a string.
  1000.  */
  1001. char *upcase(dest, s)
  1002. char *dest ;
  1003. register char *s ;
  1004. {
  1005.    register char *d = dest ;
  1006.  
  1007.    while (*s) {
  1008.       if ('a' <= *s && *s <= 'z')
  1009.          *d++ = *s++ - 32 ;
  1010.       else
  1011.          *d++ = *s++ ;
  1012.    }
  1013.    *d = 0 ;
  1014.    return(dest) ;
  1015. }
  1016. /*
  1017.  *   Say we got a bad line.
  1018.  */
  1019. badline() {
  1020.    puts("Error in startup file!") ;
  1021.    puts(startbuf) ;
  1022. }
  1023. /*
  1024.  *   Copies a string from one place to another; string delimited by
  1025.  *   double quotes.
  1026.  */
  1027. char *cpystr(dest, src)
  1028. register char *dest, *src ;
  1029. {
  1030.    if (*src != '"')
  1031.       badline() ;
  1032.    else {
  1033.       src++ ;
  1034.       while (*src != '"' && *src != 0) {
  1035.          if (*src == '\\' && src[1] != 0)
  1036.             src++ ;
  1037.          *dest++ = *src++ ;
  1038.       }
  1039.       if (*src)
  1040.          src++ ;
  1041.    }
  1042.    *dest = 0 ;
  1043.    return(getword(src)) ;
  1044. }
  1045. /*
  1046.  *   Handle a single startup line that's not a comment and non-empty
  1047.  *   and been converted to all upper case.
  1048.  */
  1049. parseline(s, msg)
  1050. register char *s ;
  1051. struct OURMSG *msg ;
  1052. {
  1053.    int flags ;
  1054.    short t ;
  1055.    int key ;
  1056.    char *p ;
  1057.    register struct hotkey *hk ;
  1058.  
  1059.    flags = 0 ;
  1060.    if (strncmp(s, "COMMAND", 7)==0) {
  1061.       s = getword(s+7) ;
  1062.       cpystr(msg->cmd, s) ;
  1063.    } else if (strncmp(s, "TIMEOUT", 7)==0) {
  1064.       s = getword(s+7) ;
  1065.       t = 0 ;
  1066.       while ('0' <= *s && *s <= '9')
  1067.          t = t * 10 + *s++ - '0' ;
  1068.       if (t <= 0)
  1069.          t = DEFTIME ;
  1070.       msg->interval = t ;
  1071.    } else if (strncmp(s, "LINES", 5)==0) {
  1072.       msg->draw = 1 ;
  1073.    } else if (strncmp(s, "BLANK", 5)==0) {
  1074.       msg->draw = -1 ;
  1075.    } else {
  1076.       if (strncmp(s, "SHIFT", 5)==0) {
  1077.          flags = SHIFT ;
  1078.          s = getword(s+5) ;
  1079.       }
  1080.       if (*s == 0)
  1081.          badline() ;
  1082.       else {
  1083.          if (issep(s[1]) &&
  1084.              (('A' <= *s && *s <= 'Z') ||
  1085.               ('0' <= *s && *s <= '9'))) {
  1086.             key = *s ;
  1087.             s = getword(s+1) ;
  1088.          } else if (strncmp(s, "SPACE", 5)==0) {
  1089.             key = ' ' ;
  1090.             s = getword(s+5) ;
  1091.          } else if (*s == 'F' && ('1' <= s[1] && s[1] <= '9')) {
  1092.             s++ ;
  1093.             t = *s++ - '0' ;
  1094.             if (t == 1 && *s == '0') {
  1095.                t = 10 ;
  1096.                s++ ;
  1097.             }
  1098.             s = getword(s) ;
  1099.           } else {
  1100.             badline() ;
  1101.             return ;
  1102.          }
  1103.          if (strncmp(s, "INTUITION", 9)==0) {
  1104.             flags |= NOTCLI ;
  1105.             s = getword(s+9) ;
  1106.          } else if (strncmp(s, "CLI", 3)==0) {
  1107.             flags |= NOTINTUITION ;
  1108.             s = getword(s+3) ;
  1109.          }
  1110.          s = cpystr(upline, s) ;
  1111.          p = upline + strlen(upline) + 1 ;
  1112.          if (*s)
  1113.             cpystr(p, startbuf + (s-upline)) ;
  1114.          else
  1115.             *p = 0 ;
  1116.          t = sizeof(struct hotkey) + strlen(p) + strlen(upline) ;
  1117.          hk = AllocMem((long)t, MEMF_CLEAR | MEMF_PUBLIC) ;
  1118.          if (hk) {
  1119.             hk->key = key ;
  1120.             hk->flags = flags ;
  1121.             hk->next = hotkeys ;
  1122.         hk->structlen = t ;
  1123.         hk->matchstring = strcpy(hk->strings, upline) ;
  1124.         hk->startstring = strcpy(hk->strings + strlen(upline) + 1, p) ;
  1125.             if (hk->startstring[0]==0)
  1126.                hk->startstring = NULL ;
  1127.             hotkeys = hk ;
  1128.          } else
  1129.             puts("Out of memory in startup") ;
  1130.       }
  1131.    }
  1132. }
  1133. /*
  1134.  *   Handle the startup file.
  1135.  */
  1136. processstartup(s, msg)
  1137. char *s ;
  1138. struct OURMSG *msg ;
  1139. {
  1140.    FILE *f ;
  1141.    char *p ;
  1142.  
  1143.    if (f=fopen(s, "r")) {
  1144.       while (fgets(startbuf, MAXSTARTUPLINE, f)) {
  1145.          p = getword(startbuf) ;
  1146.          if (*p != '*' && *p != '#' && *p != ';' && *p != 0) {
  1147.             upcase(upline, p) ;
  1148.             parseline(upline, msg) ;
  1149.          }
  1150.       }
  1151.    } else {
  1152.       puts("Couldn't open startup file:") ;
  1153.       puts(s) ;
  1154.    }
  1155. }
  1156. /*
  1157.  *   This stuff down here handles the raw key conversion stuff
  1158.  *   properly.  Thanks to Willy Langeveld and Carolyn Scheppner.
  1159.  */
  1160. char *dos_rkcv();
  1161. int  dos_rkcvinit(), dos_rkcvexit();
  1162. struct IOStdReq ConStdReq;
  1163. /*
  1164.  *   This code won't compile under Manx unless you delete the
  1165.  *   `ConsoleDevice' function in functions.h, or perform a kludge
  1166.  *   like the one I did when I included it.  Why the hell does
  1167.  *   Manx have that in there?  If you try to use it, it comes out
  1168.  *   undefined, but if you rename the following, it won't link
  1169.  *   because it needs the function `ConsoleDevice'.
  1170.  */
  1171. long ConsoleDevice ;
  1172. /**
  1173. *
  1174. *  Calling sequence:
  1175. *  =================
  1176. *
  1177. *    result = (char *) dos_rkcv(code, buffer, length);
  1178. *
  1179. *  Description:
  1180. *  ============
  1181. *
  1182. *    Covert raw key number to array of console device ascii text
  1183. *    using the default keymap.
  1184. *
  1185. *  Inputs:
  1186. *  =======
  1187. *
  1188. *    int code        Raw key number.
  1189. *    int qual        Qualifier.
  1190. *    char *buffer        Pointer to an array of char to receive the
  1191. *                conversion.
  1192. *    int length        length of buffer.
  1193. *
  1194. *  Outputs:
  1195. *  ========
  1196. *
  1197. *    F. value:        NULL on conversion failure, or pointer to
  1198. *                buffer on success.
  1199. *
  1200. **/
  1201. char *dos_rkcv(code, qual, buffer, length)
  1202. int code;
  1203. int qual;
  1204. char *buffer;
  1205. int length;
  1206. {
  1207.    static struct InputEvent event;
  1208.  
  1209.    event.ie_Class = IECLASS_RAWKEY;
  1210.    event.ie_Code = code;
  1211.    event.ie_Qualifier = qual;
  1212.  
  1213.    if (RawKeyConvert(&event, buffer, (long) length, NULL) == 0L) return(0L);
  1214.  
  1215.    return(buffer);
  1216. }
  1217.  
  1218. /**
  1219. *
  1220. *  Calling sequence:
  1221. *  =================
  1222. *
  1223. *    error = dos_rkcvinit();
  1224. *
  1225. *  Description:
  1226. *  ============
  1227. *
  1228. *    Open the Console device for later use with dos_rkcv().
  1229. *
  1230. *  Inputs:
  1231. *  =======
  1232. *
  1233. *    None
  1234. *
  1235. *  Outputs:
  1236. *  ========
  1237. *
  1238. *    F. value:        1 on failure, zero otherwise.
  1239. *                
  1240. *
  1241. **/
  1242. int dos_rkcvinit()
  1243. {
  1244.    if (OpenDevice("console.device", -1L, &ConStdReq, 0L) != NULL) {
  1245.       ConsoleDevice = 0L;
  1246.       return(1);
  1247.    }
  1248.    else {
  1249.       ConsoleDevice = (long) ConStdReq.io_Device;
  1250.       return(0);
  1251.    }
  1252. }
  1253.  
  1254. /**
  1255. *
  1256. *  Calling sequence:
  1257. *  =================
  1258. *
  1259. *    error = dos_rkcvexit();
  1260. *
  1261. *  Description:
  1262. *  ============
  1263. *
  1264. *    Close the Console device after use with dos_rkcv().
  1265. *
  1266. *  Inputs:
  1267. *  =======
  1268. *
  1269. *    None
  1270. *
  1271. *  Outputs:
  1272. *  ========
  1273. *
  1274. *    F. value:        Always zero;
  1275. *                
  1276. **/
  1277. int dos_rkcvexit()
  1278. {
  1279.    if (ConsoleDevice) CloseDevice(&ConStdReq);
  1280.    return(0);
  1281. }
  1282. /*
  1283.  *   Set up the key conversion table.  Note that the buffer has to be
  1284.  *   long word aligned!
  1285.  */
  1286. initkeytoasc() {
  1287.    register int i ;
  1288.    char buf[100] ;
  1289.  
  1290.    for (i=0; i<128; i++)
  1291.       keytoasc[i] = '.' ;
  1292.    if (dos_rkcvinit())
  1293.       return(1) ;
  1294.    for (i=0; i<128; i++) {
  1295.       buf[1] = 0 ;
  1296.       if (dos_rkcv(i, 0, buf, 100) && buf[1] == 0 &&
  1297.           (buf[0] == ' ' ||
  1298.            ('a' <= buf[0] && buf[0] <= 'z' && (buf[0] -= 32)) ||
  1299.            ('0' <= buf[0] && buf[0] <= '9'))) {
  1300.          keytoasc[i] = buf[0] ;
  1301.       }
  1302.    }
  1303. /*
  1304.  *   Have to handle the function keys separately
  1305.  */
  1306.    for (i=80; i<90; i++)
  1307.       keytoasc[i] = i-79 ;
  1308.    dos_rkcvexit() ;
  1309.    return(0) ;
  1310. }
  1311.