home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 492.lha / altmenu_v1.0 / altmenu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-04-06  |  18.7 KB  |  717 lines

  1. /*
  2. ** AltMenu - the keyboard menu replacement doohicky
  3. **
  4. ** Version 1.0        10/14/89
  5. ** Authors: E. A. Hutchins and L. J. Rittle
  6. **
  7. ** Credits: Many basic input event handling routines and ideas blatantly
  8. **        lifted from:
  9. **
  10. ** NewPOP which is based upon POPCLI,
  11. **
  12. ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  13. ** |_o_o|\\ Copyright (c) 1986 The Software Distillery.  All Rights Reserved *
  14. ** |. o.| || This program may not be distributed without the permission of   *
  15. ** | .  | || the authors.                                                    *
  16. ** | o  | ||    Dave Baker     Ed Burnette  Stan Chow    Jay Denebeim        *
  17. ** |  . |//     Gordon Keener  Jack Rouse   John Toebes  Doug Walker         *
  18. ** ======          BBS:(919)-471-6436      VOICE:(919)-469-4210              * 
  19. ** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  20. **
  21. ** which is VERY loosely based on the input.device example by Rob Peck, 12/1/85
  22. **
  23. ** NewPOP additions and modifications Copyright © 1989 Loren J. Rittle. 
  24. **
  25. ** As stated in the original POPCLI documentation file about POPCLI:
  26. **
  27. ** Permission is hereby granted to distribute this program provided 
  28. ** both the documentation accompanies the executable and that no 
  29. ** charge is made for its distribution.
  30. **
  31. **
  32. **
  33. ** History:
  34. **    EAH&LJR    10/14    While chatting about Amiga problems, Ed points out that
  35. **            it would sure be nice if one could navigate through
  36. **            menus with out picking up the mouse. I finally see the
  37. **            light and agree, thus AltMenu is born!
  38. **    EAH&LJR 10/14    Started version 1.0 with the intent of getting it done
  39. **            in one flurry of Amiga hacking.
  40. **    EAH    10/14    Finished version 1.0! 
  41. **            (Loren sleeping at the great momment)
  42. **    LJR    10/14    Changed the priority to run us at from -20 to 19 in
  43. **            order to clean up the order in which output is displayed
  44. **            on the screen. (No more prompt then our output!)
  45. **    LJR    10/14    Added nice HELLO and START messages.
  46. **    LJR    10/14    Fixed problem with DMouse by just making sure that
  47. **            DMouse's input handler has a higher priority than
  48. **            ours.
  49. **    EAH    10/21    Added direct key jumps.
  50. */
  51.  
  52. /*
  53. ** Includes
  54. */
  55.  
  56. #include <exec/types.h>
  57. #include <exec/exec.h>
  58. #include <devices/input.h>
  59. #include <devices/inputevent.h>
  60. #include <intuition/intuition.h>
  61. #include <intuition/intuitionbase.h>
  62. #include <proto/dos.h>
  63. #include <proto/exec.h>
  64. #include <proto/intuition.h>
  65. #include <proto/console.h>
  66. #include <string.h>
  67.  
  68. /*
  69. ** Defines
  70. */
  71.  
  72. #define ALTMENU_PRIORITY 55
  73.  
  74. #define PORTNAME         "AltMenu.port"
  75. #define HELLOMSG    "\x9B" "0;33mAltMenu\x9B" "0m by E. A. Hutchins and L. J. Rittle\n" \
  76.                  "Version 1.0  Copyright \xA9 1989  All Rights Reserved.\n"
  77. #define STARTMSG    "AltMenu is starting.\n"
  78. #define KILLMSG        "AltMenu is leaving.\n"
  79.  
  80. #define LAST_KEY    (0x4a)
  81.  
  82. #define UP(x)        ((x) | 0x80)
  83. #define RAW_ESC        (0x45)
  84. #define RAW_RETURN    (0x44)
  85. #define RAW_SPACE    (0x40)
  86. #define RAW_UP        (0x4c)
  87. #define RAW_DOWN    (0x4d)
  88. #define RAW_RIGHT    (0x4e)
  89. #define RAW_LEFT    (0x4f)
  90. #define RAW_LALT    (0x64)
  91. #define RAW_RALT    (0x65)
  92. #define EXTQUAL        (0x70cf)
  93.  
  94. #define SCRN        (gptr->Scrn)
  95. #define ROOT        (gptr->Root)
  96. #define MENU        (gptr->Menu)
  97. #define menu        (gptr->_menu)
  98. #define MID        (gptr->MidItem)
  99. #define SUB        (gptr->SubItem)
  100. #define item        (gptr->_item)
  101. #define mtmp        ((struct Menu *)(gptr->_mtmp))
  102. #define itmp        ((struct MenuItem *)(gptr->_mtmp))
  103. #define WHERE        (gptr->where)
  104. #define MENUX        (gptr->MenuX)
  105. #define MENUY        (gptr->MenuY)
  106. #define EVT        (gptr->Evt)
  107. #define GETKEY(x)    ((gptr->Key)=((gptr->RawKeyMap)[(UBYTE)(x)]))
  108. #define KEY        (gptr->Key)
  109. #define NAME        (gptr->Name)
  110. #define UPPER(x)    (((x) >= 'a' && (x) <= '~')?((x)-'a'+'A'):(x))
  111. #define MX        (ep->ie_X)
  112. #define MY        (ep->ie_Y)
  113. #define GLOBALMOUSE    ((gptr->MouseX=MX),(gptr->MouseY=MY),(MX=((MX*gptr->XMul)-(gptr->IBase->MouseX))),(MY=((MY*gptr->YMul)-(gptr->IBase->MouseY))))
  114. #define ITEXT_OF(x)    (((struct IntuiText *)((x)->ItemFill))->IText)
  115.  
  116. /*
  117. ** Type definitions
  118. */
  119.  
  120. typedef enum { Idle, AltDown, InMenu } States;
  121. typedef enum { Top, Mid, Sub } MenuPos;
  122.  
  123. typedef struct 
  124. {
  125.     struct Task        *buddy;
  126.     struct IntuitionBase    *IBase;
  127.     States            state;
  128.     WORD            OldMouseX, OldMouseY;
  129.     WORD            MouseX, MouseY;
  130.     struct Screen        *Scrn;
  131.     int            XMul, YMul;
  132.     MenuPos            where;
  133.     struct Menu        *Root, *Menu, *_menu;
  134.     struct MenuItem        *MidItem, *SubItem, *_item;
  135.     void            *_mtmp;
  136.     int            MenuX, MenuY;
  137.     struct InputEvent    Evt;
  138.     BYTE            *Name;
  139.     BYTE            Key;
  140.     BYTE            RawKeyMap[LAST_KEY];
  141. } GLOBAL_DATA;
  142.  
  143. /*
  144. ** Global variables
  145. */
  146.  
  147. struct IntuitionBase    *IntuitionBase = NULL;
  148. struct Library        *ConsoleDevice = NULL;
  149.  
  150. extern BPTR _Backstdout;          /* standard output when run in background */
  151. long  _BackGroundIO = 1;          /* Flag to tell it we want to do I/O      */
  152. long  _stack = 4000;              /* Amount of stack space our task needs   */
  153. char *_procname = "AltMenu";      /* The name of the task to create         */
  154. long  _priority = 19;             /* The priority to run us at              */
  155.  
  156. /*
  157. ** Prototypes
  158. */
  159.  
  160. struct MsgPort         *FindPort();
  161. struct MsgPort         *CreatePort();
  162. void             DeletePort();
  163. struct IOStdReq        *CreateIOReq(struct MsgPort *, int);
  164. void             DeleteIOReq(struct IOStdReq *);
  165.  
  166. /*
  167. ** myhandler - our awesome input event handler
  168. */
  169.  
  170. __regargs struct InputEvent *myhandler( struct InputEvent *ev, register GLOBAL_DATA *gptr )
  171. {
  172.     register struct InputEvent *ep;
  173.  
  174.        for (ep = ev; ep != NULL; ep = ep->ie_NextEvent)
  175.        {
  176.         if (ep->ie_Class == IECLASS_TIMER ||
  177.             ep->ie_Class == IECLASS_NULL)
  178.             continue;
  179.  
  180.         if (gptr->state == InMenu)
  181.         {
  182.             if (ep->ie_Class == IECLASS_RAWKEY)
  183.             {
  184.                 switch (ep->ie_Code)
  185.                 {
  186.                 case UP(RAW_ESC):
  187.                 case RAW_LALT:
  188.                 case RAW_RALT:
  189.                     gptr->MouseX = SCRN->LeftEdge;
  190.                     gptr->MouseY = SCRN->TopEdge;
  191.                     /* fall through */
  192.                 case UP(RAW_RETURN):
  193.                     MX = gptr->MouseX;
  194.                     MY = gptr->MouseY;
  195.                     ep->ie_Class = IECLASS_RAWMOUSE;
  196.                     ep->ie_Code = UP(IECODE_RBUTTON);
  197.                     ep->ie_Qualifier = 0x8000; /* relmouse */
  198.                     GLOBALMOUSE;
  199.                     gptr->state = Idle;
  200.                     continue;
  201.                 case RAW_SPACE:
  202.                     MX = gptr->MouseX;
  203.                     MY = gptr->MouseY;
  204.                     ep->ie_Class = IECLASS_RAWMOUSE;
  205.                     ep->ie_Code = IECODE_LBUTTON;
  206.                     ep->ie_Qualifier = 0xc000; /* relmouse | lbutton */
  207.                     GLOBALMOUSE;
  208.                     continue;
  209.                 case UP(RAW_SPACE):
  210.                     MX = gptr->MouseX;
  211.                     MY = gptr->MouseY;
  212.                     ep->ie_Class = IECLASS_RAWMOUSE;
  213.                     ep->ie_Code = UP(IECODE_LBUTTON);
  214.                     ep->ie_Qualifier = 0x8000; /* relmouse */
  215.                     GLOBALMOUSE;
  216.                     continue;
  217.                 case RAW_UP:
  218.                     switch (WHERE)
  219.                     {
  220.                     case Top:
  221.                         if ((MID = MENU->FirstItem) == NULL) goto EatMe;
  222.                         WHERE = Mid;
  223.                         while (MID->NextItem != NULL)
  224.                             MID = MID->NextItem;
  225.                         break;
  226.                     case Mid:
  227.                         if ((item = MENU->FirstItem) == MID)
  228.                         {
  229.                             WHERE = Top;
  230.                             break;
  231.                         }
  232.                         while (item->NextItem != NULL && item->NextItem != MID)
  233.                             item = item->NextItem;
  234.                         MID = item;
  235.                         break;
  236.                     case Sub:
  237.                         if ((item = MID->SubItem) == SUB)
  238.                         {
  239.                             while (SUB->NextItem != NULL)
  240.                                 SUB = SUB->NextItem;
  241.                             break;
  242.                         }
  243.                         while (item->NextItem != NULL && item->NextItem != SUB)
  244.                             item = item->NextItem;
  245.                         SUB = item;
  246.                         break;
  247.                     }
  248.                     break;
  249.                 case RAW_DOWN:
  250.                     switch (WHERE)
  251.                     {
  252.                     case Top:
  253.                         if ((MID = MENU->FirstItem) == NULL) goto EatMe;
  254.                         WHERE = Mid;
  255.                         break;
  256.                     case Mid:
  257.                         if (MID->NextItem != NULL)
  258.                             MID = MID->NextItem;
  259.                         else
  260.                             MID = MENU->FirstItem;
  261.                         break;
  262.                     case Sub:
  263.                         if (SUB->NextItem != NULL)
  264.                             SUB = SUB->NextItem;
  265.                         else
  266.                             SUB = MID->SubItem;
  267.                         break;
  268.                     }
  269.                     break;
  270.                 case RAW_LEFT:
  271.                     switch (WHERE)
  272.                     {
  273.                     case Mid:
  274.                         WHERE = Top;
  275.                         /* fall through */
  276.                     case Top:
  277.                         if (MENU == (menu = ROOT))
  278.                             while (MENU->NextMenu != NULL) MENU = MENU->NextMenu;
  279.                         else
  280.                         {
  281.                             while (menu->NextMenu != NULL && menu->NextMenu != MENU) menu = menu->NextMenu;
  282.                             MENU = menu;
  283.                         }
  284.                         break;
  285.                     case Sub:
  286.                         WHERE = Mid;
  287.                         break;
  288.                     }
  289.                     break;
  290.                 case RAW_RIGHT:
  291.                     switch (WHERE)
  292.                     {
  293.                     case Mid:
  294.                         if (MID->SubItem != NULL)
  295.                         {
  296.                             WHERE = Sub;
  297.                             SUB = MID->SubItem;
  298.                             break;
  299.                         }
  300.                         /* fall through */
  301.                     case Sub:
  302.                         WHERE = Top;
  303.                         /* fall through */
  304.                     case Top:
  305.                         if (MENU->NextMenu != NULL)
  306.                             MENU = MENU->NextMenu;
  307.                         else
  308.                             MENU = ROOT;
  309.                         break;
  310.                     }
  311.                     break;
  312.                 default:
  313.                     if (((UBYTE)(ep->ie_Code)) > LAST_KEY) goto EatMe;
  314.                     GETKEY( ep->ie_Code );
  315.                     if (KEY == 0) goto EatMe;
  316.                     /* find the menu name */
  317.                     switch (WHERE)
  318.                     {
  319.                     case Top:
  320.                         mtmp = NULL;
  321.                         menu = MENU;
  322.                         do {
  323.                             NAME = menu->MenuName;
  324.                             while (*NAME == ' ') ++NAME;
  325.                             if (KEY == UPPER( *NAME ))
  326.                             {
  327.                                 if (mtmp != NULL)
  328.                                 {
  329.                                     if (mtmp == MENU) mtmp = menu;
  330.                                     break;
  331.                                 }
  332.                                 mtmp = menu;
  333.                             }
  334.                             menu = menu->NextMenu;
  335.                             if (menu == NULL) menu = ROOT;
  336.                         } while (menu != MENU);
  337.                         /* no matches? */
  338.                         if (mtmp == NULL) goto EatMe;
  339.                         /* only one match? */
  340.                         if (menu == MENU)
  341.                         {
  342.                             MID = mtmp->FirstItem;
  343.                             if (MENU == mtmp && MID != NULL)
  344.                                 WHERE = Mid;
  345.                         }
  346.                         MENU = mtmp;
  347.                         break;
  348.                     case Mid:
  349.                         itmp = NULL;
  350.                         item = MID;
  351.                         do {
  352.                             if (item->Flags & ITEMTEXT)
  353.                             {
  354.                                 NAME = ITEXT_OF(item);
  355.                                 while (*NAME == ' ') ++NAME;
  356.                                 if (KEY == UPPER( *NAME ))
  357.                                 {
  358.                                     if (itmp != NULL)
  359.                                     {
  360.                                         if (itmp == MID) itmp = item;
  361.                                         break;
  362.                                     }
  363.                                     itmp = item;
  364.                                 }
  365.                             }
  366.                             item = item->NextItem;
  367.                             if (item == NULL) item = MENU->FirstItem;
  368.                         } while (item != MID);
  369.                         /* no matches? */
  370.                         if (itmp == NULL) goto EatMe;
  371.                         /* only one match? */
  372.                         if (item == MID)
  373.                         {
  374.                             SUB = itmp->SubItem;
  375.                             if (MID == itmp)
  376.                             {
  377.                                 if (SUB != NULL)
  378.                                     WHERE = Sub;
  379.                                 else
  380.                                 {
  381.                                     EVT.ie_NextEvent = ep->ie_NextEvent;
  382.                                     EVT.ie_Class = IECLASS_RAWKEY;
  383.                                     EVT.ie_SubClass = 0;
  384.                                     EVT.ie_Qualifier = 0;
  385.                                     EVT.ie_Code = UP(RAW_RETURN);
  386.                                     ep->ie_NextEvent = &EVT;
  387.                                 }
  388.                             }
  389.                         }
  390.                         MID = itmp;
  391.                         break;
  392.                     case Sub:
  393.                         itmp = NULL;
  394.                         item = SUB;
  395.                         do {
  396.                             if (item->Flags & ITEMTEXT)
  397.                             {
  398.                                 NAME = ITEXT_OF(item);
  399.                                 while (*NAME == ' ') ++NAME;
  400.                                 if (KEY == UPPER( *NAME ))
  401.                                 {
  402.                                     if (itmp != NULL)
  403.                                     {
  404.                                         if (itmp == SUB) itmp = item;
  405.                                         break;
  406.                                     }
  407.                                     itmp = item;
  408.                                 }
  409.                             }
  410.                             item = item->NextItem;
  411.                             if (item == NULL) item = MID->SubItem;
  412.                         } while (item != SUB);
  413.                         /* no matches? */
  414.                         if (itmp == NULL) goto EatMe;
  415.                         /* only one match? */
  416.                         if (item == SUB && SUB == itmp)
  417.                         {
  418.                             EVT.ie_NextEvent = ep->ie_NextEvent;
  419.                             EVT.ie_Class = IECLASS_RAWKEY;
  420.                             EVT.ie_SubClass = 0;
  421.                             EVT.ie_Qualifier = 0;
  422.                             EVT.ie_Code = UP(RAW_RETURN);
  423.                             ep->ie_NextEvent = &EVT;
  424.                         }
  425.                         SUB = itmp;
  426.                         break;
  427.                     }
  428.                     break;
  429.                 EatMe:
  430.                     ep->ie_Class = IECLASS_NULL;
  431.                     continue;
  432.                 }
  433.  
  434.                 /* move the mouse cursor on top of the item */
  435.  
  436.                 switch (WHERE)
  437.                 {
  438.                 case Top:
  439.                     MX = SCRN->LeftEdge + MENU->LeftEdge + MENU->Width - 2;
  440.                     MY = SCRN->TopEdge + MENU->Height/2;
  441.                     break;
  442.                 case Mid:
  443.                     MX = MENUX + MENU->LeftEdge + MID->LeftEdge + 2;
  444.                     MY = MENUY + MENU->Height + MID->TopEdge + MID->Height/2;
  445.                     break;
  446.                 case Sub:
  447.                     MX = MENUX + MENU->LeftEdge + MID->LeftEdge + SUB->LeftEdge + SUB->Width - 8;
  448.                     MY = MENUY + MENU->Height + MID->TopEdge + SUB->TopEdge + SUB->Height/2;
  449.                     break;
  450.                 }
  451.                 ep->ie_Class = IECLASS_RAWMOUSE;
  452.                 ep->ie_Code = IECODE_NOBUTTON;
  453.                 ep->ie_Qualifier = 0x8000; /* relmouse */
  454.                 GLOBALMOUSE;
  455.             }
  456.             else if (ep->ie_Class == IECLASS_RAWMOUSE)
  457.             {
  458.                 /* if this is a button up, quit */
  459.                 if (ep->ie_Code != IECODE_NOBUTTON)
  460.                     gptr->state = Idle;
  461.                 else /* otherwise eat 'em for now */
  462.                     ep->ie_Class = IECLASS_NULL;
  463.             }
  464.         }
  465.               else if ((ep->ie_Class == IECLASS_RAWKEY) &&
  466.                   (gptr->state == Idle) &&
  467.                   ((ep->ie_Code == RAW_LALT) || (ep->ie_Code == RAW_RALT)) &&
  468.                   ((ep->ie_Qualifier & EXTQUAL) == 0))
  469.              {
  470.             gptr->state = AltDown;
  471.         }
  472.         else if ((ep->ie_Class == IECLASS_RAWKEY) &&
  473.             (gptr->state == AltDown) &&
  474.                   ((ep->ie_Code == UP(RAW_LALT)) || (ep->ie_Code == UP(RAW_RALT))) &&
  475.                   ((ep->ie_Qualifier & EXTQUAL) == 0))
  476.         {
  477.             /* point at the menu */
  478.             gptr->state = InMenu;
  479.             ROOT = MENU = gptr->IBase->ActiveWindow->MenuStrip;
  480.             SCRN = gptr->IBase->ActiveWindow->WScreen;
  481.             if (ROOT == NULL || SCRN == NULL)
  482.             {
  483.                 gptr->state = Idle;
  484.                 continue;
  485.             }
  486.             gptr->OldMouseX = gptr->IBase->MouseX;
  487.             gptr->OldMouseY = gptr->IBase->MouseY;
  488.             gptr->XMul = (gptr->Scrn->ViewPort.Modes & HIRES) ? 1 : 2;
  489.             gptr->YMul = (gptr->Scrn->ViewPort.Modes & LACE) ? 1 : 2;
  490.             MENUX = SCRN->LeftEdge + SCRN->MenuHBorder;
  491.             MENUY = SCRN->TopEdge + SCRN->MenuVBorder;
  492.             /* fix for non-standard menus */
  493.             if (MENU->Height == 0) MENUY += SCRN->BarHeight;
  494.             WHERE = Top;
  495.             MX = SCRN->LeftEdge + MENU->LeftEdge + MENU->Width - 2;
  496.             MY = SCRN->TopEdge + MENU->Height/2;
  497.             ep->ie_Class = IECLASS_RAWMOUSE;
  498.             ep->ie_Code = IECODE_RBUTTON;
  499.             ep->ie_Qualifier = 0xa000; /* relmouse | rbutton */
  500.             GLOBALMOUSE;
  501.         }
  502.         else gptr->state = Idle;
  503.     }
  504.     return(ev);
  505. }
  506.  
  507. /*
  508. ** GetRawKeyMap - get the raw key conversion lookup table
  509. */
  510.  
  511. void GetRawKeyMap( GLOBAL_DATA *gptr )
  512. {
  513.     BYTE            key;
  514.     BYTE            Ascii[16];
  515.     struct InputEvent    ev;
  516.  
  517.     for (key = 0; key <= LAST_KEY; ++key)
  518.     {
  519.         ev.ie_NextEvent = NULL;
  520.         ev.ie_Class = IECLASS_RAWKEY;
  521.         ev.ie_SubClass = 0;
  522.         ev.ie_Qualifier = 0;
  523.  
  524.         ev.ie_Code = key;
  525.         RawKeyConvert( &ev, Ascii, sizeof( Ascii ), NULL );
  526.         (gptr->RawKeyMap)[key] = UPPER( Ascii[0] );
  527.     }
  528. }
  529.  
  530. /*
  531. ** Main entry point
  532. */
  533.  
  534. void _main( char *cmd )
  535. {
  536.     int            stay = 0;
  537.     struct MsgPort        *port;
  538.     struct MsgPort        *DevPort = NULL;
  539.     struct Message         *msg = NULL;
  540.     struct IOStdReq        *inputRequestBlock = NULL;
  541.     struct IOStdReq        *conRequestBlock = NULL;
  542.     struct Interrupt    handlerStuff;
  543.     GLOBAL_DATA        global;
  544.  
  545.     if (_Backstdout) Write( _Backstdout, HELLOMSG, sizeof(HELLOMSG) );
  546.  
  547.     /* now see if we are already installed */
  548.     if ((port = FindPort( PORTNAME )) == NULL) 
  549.     {
  550.         /* remember to hang around when we are done */
  551.         stay = 1;
  552.         /* not installed, we need to install our own port */
  553.         if ((port = CreatePort( PORTNAME, 0 )) == NULL) goto abort;
  554.         if (_Backstdout)
  555.             Write( _Backstdout, STARTMSG, sizeof(STARTMSG) );
  556.     }
  557.  
  558.     /* if we were run from CLI then process parameters */
  559.     if (cmd && *cmd)
  560.     {
  561.         /* skip over any leading spaces in the command line */
  562.         while (*cmd && *cmd != '-') cmd++;
  563.  
  564.         /* see if they are trying to kill us. */
  565.         if (*cmd == '-' && cmd[1] == 'q')
  566.         {
  567.             if ((msg = (struct Message *)
  568.                 AllocMem( sizeof(struct Message), MEMF_CLEAR|MEMF_PUBLIC)) == NULL )
  569.                 goto abort;
  570.             msg->mn_Length = sizeof(struct Message);
  571.             PutMsg( port, msg );
  572.             msg = NULL;
  573.  
  574.             if (_Backstdout)
  575.                 Write( _Backstdout, KILLMSG, sizeof(KILLMSG) );
  576.         }
  577.     }
  578.  
  579.     if (!stay) goto abort;
  580.  
  581.     /* Let the original window go away */
  582.     if (_Backstdout) Close( _Backstdout );
  583.     _Backstdout = NULL;
  584.  
  585.     if (((DevPort = CreatePort( NULL, 0 )) == NULL)    ||
  586.         ((inputRequestBlock = CreateIOReq( DevPort, sizeof(struct IOStdReq) )) == NULL)     ||
  587.         ((conRequestBlock = CreateIOReq( DevPort, sizeof(struct IOStdReq) )) == NULL)     ||
  588.         ((IntuitionBase = (struct IntuitionBase *)OpenLibrary( "intuition.library", 0 )) == NULL)      ||
  589.           OpenDevice( "input.device", 0, (struct IORequest *)inputRequestBlock, 0 )    ||
  590.           OpenDevice( "console.device", -1, (struct IORequest *)conRequestBlock, 0 ))
  591.         goto abort;
  592.  
  593.     /* for using RawKeyConvert */
  594.     ConsoleDevice = (struct Library *)conRequestBlock->io_Device;
  595.     if (ConsoleDevice == NULL) goto abort;
  596.  
  597.     GetRawKeyMap( &global );
  598.     global.buddy = FindTask( NULL );
  599.     global.IBase = IntuitionBase;
  600.     global.state = Idle;
  601.  
  602.     handlerStuff.is_Data = (APTR)&global;
  603.        handlerStuff.is_Code = (VOID (*)()) myhandler;
  604.        handlerStuff.is_Node.ln_Pri = ALTMENU_PRIORITY;
  605.  
  606.     inputRequestBlock->io_Command = IND_ADDHANDLER;
  607.        inputRequestBlock->io_Data    = (APTR)&handlerStuff;
  608.     DoIO( inputRequestBlock );
  609.  
  610.     WaitPort( port );
  611.     msg = GetMsg( port );
  612.  
  613. abort:
  614.     if (msg != NULL) FreeMem( (char *)msg, msg->mn_Length );
  615.  
  616.        if (conRequestBlock != NULL)
  617.           {
  618.               if (conRequestBlock->io_Device != NULL)
  619.                  CloseDevice( (struct IORequest *)conRequestBlock );
  620.               DeleteIOReq( conRequestBlock );
  621.           }
  622.  
  623.        if (inputRequestBlock != NULL)
  624.           {
  625.               if (inputRequestBlock->io_Device != NULL)
  626.              {
  627.                  inputRequestBlock->io_Command = IND_REMHANDLER;
  628.                  inputRequestBlock->io_Data = (APTR)&handlerStuff;
  629.                  DoIO( (struct IORequest *)inputRequestBlock );
  630.                  CloseDevice( (struct IORequest *)inputRequestBlock );
  631.              }
  632.               DeleteIOReq( inputRequestBlock );
  633.           }
  634.  
  635.        if (IntuitionBase != NULL)      CloseLibrary( (struct Library *)IntuitionBase );
  636.        if (DevPort != NULL)           DeletePort( DevPort );
  637.        if (_Backstdout)                Close( _Backstdout );
  638.        if (stay && (port != NULL))     DeletePort( port );
  639. }
  640.  
  641. /*
  642. ** No nutty memory cleanup needed!
  643. */
  644.  
  645. void MemCleanup( void )
  646. {
  647. }
  648.  
  649. /*
  650. ** CreatePort - create a message port
  651. */
  652.  
  653. struct MsgPort *CreatePort( name, pri )
  654. char *name;
  655. int pri;
  656. {
  657.        UBYTE             sigbit;
  658.        register struct MsgPort *port;
  659.  
  660.        if ((sigbit = AllocSignal(-1)) == -1) return( NULL );
  661.     if ((port = (struct MsgPort *)AllocMem( sizeof( struct MsgPort ), MEMF_CLEAR|MEMF_PUBLIC)) == NULL)
  662.           {
  663.               FreeSignal( sigbit );
  664.               return( NULL );
  665.           }
  666.  
  667.        port->mp_Node.ln_Name = name;
  668.        port->mp_Node.ln_Pri = pri;
  669.        port->mp_Node.ln_Type = NT_MSGPORT;
  670.        port->mp_Flags = PA_SIGNAL;
  671.        port->mp_SigBit = sigbit;
  672.        port->mp_SigTask = (struct Task *)FindTask( NULL );
  673.        AddPort( port );
  674.        return( port );
  675. }
  676.  
  677. /*
  678. ** DeletePort - delete an allocated message port
  679. */
  680.  
  681. void DeletePort( struct MsgPort *port )
  682. {
  683.     RemPort( port );
  684.     FreeSignal( port->mp_SigBit );
  685.     FreeMem( (char *)port,sizeof(struct MsgPort) );
  686. }
  687.  
  688. /*
  689. ** CreateIOReq - create an i/o request block
  690. */
  691.  
  692. struct IOStdReq *CreateIOReq( struct MsgPort *port, int size )
  693. {
  694.        struct IOStdReq *ioReq;
  695.  
  696.        if ((ioReq = (struct IOStdReq *)AllocMem( size, MEMF_CLEAR | MEMF_PUBLIC )) != NULL)
  697.           {
  698.               ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
  699.               ioReq->io_Message.mn_Node.ln_Pri  = 0;
  700.               ioReq->io_Message.mn_Length       = size;
  701.               ioReq->io_Message.mn_ReplyPort    = port;
  702.           }
  703.        return( ioReq );
  704. }
  705.  
  706. /*
  707. ** DeleteIOReq - delete an allocated i/o block
  708. */
  709.  
  710. void DeleteIOReq( struct IOStdReq *ioReq )
  711. {
  712.     ioReq->io_Message.mn_Node.ln_Type = 0xff;
  713.     ioReq->io_Device = (struct Device *) -1;
  714.     ioReq->io_Unit = (struct Unit *) -1;
  715.     FreeMem( (char *)ioReq, ioReq->io_Message.mn_Length );
  716. }
  717.