home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 372.lha / PopUpMenu_3.2 / Source / PopUpMenu.c < prev    next >
C/C++ Source or Header  |  1990-05-06  |  7KB  |  249 lines

  1. #include "PopUpMenu.h"
  2.  
  3. /****************************************
  4.  * PopUpMenu(InputSignals)              *
  5.  *                    *
  6.  * Input:                *
  7.  *   InputSignals  - Allocated signals. *
  8.  * Output:                *
  9.  *   none                *
  10.  ****************************************/
  11. VOID PopUpMenu(InputSignals)
  12.   struct SignalData *const InputSignals;
  13. {
  14.   IMPORT struct WindowData MenuWindow, ItemWindow, SubWindow;
  15.   IMPORT struct RastPort Rp;
  16.   IMPORT struct Window *ActiveWindow;
  17.   IMPORT struct Screen *Screen;
  18.   IMPORT struct Menu *Menues;
  19.   IMPORT UWORD    CurrentMenuNr;
  20.   IMPORT UWORD    MenuFontSize;
  21.   IMPORT WORD    MouseX,MouseY;
  22.   IMPORT struct SignalSemaphore PopUpSemaphore;
  23.   IMPORT struct timerequest  *TimerReqBlock;
  24.   IMPORT struct Window *LastWindow;
  25.   IMPORT WORDBITS LastSelected;
  26.   IMPORT struct IntuitionBase *IntuitionBase;
  27.  
  28.   WORDBITS MenuNumber;
  29.  
  30.   ObtainSemaphore(&PopUpSemaphore);
  31.  
  32.   /* be sure that the window to use is still active */
  33.   if (IntuitionBase->ActiveWindow != ActiveWindow)
  34.     goto Abort;
  35.  
  36. #ifndef NOLOCKING
  37.   LockLayers(&Screen->LayerInfo); /* puh! now we are safe (I hope) */
  38. #endif
  39.   InitGlobals();
  40.  
  41.   /* try to open menues */
  42.   if ((Menues) AND
  43.       (OpenMenuWindow((ActiveWindow == LastWindow)?
  44.                (UWORD)(MENUNUM(LastSelected)) * MenuFontSize: 0))) {
  45.  
  46.     const LONGBITS MenuButtonSignals = InputSignals->MenuUpSig |
  47.                        InputSignals->MenuDownSig;
  48.     const LONGBITS MouseMovedSignal  = InputSignals->MouseMovedSig;
  49.     const LONGBITS ButtonSignals     = MenuButtonSignals |
  50.                        InputSignals->SelectDownSig;
  51.  
  52.     BOOL Waiting = FALSE;
  53.     struct MsgPort *const TimerPort =
  54.               TimerReqBlock->tr_node.io_Message.mn_ReplyPort;
  55.     const LONGBITS TimerSignal         = 1L << TimerPort->mp_SigBit;
  56.  
  57.     /* menuwindow opened ok */
  58.     MenuNumber = LastSelected = MENUNULL;
  59.  
  60.     /* start timer */
  61.  
  62.     SetSignal(0,TimerSignal); /* clear old timermessages */
  63.     if (CheckIO((struct IORequest *)TimerReqBlock) == NULL) {
  64.       WaitIO((struct IORequest *)TimerReqBlock);
  65.       GetMsg(TimerPort); /* get rid of the message */
  66.     }
  67.     QueueTimer();
  68.  
  69.     FOREVER {
  70.       const LONGBITS SignalBits = Wait(MouseMovedSignal |
  71.                        ButtonSignals |
  72.                        TimerSignal);
  73.  
  74.       if (SignalBits & MouseMovedSignal) {
  75.     Waiting = FALSE;
  76.     if ((MouseX != Screen->MouseX) OR (MouseY != Screen->MouseY)) {
  77.       MouseX = Screen->MouseX;
  78.       MouseY = Screen->MouseY;
  79.       SelectItem();
  80.     }
  81.       }
  82.       if (SignalBits & ButtonSignals) {
  83.     const WORDBITS Selected = FinalSelect();
  84.  
  85.     Waiting = FALSE;
  86.     /* do multiple select */
  87.     if (Selected != LastSelected) { /* same => do nothing */
  88.       if (MenuNumber == MENUNULL)
  89.         MenuNumber = Selected;   /* first selectiom */
  90.       else
  91.         (ItemAddress(Menues,(LONG)LastSelected))->NextSelect = Selected;
  92.       LastSelected = Selected;
  93.     }
  94.  
  95.     if (SignalBits & MenuButtonSignals) /* Menubutton -> final selection */
  96.       break;
  97.       }
  98.  
  99.       if (SignalBits & TimerSignal) {
  100.     GetMsg(TimerPort); /* get rid of the message */
  101.  
  102.     if (Waiting) {
  103.  
  104.       /* the input.device has stopped, unlock the screen and wait */
  105.  
  106.       SwapBits(&SubWindow);
  107.       SwapBits(&ItemWindow);
  108.       SwapBits(&MenuWindow);
  109.  
  110. #ifndef NOLOCKING
  111.       UnlockLayers(&Screen->LayerInfo);
  112. #endif
  113.       Wait(MouseMovedSignal);
  114. #ifndef NOLOCKING
  115.       LockLayers(&Screen->LayerInfo); /* let's hope the screen is still here */
  116. #endif
  117.       SwapBits(&MenuWindow);
  118.       SwapBits(&ItemWindow);
  119.       SwapBits(&SubWindow);
  120.     }
  121.  
  122.     /* start timer again */
  123.     QueueTimer();
  124.     Waiting = !Waiting;
  125.       }
  126.     } /* FOREVER */
  127.  
  128.     /* close all windows */
  129.     CloseItemWindow(&SubWindow);
  130.     CloseItemWindow(&ItemWindow);
  131.     CloseItemWindow(&MenuWindow);
  132.   }
  133.  
  134.   /* remember last menu selected */
  135.   LastWindow = ActiveWindow;
  136.  
  137. #ifndef NOLOCKING
  138.   UnlockLayers(&Screen->LayerInfo);
  139. #endif
  140.   /* tell the window the good news (MENUPICK) */
  141.   TellWindow(MenuNumber);
  142. Abort:
  143.   ReleaseSemaphore(&PopUpSemaphore);
  144. }
  145.  
  146. /*****************************************
  147.  *  TellWindow() - Send Fake Menu Event. *
  148.  *                     *
  149.  * Input:                 *
  150.  *   none                 *
  151.  * Output:                 *
  152.  *   none                 *
  153.  *****************************************/
  154. VOID TellWindow(MenuNumber)
  155.   WORDBITS MenuNumber;
  156. {
  157.   IMPORT struct Window          *const ActiveWindow;
  158.   IMPORT struct IOStdReq      *const InputReqBlock;
  159.   IMPORT struct IntuitionBase *const IntuitionBase;
  160.  
  161.   STATIC struct InputEvent MyFakeEvent;
  162.  
  163.   /* get the current time */
  164.   CurrentTime(&MyFakeEvent.ie_TimeStamp.tv_secs,
  165.           &MyFakeEvent.ie_TimeStamp.tv_micro);
  166.  
  167.   MyFakeEvent.ie_Class       = IECLASS_MENULIST;
  168.   MyFakeEvent.ie_Code       = MenuNumber;
  169.   MyFakeEvent.ie_Qualifier = 0;
  170.   MyFakeEvent.ie_NextEvent = NULL;
  171.   MyFakeEvent.ie_EventAddress = NULL;
  172.  
  173.   InputReqBlock->io_Command = IND_WRITEEVENT;
  174.   InputReqBlock->io_Flags   = 0;
  175.   InputReqBlock->io_Length  = sizeof(struct InputEvent);
  176.   InputReqBlock->io_Data    = (APTR)&MyFakeEvent;
  177.  
  178.   /* be sure the right window will get the message. */
  179.   ActivateWindow(ActiveWindow);
  180.  
  181.   DoIO(InputReqBlock);
  182. }
  183. /****************************************************
  184.  * InitGlobals() - Init the needed global variables *
  185.  *                            *
  186.  * Input:                        *
  187.  *   none                        *
  188.  * Output:                        *
  189.  *   none                        *
  190.  ****************************************************/
  191. VOID InitGlobals()
  192. {
  193.   IMPORT struct WindowData MenuWindow, ItemWindow, SubWindow;
  194.   IMPORT UWORD    CurrentMenuNr;
  195.   IMPORT struct Menu     *CurrentMenuPtr;
  196.   IMPORT struct MenuItem *CurrentItem, *CurrentSubItem;
  197.  
  198.   IMPORT struct Screen     *Screen;
  199.   IMPORT struct Menu     *Menues;
  200.   IMPORT struct RastPort Rp;
  201.   IMPORT struct Window     *const ActiveWindow;
  202.   IMPORT UWORD    MenuFontSize;
  203.   IMPORT BOOL    ScreenType;
  204.  
  205.   /* no window is open */
  206.   ItemWindow.BitMapOk = FALSE;
  207.   SubWindow.BitMapOk = FALSE;
  208.   MenuWindow.BitMapOk = FALSE;
  209.  
  210.   /* no menu is selected */
  211.   CurrentMenuNr  = 0;
  212.   CurrentMenuPtr = NULL;
  213.   CurrentItem     = NULL;
  214.   CurrentSubItem = NULL;
  215.  
  216.   Menues = ActiveWindow->MenuStrip;
  217.  
  218.   /* set up a rastport for the screen */
  219.   InitRastPort(&Rp);
  220.  
  221.   SetFont(&Rp,Screen->RastPort.Font);
  222.   Rp.BitMap = &Screen->BitMap;
  223.  
  224.   /* default font height */
  225.   MenuFontSize = Rp.TxHeight + 2;
  226.  
  227.   /* Size of screen */
  228.   ScreenType = (Screen->ViewPort.Modes & HIRES) == 0;
  229. }
  230.  
  231. /******************************************************
  232.  * QueueTimer() - Queue the timer to go of after 0.2s *
  233.  *                              *
  234.  * Input:                          *
  235.  *   none                          *
  236.  * Output:                          *
  237.  *   none:                          *
  238.  ******************************************************/
  239. VOID QueueTimer()
  240. {
  241.   IMPORT struct timerequest  *TimerReqBlock;
  242.  
  243.   TimerReqBlock->tr_node.io_Command = TR_ADDREQUEST;
  244.   TimerReqBlock->tr_time.tv_secs    = 0;
  245.   TimerReqBlock->tr_time.tv_micro   = 200000L;
  246.   SendIO((struct IORequest *)TimerReqBlock);
  247. }
  248.  
  249.