home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / commod / altmenu.lha / AltMenuCom.c < prev    next >
C/C++ Source or Header  |  1992-05-23  |  16KB  |  764 lines

  1. /*======================================================*/
  2. /*                                                                                                            */
  3. /* Small and efficient commodity to simulate the                */
  4. /* MS-Windows(TM) way of walking through the menus            */
  5. /* with the arrow keys.                                                                    */
  6. /* (Tab size 2)                                                                                    */
  7. /*                                                                                                            */
  8. /* © Copyright 1992, Jorrit Tyberghein                                    */
  9. /*                                                                                                            */
  10. /*======================================================*/
  11.  
  12.  
  13. #include <exec/types.h>
  14. #include <exec/memory.h>
  15. #include <exec/interrupts.h>
  16. #include <devices/input.h>
  17. #include <devices/inputevent.h>
  18. #include <dos/dos.h>
  19. #include <pragmas/exec.h>
  20. #include <pragmas/dos.h>
  21. #include <pragmas/intuition.h>
  22. #include <pragmas/keymap.h>
  23. #include <pragmas/input.h>
  24. #include <pragmas/commodities.h>
  25. #include <pragmas/icon.h>
  26. #include <intuition/intuitionbase.h>
  27. #include <string.h>
  28. #include <ctype.h>
  29. #include <libraries/commodities.h>
  30. #include <workbench/workbench.h>
  31.  
  32. /* Input handler and commodity stuff */
  33. struct MsgPort *InputMP;
  34. struct MsgPort *CxPort;
  35. struct Library *CxBase;
  36. struct Library *InputBase;
  37. struct Interrupt Handler;
  38. struct IOStdReq *InputIO;
  39. struct RDArgs *RDArgs;
  40. CxObj *Broker;
  41.  
  42. /* Some library bases */
  43. extern APTR DOSBase;
  44. APTR KeymapBase;
  45. struct IntuitionBase *IntuitionBase;
  46. struct Library *IconBase;
  47.  
  48. /* Commandline arguments */
  49. ULONG *ArgsArray[6];
  50.  
  51. /* Success code for OpenDevice */
  52. LONG Device = -1;
  53.  
  54. /* Raw key codes */
  55. #define CODE_LEFT            0x4f
  56. #define CODE_RIGHT        0x4e
  57. #define CODE_UP                0x4c
  58. #define CODE_DOWN            0x4d
  59. #define CODE_ENTER        0x43
  60. #define CODE_RETURN        0x44
  61. #define CODE_SPACE        0x40
  62. #define CODE_HELP            0x5f
  63.  
  64.  
  65. /* External handler routine */
  66. struct InputEvent *handler ();
  67.  
  68. /* Our broker */
  69. struct NewBroker NewBroker =
  70.     {
  71.         NB_VERSION,"AltMenu",
  72.         "AltMenu 1.0, © 1992 Jorrit Tyberghein",
  73.         "Use arrows to navigate in menus",
  74.         NBU_UNIQUE,0,0,0,0
  75.     };
  76.  
  77.  
  78. /* Message used to pass some information from input handler to main program */
  79. struct SpecMsg
  80.     {
  81.         struct Message msg;
  82.         WORD Code;
  83.         WORD Qualifier;
  84.         WORD Class;
  85.     };
  86.  
  87. /* Global data used to pass information from main program to input handler */
  88. struct GlobData
  89.     {
  90.         ULONG peek,qual;
  91.         int EveryKey;
  92.         WORD Enable;
  93.         int IsAlt;
  94.         struct MsgPort *Port;
  95.     };
  96.  
  97. struct GlobData volatile glob = { 0,0,0,TRUE,0,NULL };
  98.  
  99.  
  100. /*
  101.  * Clean everything and release all memory
  102.  */
  103. void __regargs CloseStuff (UWORD code)
  104. {
  105.     if (Broker) DeleteCxObj (Broker);
  106.     if (CxPort) DeleteMsgPort (CxPort);
  107.     if (RDArgs) FreeArgs (RDArgs);
  108.     if (!Device) CloseDevice (InputIO);
  109.     if (InputIO) DeleteExtIO (InputIO);
  110.     if (InputMP) DeleteMsgPort (InputMP);
  111.     if (glob.Port) DeleteMsgPort (glob.Port);
  112.     if (IconBase) CloseLibrary (IconBase);
  113.     if (CxBase) CloseLibrary (CxBase);
  114.     if (IntuitionBase) CloseLibrary (IntuitionBase);
  115.     if (KeymapBase) CloseLibrary ((struct Library *)KeymapBase);
  116.     XCEXIT (code);
  117. }
  118.  
  119.  
  120. /*
  121.  * Open everything
  122.  */
  123. void OpenStuff (void)
  124. {
  125.     if (!(IconBase = (struct IconBase *)OpenLibrary ("icon.library",37)))
  126.         CloseStuff (10);
  127.     if (!(IntuitionBase = (struct IntuitionBase *)OpenLibrary ("intuition.library",37)))
  128.         CloseStuff (10);
  129.     if (!(CxBase = (struct CxBase *)OpenLibrary ("commodities.library",37)))
  130.         CloseStuff (10);
  131.     if (!(KeymapBase = (APTR)OpenLibrary ("keymap.library",37)))
  132.         CloseStuff (10);
  133.     if (!(InputMP = (struct MsgPort *)CreateMsgPort ()))
  134.         CloseStuff (10);
  135.     if (!(glob.Port = (struct MsgPort *)CreateMsgPort ()))
  136.         CloseStuff (10);
  137.     if (!(InputIO = (struct StdIOReq *)CreateExtIO (InputMP,sizeof (struct IOStdReq))))
  138.         CloseStuff (10);
  139.     if (Device = OpenDevice ("input.device",NULL,InputIO,NULL))
  140.         CloseStuff (10);
  141.     InputBase = (struct Library *)InputIO->io_Device;
  142.     glob.EveryKey = FALSE;
  143.     if (!(CxPort = (struct MsgPort *)CreateMsgPort ()))
  144.         CloseStuff (10);
  145.     NewBroker.nb_Port = CxPort;
  146.     if (!(Broker = (CxObj *)CxBroker (&NewBroker,NULL)))
  147.         CloseStuff (10);
  148.     ActivateCxObj (Broker,TRUE);
  149. }
  150.  
  151.  
  152. /*
  153.  * Add an input event to the input event chain
  154.  */
  155. void AddEvent (int class, int subclass, int code, int qual, int x, int y, APTR eventad)
  156. {
  157.     struct InputEvent ie;
  158.  
  159.     ie.ie_Code = code;
  160.     ie.ie_Qualifier = qual;
  161.     ie.ie_Class = class;
  162.     ie.ie_SubClass = subclass;
  163.     if (eventad) ie.ie_EventAddress = eventad;
  164.     else
  165.         {
  166.             ie.ie_X = x;
  167.             ie.ie_Y = y;
  168.         }
  169.     InputIO->io_Data = (APTR)&ie;
  170.     InputIO->io_Command = IND_WRITEEVENT;
  171.     InputIO->io_Length = sizeof (struct InputEvent);
  172.     DoIO (InputIO);
  173. }
  174.  
  175.  
  176.  
  177. /*
  178.  * This routine is only for the input handler. It is used to send a
  179.  * message to the main program
  180.  */
  181. void __regargs Send (struct GlobData *gd, struct InputEvent *ev)
  182. {
  183.     struct SpecMsg *Msg;
  184.  
  185.     if (Msg = (struct SpecMsg *)AllocMem (sizeof (struct SpecMsg),MEMF_PUBLIC))
  186.         {
  187.             Msg->msg.mn_ReplyPort = NULL;
  188.             Msg->msg.mn_Length = sizeof (struct SpecMsg);
  189.             Msg->Class = ev->ie_Class;
  190.             Msg->Code = ev->ie_Code;
  191.             Msg->Qualifier = ev->ie_Qualifier;
  192.             PutMsg (gd->Port,(struct Message *)Msg);
  193.         }
  194. }
  195.  
  196.  
  197. /*
  198.  * The input handler
  199.  */
  200. void __asm HandlerCode (register __a0 struct InputEvent *Ev,
  201.                                                 register __a1 struct GlobData *gd)
  202. {
  203.     struct InputEvent *ev;
  204.  
  205.     if (!gd->Enable) return;
  206.     for (ev = Ev; ev; ev = ev->ie_NextEvent)
  207.         if (ev->ie_Class == IECLASS_RAWMOUSE)
  208.             {
  209.                 gd->IsAlt = 0;
  210.                 if (ev->ie_Qualifier == 0x1234) continue;
  211.                 else if (ev->ie_Code == IECODE_RBUTTON+0x80)
  212.                     {
  213.                         /* Right mouse button */
  214.                         Send (gd,ev);
  215.                         ev->ie_Class = IECLASS_NULL;
  216.                     }
  217.             }
  218.         else if (ev->ie_Class == IECLASS_RAWKEY)
  219.             if (gd->EveryKey)
  220.                 {
  221.                     /* Menu mode */
  222.                     Send (gd,ev);
  223.                     ev->ie_Class = IECLASS_NULL;
  224.                 }
  225.             else
  226.                 {
  227.                     if (!(ev->ie_Qualifier & gd->qual))
  228.                         if (ev->ie_Code == gd->peek)        /* Left-alt */
  229.                             {
  230.                                 /* Left-alt is pressed */
  231.                                 gd->IsAlt = 1;
  232.                             }
  233.                         else if (ev->ie_Code == gd->peek+0x80)
  234.                             {
  235.                                 /* Left-alt is released */
  236.                                 if (!gd->IsAlt) continue;
  237.                                 gd->IsAlt = 0;
  238.                                 Send (gd,ev);
  239.                             }
  240.                         else gd->IsAlt = 0;
  241.                     else gd->IsAlt = 0;
  242.                 }
  243. }
  244.  
  245.  
  246. /*
  247.  * Handle some special commodity messages
  248.  */
  249. UWORD TraiterCx (void)
  250. {
  251.     CxMsg *CxMsg;
  252.     UWORD Quit = FALSE;
  253.     ULONG msgid,msgtype;
  254.  
  255.     while (CxMsg = (LONG *)GetMsg (CxPort))
  256.         {
  257.             msgid = CxMsgID (CxMsg);
  258.             msgtype = CxMsgType (CxMsg);
  259.             ReplyMsg ((struct Message *)CxMsg);
  260.  
  261.             if (msgtype == CXM_COMMAND)
  262.                 switch (msgid)
  263.                     {
  264.                         case CXCMD_DISABLE:
  265.                             glob.Enable = FALSE;
  266.                             ActivateCxObj (Broker, FALSE);
  267.                             break;
  268.                         case CXCMD_ENABLE:
  269.                             glob.Enable = TRUE;
  270.                             ActivateCxObj (Broker, TRUE);
  271.                             break;
  272.                         case CXCMD_KILL:
  273.                             Quit = TRUE;
  274.                             break;
  275.                     }
  276.         }
  277.     return (Quit);
  278. }
  279.  
  280.  
  281. /* Data to remember the selected item */
  282. struct Menu *menu;
  283. struct MenuItem *menuit,*menusub;
  284. struct Screen *scr;
  285. struct Window *win;
  286.  
  287.  
  288. /*
  289.  * Move the mouse pointer to a fixed position
  290.  */
  291. void __regargs MovePointer (int x, int y)
  292. {
  293.     struct IEPointerPixel iepp;
  294.  
  295.     iepp.iepp_Screen = scr;
  296.     iepp.iepp_Position.X = x;
  297.     iepp.iepp_Position.Y = y;
  298.  
  299.     AddEvent (IECLASS_NEWPOINTERPOS,IESUBCLASS_PIXEL,0,0,0,0,(APTR)&iepp);
  300. }
  301.  
  302.  
  303. /*
  304.  * Move the mouse pointer to the position represented by the selected
  305.  * item
  306.  */
  307. void MoveMenu ()
  308. {
  309.     int x,y;
  310.  
  311.     x = menu->LeftEdge+3;
  312.     y = menu->TopEdge+3;
  313.  
  314.     if (menuit)
  315.         {
  316.             x += 7+menuit->LeftEdge;
  317.             y += menuit->TopEdge+scr->BarHeight;
  318.         }
  319.     if (menusub)
  320.         {
  321.             x += menusub->LeftEdge;
  322.             y += menusub->TopEdge;
  323.         }
  324.     MovePointer (x,y);
  325. }
  326.  
  327.  
  328. /*
  329.  * Search for the menu on a given position
  330.  */
  331. struct Menu * __regargs SearchMenu (int x, int y)
  332. {
  333.     struct Menu *m;
  334.  
  335.     m = win->MenuStrip;
  336.     while (m)
  337.         {
  338.             if (x >= m->LeftEdge && x <= (m->LeftEdge+m->Width) && y >= m->TopEdge
  339.                     && y <= (m->TopEdge+scr->BarHeight))
  340.                 return (m);
  341.             m = m->NextMenu;
  342.         }
  343.     return (NULL);
  344. }
  345.  
  346.  
  347. /*
  348.  * Search for the menuitem on a given position
  349.  */
  350. struct MenuItem * __regargs SearchItem (struct Menu **m)
  351. {
  352.     struct MenuItem *mi,*ms;
  353.  
  354.     *m = win->MenuStrip;
  355.     while (*m)
  356.         {
  357.             mi = (*m)->FirstItem;
  358.             while (mi)
  359.                 {
  360.                     if (mi->Flags & HIGHITEM)
  361.                         {
  362.                             ms = mi->SubItem;
  363.                             while (ms)
  364.                                 {
  365.                                     if (ms->Flags & HIGHITEM) return (NULL);
  366.                                     ms = ms->NextItem;
  367.                                 }
  368.                             return (mi);
  369.                         }
  370.                     mi = mi->NextItem;
  371.                 }
  372.             *m = (*m)->NextMenu;
  373.         }
  374.     *m = NULL;
  375.     return (NULL);
  376. }
  377.  
  378.  
  379. /*
  380.  * Move to the left
  381.  */
  382. void __regargs MoveLeft (int qual)
  383. {
  384.     struct Menu *m;
  385.  
  386.     if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  387.         {
  388.             menusub = menuit = NULL;
  389.             menu = win->MenuStrip;
  390.             return;
  391.         }
  392.  
  393.     if (menusub) menusub = NULL;
  394.     else
  395.         {
  396.             m = win->MenuStrip;
  397.             while (m)
  398.                 {
  399.                     if (m->NextMenu == menu || m->NextMenu == NULL)
  400.                         {
  401.                             menu = m;
  402.                             menuit = NULL;
  403.                             break;
  404.                         }
  405.                     m = m->NextMenu;
  406.                 }
  407.         }
  408. }
  409.  
  410.  
  411. /*
  412.  * Move to the right
  413.  */
  414. void __regargs MoveRight (int qual)
  415. {
  416.     if (qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT))
  417.         {
  418.             menusub = menuit = NULL;
  419.             while (menu->NextMenu) menu = menu->NextMenu;
  420.             return;
  421.         }
  422.  
  423.     if ((!menusub) && menuit && menuit->SubItem)
  424.         menusub = menuit->SubItem;
  425.     else
  426.         {
  427.             if (menu->NextMenu)
  428.                 menu = menu->NextMenu;
  429.             else menu = win->MenuStrip;
  430.  
  431.             menuit = NULL;
  432.             menusub = NULL;
  433.         }
  434. }
  435.  
  436.  
  437. /*
  438.  * Move down
  439.  */
  440. void __regargs MoveDown (int qual)
  441. {
  442.     int shift;
  443.  
  444.     shift = qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT);
  445.  
  446.     if (menusub)
  447.         {
  448.             if (menusub->NextItem) menusub = menusub->NextItem;
  449.             if (shift)
  450.                 while (menusub->NextItem) menusub = menusub->NextItem;
  451.         }
  452.     else
  453.         {
  454.             if (menuit)
  455.                 {
  456.                     if (menuit->NextItem) menuit = menuit->NextItem;
  457.                     if (shift)
  458.                         while (menuit->NextItem) menuit = menuit->NextItem;
  459.                 }
  460.             else
  461.                 {
  462.                     menuit = menu->FirstItem;
  463.                     if (shift)
  464.                         while (menuit->NextItem) menuit = menuit->NextItem;
  465.                 }
  466.         }
  467. }
  468.  
  469.  
  470.  
  471. /*
  472.  * Move up
  473.  */
  474. void __regargs MoveUp (int qual)
  475. {
  476.     int shift;
  477.     struct MenuItem *mi;
  478.  
  479.     shift = qual & (IEQUALIFIER_LSHIFT|IEQUALIFIER_RSHIFT);
  480.  
  481.     if (menusub)
  482.         {
  483.             if (shift) menusub = menuit->SubItem;
  484.             else
  485.                 {
  486.                     mi = menuit->SubItem;
  487.                     while (mi)
  488.                         {
  489.                             if (mi->NextItem == menusub)
  490.                                 {
  491.                                     menusub = mi;
  492.                                     break;
  493.                                 }
  494.                             mi = mi->NextItem;
  495.                         }
  496.                 }
  497.         }
  498.     else
  499.         {
  500.             if (menuit)
  501.                 {
  502.                     if (shift) menuit = menu->FirstItem;
  503.                     else
  504.                         {
  505.                             mi = menu->FirstItem;
  506.                             while (mi)
  507.                                 {
  508.                                     if (mi->NextItem == menuit)
  509.                                         {
  510.                                             menuit = mi;
  511.                                             break;
  512.                                         }
  513.                                     mi = mi->NextItem;
  514.                                 }
  515.                             if (!mi) menuit = NULL;
  516.                         }
  517.                 }
  518.         }
  519. }
  520.  
  521.  
  522. /*
  523.  * Search the next char and move to that item
  524.  */
  525. void __regargs MoveChar (int code, int qual)
  526. {
  527.     struct MenuItem *mi;
  528.     struct Menu *m;
  529.     struct IntuiText *it;
  530.     char buf[3];
  531.     int rc;
  532.     struct InputEvent ie;
  533.  
  534.     ie.ie_Class = IECLASS_RAWKEY;
  535.     ie.ie_SubClass = 0;
  536.     ie.ie_X = 0;
  537.     ie.ie_Y = 0;
  538.  
  539.     ie.ie_Code = code;
  540.     ie.ie_Qualifier = qual;
  541.     rc = MapRawKey (&ie,buf,1,NULL);
  542.     if (!rc) return;
  543.     buf[0] = tolower(buf[0]);
  544.  
  545.     if (menusub)
  546.         {
  547.             mi = menusub;
  548.             do
  549.                 {
  550.                     if (mi->Flags & ITEMTEXT)
  551.                         {
  552.                             it = (struct IntuiText *)(mi->ItemFill);
  553.                             if (it && tolower(it->IText[0]) == buf[0])
  554.                                 {
  555.                                     menusub = mi;
  556.                                     break;
  557.                                 }
  558.                         }
  559.  
  560.                     mi = mi->NextItem;
  561.                     if (!mi) mi = menuit->SubItem;
  562.                 }
  563.             while (mi != menusub);
  564.         }
  565.     else
  566.         {
  567.             if (menuit)
  568.                 {
  569.                     mi = menuit;
  570.                     do
  571.                         {
  572.                             if (mi->Flags & ITEMTEXT)
  573.                                 {
  574.                                     it = (struct IntuiText *)(mi->ItemFill);
  575.                                     if (it && tolower(it->IText[0]) == buf[0])
  576.                                         {
  577.                                             menuit = mi;
  578.                                             if (menuit->SubItem)
  579.                                                 {
  580.                                                     MoveMenu ();
  581.                                                     MoveRight (0);
  582.                                                 }
  583.                                             break;
  584.                                         }
  585.                                 }
  586.  
  587.                             mi = mi->NextItem;
  588.                             if (!mi) mi = menu->FirstItem;
  589.                         }
  590.                     while (mi != menuit);
  591.                 }
  592.             else
  593.                 {
  594.                     m = menu;
  595.                     do
  596.                         {
  597.                             if (m->MenuName && tolower(m->MenuName[0]) == buf[0])
  598.                                 {
  599.                                     menu = m;
  600.                                     MoveMenu ();
  601.                                     MoveDown (0);
  602.                                     break;
  603.                                 }
  604.  
  605.                             m = m->NextMenu;
  606.                             if (!m) m = win->MenuStrip;
  607.                         }
  608.                     while (m != menu);
  609.                 }
  610.         }
  611. }
  612.  
  613.  
  614.  
  615. /*
  616.  * Main program
  617.  */
  618. void argmain (void)
  619. {
  620.     long sig,sigport,sigcx;
  621.     struct SpecMsg *msg;
  622.     struct Task *Task;
  623.     struct DiskObject *diskobj;
  624.     int MouseX = 0,MouseY = 0;
  625.     int end;
  626.  
  627.     OpenStuff ();
  628.  
  629.     glob.peek = 0x64;
  630.     if (Cli ())
  631.         {
  632.             PutStr ("\33[33mAltMenu 1.0 by Jorrit Tyberghein\33[31m\n© Copyright 1992\33[31m\n");
  633.             if (RDArgs = (struct RDArgs *)ReadArgs ("LALT/s,RALT/s,CTRL/s,LCMD/s,RCMD/s",ArgsArray,NULL))
  634.                 {
  635.                     if (ArgsArray[0]) glob.peek = 0x64;
  636.                     if (ArgsArray[1]) glob.peek = 0x65;
  637.                     if (ArgsArray[2]) glob.peek = 0x63;
  638.                     if (ArgsArray[3]) glob.peek = 0x66;
  639.                     if (ArgsArray[4]) glob.peek = 0x67;
  640.                 }
  641.             else
  642.                 {
  643.                     PutStr ("Invalid parameters!\n");
  644.                     CloseStuff (10);
  645.                 }
  646.         }
  647.     else
  648.         {
  649.             Task = (struct Task *)FindTask (NULL);
  650.             if (diskobj = (struct DiskObject *)GetDiskObjectNew (Task->tc_Node.ln_Name))
  651.                 {
  652.                     if (FindToolType (diskobj->do_ToolTypes,"LALT")) glob.peek = 0x64;
  653.                     if (FindToolType (diskobj->do_ToolTypes,"RALT")) glob.peek = 0x65;
  654.                     if (FindToolType (diskobj->do_ToolTypes,"CTRL")) glob.peek = 0x63;
  655.                     if (FindToolType (diskobj->do_ToolTypes,"LCMD")) glob.peek = 0x66;
  656.                     if (FindToolType (diskobj->do_ToolTypes,"RCMD")) glob.peek = 0x67;
  657.                     FreeDiskObject (diskobj);
  658.                 }
  659.         }
  660.     switch (glob.peek)
  661.         {
  662.             case 0x64 : glob.qual = 0xfb & ~IEQUALIFIER_LALT; break;
  663.             case 0x65 : glob.qual = 0xfb & ~IEQUALIFIER_RALT; break;
  664.             case 0x63 : glob.qual = 0xfb & ~IEQUALIFIER_CONTROL; break;
  665.             case 0x66 : glob.qual = 0xfb & ~IEQUALIFIER_LCOMMAND; break;
  666.             case 0x67 : glob.qual = 0xfb & ~IEQUALIFIER_RCOMMAND; break;
  667.         }
  668.  
  669.     Handler.is_Code = (APTR)handler;
  670.     Handler.is_Data = (APTR)&glob;
  671.     Handler.is_Node.ln_Pri = 100;
  672.     Handler.is_Node.ln_Name = "AltMenu";
  673.     InputIO->io_Data = &Handler;
  674.     InputIO->io_Command = IND_ADDHANDLER;
  675.     DoIO (InputIO);
  676.  
  677.     sigport = 1<<glob.Port->mp_SigBit;
  678.     sigcx = 1<<CxPort->mp_SigBit;
  679.     while (TRUE)
  680.         {
  681.             sig = Wait (sigcx|sigport|SIGBREAKF_CTRL_C);
  682.             if (sig & sigport)
  683.                 while (msg = (struct SpecMsg *)GetMsg (glob.Port))
  684.                     {
  685.                         if (glob.EveryKey && (msg->Class != IECLASS_RAWMOUSE || msg->Code != IECODE_RBUTTON+0x80))
  686.                             {
  687.                                 end = FALSE;
  688.                                 if (msg->Code == glob.peek) msg->Code = -1;
  689.                                 switch (msg->Code)
  690.                                     {
  691.                                         case CODE_SPACE :
  692.                                             AddEvent (IECLASS_RAWMOUSE,0,IECODE_LBUTTON,0x1234,0,0,NULL);
  693.                                             AddEvent (IECLASS_RAWMOUSE,0,IECODE_LBUTTON+0x80,0x1234,0,0,NULL);
  694.                                             break;
  695.                                         case -1 :
  696.                                             AddEvent (IECLASS_POINTERPOS,0,0,0,0,0,NULL);
  697.                                         case CODE_ENTER :
  698.                                         case CODE_RETURN :
  699.                                             end = TRUE;
  700.                                             glob.EveryKey = FALSE;
  701.                                             AddEvent (IECLASS_RAWMOUSE,0,IECODE_RBUTTON+0x80,0x1234,0,0,NULL);
  702.                                             MovePointer (MouseX,MouseY);
  703.                                             break;
  704.                                         case CODE_LEFT :
  705.                                             MoveLeft (msg->Qualifier);
  706.                                             break;
  707.                                         case CODE_RIGHT :
  708.                                             MoveRight (msg->Qualifier);
  709.                                             break;
  710.                                         case CODE_DOWN :
  711.                                             MoveDown (msg->Qualifier);
  712.                                             break;
  713.                                         case CODE_UP :
  714.                                             MoveUp (msg->Qualifier);
  715.                                             break;
  716.                                         default :
  717.                                             MoveChar (msg->Code,msg->Qualifier);
  718.                                     }
  719.                                 if (!end) MoveMenu ();
  720.                             }
  721.                         else
  722.                             {
  723.                                 glob.EveryKey = FALSE;
  724.                                 win = IntuitionBase->ActiveWindow;
  725.                                 scr = win->WScreen;
  726.                                 MouseX = scr->MouseX;
  727.                                 MouseY = scr->MouseY;
  728.                                 menuit = menusub = NULL;
  729.                                 if (msg->Class == IECLASS_RAWMOUSE && msg->Code == IECODE_RBUTTON+0x80)
  730.                                     {
  731.                                         if (menu = SearchMenu (MouseX,MouseY))
  732.                                             {
  733.                                                 MoveMenu ();
  734.                                                 glob.EveryKey = TRUE;
  735.                                             }
  736.                                         else if ((menuit = SearchItem (&menu)) && menuit->SubItem)
  737.                                             {
  738.                                                 MoveMenu ();
  739.                                                 glob.EveryKey = TRUE;
  740.                                             }
  741.                                         else AddEvent (IECLASS_RAWMOUSE,0,IECODE_RBUTTON+0x80,0x1234,0,0,NULL);
  742.                                     }
  743.                                 else if (menu = win->MenuStrip)
  744.                                     {
  745.                                         MovePointer (0,0);
  746.                                         AddEvent (IECLASS_RAWMOUSE,0,IECODE_RBUTTON,0x1234,0,0,NULL);
  747.                                         MoveMenu ();
  748.                                         glob.EveryKey = TRUE;
  749.                                     }
  750.                             }
  751.                         FreeMem (msg,msg->msg.mn_Length);
  752.                     }
  753.             if (sig & sigcx)
  754.                 if (TraiterCx ()) break;
  755.             if (sig & SIGBREAKF_CTRL_C) break;
  756.         }
  757.  
  758.     InputIO->io_Data = &Handler;
  759.     InputIO->io_Command = IND_REMHANDLER;
  760.     DoIO (InputIO);
  761.  
  762.     CloseStuff (0);
  763. }
  764.