4 * Handling and dispatching events
6 * © 1994-1998 Straylight
9 /*----- Licensing note ----------------------------------------------------*
11 * This file is part of Straylight's Steel library.
13 * Steel is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2, or (at your option)
18 * Steel is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with Steel. If not, write to the Free Software Foundation,
25 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
28 /*----- Header files ------------------------------------------------------*/
43 #define dbox__INTERNALS
46 /*----- Global variables --------------------------------------------------*/
48 static wimp_emask event__mask=wimp_EMNULL;
50 static menu event__currentMenu;
51 static event_menu_maker event__currentMaker;
52 static event_menu_proc event__menuProc;
53 static void *event__menuHandle;
55 /* --- For bodging menus which move around in memory --- */
57 static int event__menuX;
58 static int event__menuY;
60 static BOOL event__recreating;
61 static event_menuPurpose event__purpose;
62 static BOOL event__returnMenuHelp;
64 /*----- Event masks -------------------------------------------------------*/
66 void event_setmask (wimp_emask mask)
71 wimp_emask event_getmask (void)
74 return (event__mask&~wimp_EMNULL);
79 /*----- Menu button handling ----------------------------------------------*/
81 typedef struct event__midbstr
83 event_midbhandler proc;
92 * BOOL event_attachMidbHandler(wimp_w w,
93 * event_midbhandler proc,
100 * Registers a function to be called by event when a menu button event is
101 * received by a particular window. Typically, this handler will display a
102 * menu at the mouse coordinates, although you can do anything you want.
104 * You shouldn't need to call this function very much. It's really for
105 * allowing other systems to supply menu attachment functions like event_-
109 * wimp_w == the window to which to attach the function
110 * event_midbhandler proc == the function to call when a menu button event
111 * is received for the window
112 * others == arguments to be passed (unprocessed) to proc when it's called.
115 * TRUE if the attachment succeeded.
118 BOOL event_attachMidbHandler(wimp_w w,
119 event_midbhandler proc,
125 event__midbstr *e=win_getmenuh(w);
128 if (e=mem_alloc(sizeof(event__midbstr)),!e)
130 werr(FALSE,msgs_lookup("eventNMAM:Not enough memory to attach menu"));
151 void event_attachedMenu(wimp_w w,
153 event_menu_maker *mk,
154 event_menu_proc *proc,
157 event__midbstr *e=win_getmenuh(w);
160 *m=(e->gadget ? 0 : e->handlea);
161 *mk=(e->gadget ? (event_menu_maker)e->handlea : 0);
162 *proc=(event_menu_proc)e->handleb;
174 /*----- Menu displaying ---------------------------------------------------*/
177 * void event__displayMenu(void)
180 * Displays (or redisplays) the current menu. It is assumed that the menu
181 * maker has been called to set up the current menu pointer.
184 static void event__displayMenu(void)
187 m=menu_syshandle(event__currentMenu);
188 if (win_anyWindows()==FALSE)
191 msgs_lookup("eventTMWM:Too many windows - "
192 "%s could not create menu."),
193 wimpt_programname());
196 wimpt_noerr(wimp_create_menu(m,event__menuX,event__menuY));
200 * void event__findMenu(BOOL iconbar)
203 * Sets up the global event__menuX and event__menuY for the current menu
204 * for a subsequent call of event__displayMenu. Also (as a side-effect)
205 * calls the menu maker.
208 * BOOL iconbar == whether the menu has been opened from the iconbar
211 static void event__findMenu(BOOL iconbar)
217 if (event__currentMaker)
219 event__recreating=FALSE;
220 event__currentMenu=event__currentMaker(event__menuHandle);
222 wimpt_noerr(wimp_get_point_info(&m));
226 mn=menu_syshandle(event__currentMenu);
228 it=(wimp_menuitem *)(mn+1);
231 height+=44; /* I know it may not be, but it should. */
232 if (it->flags & wimp_MSEPARATE)
234 if (it->flags & wimp_MLAST)
238 event__menuY=96+height;
245 * void event_openMenu(menu it,event_menu_proc proc,void *handle)
246 * void event_makeMenu(event_menu_maker it,event_menu_proc proc,void *handle)
247 * void event_openIconbarMenu(...)
248 * void event_makeIconbarMenu(...)
251 * Opens a menu onto the screen and tells your routine when it's finished.
254 * menu it == the menu or menu maker procedure
255 * event_menu_proc proc == the menu handler function
256 * void *handle == it's jolly old handle
259 void event_openMenu(menu it,event_menu_proc proc,void *handle)
261 event__currentMenu=it;
262 event__currentMaker=0;
263 event__menuProc=proc;
264 event__menuHandle=handle;
265 event__findMenu(FALSE);
266 event__displayMenu();
269 void event_makeMenu(event_menu_maker maker,event_menu_proc proc,void *handle)
271 event__currentMaker=maker;
272 event__menuProc=proc;
273 event__menuHandle=handle;
274 event__findMenu(FALSE);
275 event__displayMenu();
278 void event_openIconbarMenu(menu it,event_menu_proc proc,void *handle)
280 event__currentMenu=it;
281 event__currentMaker=0;
282 event__menuProc=proc;
283 event__menuHandle=handle;
284 event__findMenu(TRUE);
285 event__displayMenu();
288 void event_makeIconbarMenu(event_menu_maker maker,
289 event_menu_proc proc,
292 event__currentMaker=maker;
293 event__menuProc=proc;
294 event__menuHandle=handle;
295 event__findMenu(TRUE);
296 event__displayMenu();
299 /*----- Menu attachment ---------------------------------------------------*/
302 * event__defaultmidb(wimp_w w,
309 * Default menu button handler for windows (to support event_attachmenu
313 * As for an event_midbhandler.
316 static void event__defaultmidb(wimp_w w,
326 event_openIconbarMenu((menu)handlea,
327 (event_menu_proc)handleb,
332 event_makeIconbarMenu((event_menu_maker)handlea,
333 (event_menu_proc)handleb,
341 event_openMenu((menu)handlea,
342 (event_menu_proc)handleb,
347 event_makeMenu((event_menu_maker)handlea,
348 (event_menu_proc)handleb,
354 /*----- Default menu attachment -------------------------------------------*/
357 * void event_attachmenu(wimp_w w,menu m,event_menu_proc p,void *handle)
360 * Attaches a menu to a window so that it opens when you click menu on it.
363 * wimp_w w == the window to attach to
364 * menu m == the menu to attach to it
365 * event_menu_proc p == what to do when a menu item is chosen
366 * void *handle == something else to send to p
369 BOOL event_attachmenu(wimp_w w,menu m,event_menu_proc p,void *handle)
371 return (event_attachMidbHandler(w,
380 * void event_attachmenumaker(wimp_w w,
381 * event_menu_maker m,
386 * Attaches a menu to a window so that it opens when you click menu on it.
389 * wimp_w w == the window to attach to
390 * event_menu_maker m == how to create the menu
391 * event_menu_proc p == what to do when a menu item is chosen
392 * void *handle == something else to send to p
395 BOOL event_attachmenumaker(wimp_w w,
400 return (event_attachMidbHandler(w,
408 /*----- Pointless window counting -----------------------------------------*/
410 BOOL event_anywindows(void)
412 return(win_activeno() != 0);
415 /*----- Event processing -- the interesting bit ---------------------------*/
417 void event_returnMenuHelp(BOOL doit)
419 event__returnMenuHelp=doit;
422 event_menuPurpose event_whyMenuEvent(void)
424 return (event__purpose);
427 BOOL event_is_menu_being_recreated(void)
429 return event__recreating;
432 void (event_process)(void)
437 * void event__menuHit(int *hits)
440 * Sends a menu hit array to the current menu handling procedure
443 * int *hits == an array of menu hits (WIMP-style) to convert to obscure
444 * RISC_OSLib format (1-indexed :-( ) and bundled to an event handler.
447 static void event__menuHit(int *hits)
450 char buff[9]; /* Silly event -- using chars! */
451 if (event__currentMenu)
453 for (i=0;hits[i]!=-1;i++)
456 event__menuProc(event__menuHandle,buff);
461 * void event__process(void)
464 * Processes events :-)
467 void event__process(void)
471 static BOOL lastWasMenu;
474 /* --- Terminate the app if it has no windows --- */
476 if (!event_anywindows())
479 /* --- If we just clicked on a menu, we may need to reopen it --- */
482 event__currentMenu &&
483 wimpt_last_event()->e==wimp_EMENU)
486 wimpt_noerr(wimp_get_point_info(&m));
487 if (m.bbits & wimp_BRIGHT)
489 if (event__currentMaker)
491 event__recreating=TRUE;
492 event__currentMenu=event__currentMaker(event__menuHandle);
494 event__displayMenu();
499 event__purpose=event_MENUDELETE;
504 /* --- Get an event from wimpt and process it --- */
506 wimpt_noerr(wimpt_poll(event_getmask(),&e));
512 while (alarm_next(&nextAlarm) && alarm_timenow()-nextAlarm>=0)
516 if (e.data.but.m.bbits & wimp_BMID)
518 wimp_w w=(e.data.but.m.w<=-1) ? win_ICONBAR : e.data.but.m.w;
519 event__midbstr *m=win_getmenuh(w);
522 (m->proc)(w,m->gadget,m->handlea,m->handleb,m->handlec);
528 event__purpose=event_MENUSELECT;
529 event__menuHit(e.data.menu);
533 case wimp_ESENDWANTACK:
534 switch (e.data.msg.hdr.action)
538 if (e.data.msg.data.words[0]>0x8000)
540 if (win_anyWindows()==FALSE)
543 msgs_lookup("eventTMWS:Too many windows - "
544 "%s could not create submenu."),
545 wimpt_programname());
549 wimpt_noerr(wimp_create_submenu(
550 (wimp_menustr *)e.data.msg.data.words[0],
551 e.data.msg.data.words[1],
552 e.data.msg.data.words[2]));
557 for (i=3;e.data.msg.data.words[i] != -1;i++)
559 e.data.msg.data.words[i++] = -1;
560 event__purpose=event_MENUSUBMENU;
561 event__menuHit(e.data.msg.data.words+3);
564 case wimp_MHELPREQUEST:
565 if (event__returnMenuHelp &&
566 e.data.msg.data.helprequest.m.w!=dbox__menuDboxWindow())
570 wimpt_noerr(wimp_getmenustate(1,
572 e.data.msg.data.helprequest.m.w,
573 e.data.msg.data.helprequest.m.i));
576 event__purpose=event_MENUHELP;
577 event__menuHit(buff);
581 case 0x400C9: /* Message_MenusDeleted */
584 event__purpose=event_MENUDELETE;
585 event__menuHit(e.data.menu);
591 if (!win_processevent(&e))
594 /* --- Default event handling --- */
599 werr(TRUE,msgs_lookup("Internal error: unserviced redraw event"));
602 wimpt_noerr(wimp_open_wind(&e.data.o));
605 wimp_processkey(e.data.key.chcode);
611 void event_clear_current_menu(void)
613 wimpt_noerr(wimp_create_menu((wimp_menustr*)-1,0,0));
614 if (event__currentMenu)
617 event__purpose=event_MENUDELETE;
619 event__currentMenu=0;