1 /*
2  * file mi_tool.c - toolkit for xblast menus
3  *
4  * $Id: mi_tool.c,v 1.33 2006/02/10 13:22:12 fzago Exp $
5  *
6  * Program XBLAST
7  * (C) by Oliver Vogel (e-mail: m.vogel@ndh.net)
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published
11  * by the Free Software Foundation; either version 2; or (at your option)
12  * any later version
13  *
14  * This program is distributed in the hope that it will be entertaining,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILTY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17  * Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License along
20  * with this program; if not, write to the Free Software Foundation, Inc.
21  * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  */
23 
24 #include "xblast.h"
25 
26 /*
27  * local variables
28  */
29 static XBMenuItem *itemFirst = NULL;
30 static XBMenuItem *itemLast = NULL;
31 static XBMenuItem *itemFocus = NULL;
32 static XBBool execFlag = XBTrue;
33 static XBBool fadeFlag = XBFalse;
34 static XBMenuItem *defaultItem = NULL;
35 static XBMenuItem *abortItem = NULL;
36 static XBBool mapMode = 0;
37 static int setPressed = 0;
38 static XBComboEntryList yesNoTable[] = {
39 	{N_("no"), 0, NULL},
40 	{N_("yes"), 1, NULL},
41 	{NULL, 0, NULL},
42 };
43 
44 /*
45  * delete any menu item
46  */
47 static void
DeleteMenuItem(XBMenuItem * item)48 DeleteMenuItem (XBMenuItem * item)
49 {
50 	assert (item != NULL);
51 	switch (item->type) {
52 	case MIT_Button:
53 		MenuDeleteButton (item);
54 		break;
55 	case MIT_Color:
56 		MenuDeleteColor (item);
57 		break;
58 	case MIT_Combo:
59 		MenuDeleteCombo (item);
60 		break;
61 	case MIT_Cyclic:
62 		MenuDeleteCyclic (item);
63 		break;
64 	case MIT_Keysym:
65 		MenuDeleteKeysym (item);
66 		break;
67 	case MIT_Label:
68 		MenuDeleteLabel (item);
69 		break;
70 	case MIT_Player:
71 		MenuDeletePlayer (item);
72 		break;
73 	case MIT_String:
74 		MenuDeleteString (item);
75 		break;
76 	case MIT_Toggle:
77 		MenuDeleteToggle (item);
78 		break;
79 	case MIT_Integer:
80 		MenuDeleteInteger (item);
81 		break;
82 	case MIT_Tag:
83 		MenuDeleteTag (item);
84 		break;
85 	case MIT_Host:
86 		MenuDeleteHost (item);
87 		break;
88 	case MIT_Table:
89 		MenuDeleteTable (item);
90 		break;
91 	case MIT_Team:
92 		MenuDeleteTeam (item);
93 		break;
94 	default:
95 		break;
96 	}
97 	free (item);
98 }								/* DeleteMenuItem */
99 
100 /*****************
101  * mouse buttons *
102  *****************/
103 
104 /*
105  * store press status of mouse
106  */
107 void
SetPressed(XBBool mode)108 SetPressed (XBBool mode)
109 {
110 	setPressed = mode;
111 }								/* SetPressed */
112 
113 /*
114  * get press status of mouse
115  */
116 XBBool
GetPressed(void)117 GetPressed (void)
118 {
119 	return setPressed;
120 }								/* GetPressed */
121 
122 /***************
123  * editor mode *
124  ***************/
125 
126 /*
127  * set editor mode
128  */
129 void
SetXBEditMapMode(XBBool mode)130 SetXBEditMapMode (XBBool mode)
131 {
132 	mapMode = mode;
133 }								/* SetXBEditMapMode */
134 
135 /*
136  * get editor mode
137  */
138 XBBool
GetXBEditMapMode(void)139 GetXBEditMapMode (void)
140 {
141 	return mapMode;
142 }								/* GetXBEditMapMode */
143 
144 /***************
145  * local tools *
146  ***************/
147 
148 /*
149  * find item by id
150  */
151 static XBMenuItem *
FindItem(MENU_ID id)152 FindItem (MENU_ID id)
153 {
154 	XBMenuItem *item;
155 
156 	for (item = itemFirst; item != NULL; item = item->next) {
157 		if (item->id == id) {
158 			return item;
159 		}
160 	}
161 	return NULL;
162 }								/* FindItem */
163 
164 /**************
165  * menu tools *
166  **************/
167 
168 /*
169  * an menu item was selected (i.e Space was pressed)
170  */
171 static void
SelectItem(XBMenuItem * item)172 SelectItem (XBMenuItem * item)
173 {
174 	if (item != NULL && item->select != NULL) {
175 		(*item->select) (item);
176 	}
177 }								/* SelectItem */
178 
179 /*
180  * clear all menu items
181  */
182 void
MenuClear(void)183 MenuClear (void)
184 {
185 	XBMenuItem *item_next;
186 	while (itemFirst != NULL) {
187 		item_next = itemFirst->next;
188 		DeleteMenuItem (itemFirst);
189 		itemFirst = item_next;
190 	}
191 	itemLast = itemFocus = NULL;
192 	fadeFlag = XBTrue;
193 	defaultItem = NULL;
194 	abortItem = NULL;
195 	MenuResetBase ();
196 	MenuClearMap ();
197 }								/* MenuClear */
198 
199 /*
200  * set directional links between items for arrow keys
201  */
202 void
MenuSetLinks(void)203 MenuSetLinks (void)
204 {
205 	XBMenuItem *ptr;
206 
207 	for (ptr = itemFirst; ptr != NULL; ptr = ptr->next) {
208 		if (NULL != ptr->mouse) {
209 			ptr->left = MenuFindLeftItem (ptr);
210 			ptr->right = MenuFindRightItem (ptr);
211 			ptr->up = MenuFindUpperItem (ptr);
212 			ptr->down = MenuFindLowerItem (ptr);
213 		}
214 	}
215 }								/* MenuSetLinks */
216 
217 /*
218  * select item
219  */
220 void
MenuSelect(MENU_ID id)221 MenuSelect (MENU_ID id)
222 {
223 	SelectItem (FindItem (id));
224 }								/* MenuSelect */
225 
226 /*
227  * set default item
228  */
229 void
MenuSetDefault(MENU_ID id)230 MenuSetDefault (MENU_ID id)
231 {
232 	defaultItem = FindItem (id);
233 	if (NULL != defaultItem && MIT_Button == defaultItem->type) {
234 		MenuSetButtonIcon (defaultItem, ISA_Default);
235 	}
236 }								/* MenuSetDefault */
237 
238 /*
239  * set abort item
240  */
241 void
MenuSetAbort(MENU_ID id)242 MenuSetAbort (MENU_ID id)
243 {
244 	abortItem = FindItem (id);
245 	if (NULL != abortItem && MIT_Button == abortItem->type) {
246 		MenuSetButtonIcon (abortItem, ISA_Abort);
247 	}
248 }								/* MenuSetDefault */
249 
250 /*
251  * async execution of function
252  */
253 void
MenuExecFunc(MIC_button func,void * data)254 MenuExecFunc (MIC_button func, void *data)
255 {
256 	execFlag = XBTrue;
257 	MenuButtonSetNextExec (func, data);
258 }								/* MenuExecFunc */
259 
260 /*
261  * activate/deactivate item
262  */
263 void
MenuSetActive(MENU_ID id,XBBool active)264 MenuSetActive (MENU_ID id, XBBool active)
265 {
266 	XBMenuItem *item = FindItem (id);
267 	if (NULL != item) {
268 		/* set flags */
269 		if (active) {
270 			item->flags &= ~MIF_DEACTIVATED;
271 		}
272 		else {
273 			item->flags |= MIF_DEACTIVATED;
274 		}
275 		switch (item->type) {
276 		case MIT_Button:
277 			MenuActivateButton (item, active);
278 			break;
279 		case MIT_Table:
280 			MenuActivateTable (item, active);
281 			break;
282 		default:
283 			break;
284 		}
285 	}
286 }								/* MenuSetActive */
287 
288 /*
289  * get item id with focus
290  */
291 MENU_ID
MenuGetFocus(void)292 MenuGetFocus (void)
293 {
294 	return (NULL != itemFocus) ? itemFocus->id : 0;
295 }								/* MenuGetFocus */
296 
297 /*------------------------------------------------------------------------*
298  *
299  * add items to menu
300  *
301  *------------------------------------------------------------------------*/
302 
303 /*
304  * add a generic item to the menu
305  */
306 static MENU_ID
MenuAdd(XBMenuItem * item)307 MenuAdd (XBMenuItem * item)
308 {
309 	if (itemLast == NULL) {
310 		itemFirst = item;
311 	}
312 	if (itemLast != NULL) {
313 		itemLast->next = item;
314 		item->prev = itemLast;
315 	}
316 	itemLast = item;
317 	itemLast->next = NULL;
318 	if (itemFocus == NULL && item->focus != NULL) {
319 		item->flags |= MIF_FOCUS;
320 		itemFocus = item;
321 		(*item->focus) (item, XBTrue);
322 	}
323 	return item->id;
324 }								/* MenuAdd */
325 
326 /*
327  * add horizontal button to menu
328  */
329 MENU_ID
MenuAddHButton(int x,int y,int w,const char * text,MIC_button func,void * funcData)330 MenuAddHButton (int x, int y, int w, const char *text, MIC_button func, void *funcData)
331 {
332 	return MenuAdd (MenuCreateHButton (x, y, w, text, func, funcData));
333 }								/* MenuAddHButton */
334 
335 /*
336  * add vertical button to menu
337  */
338 MENU_ID
MenuAddVButton(int x,int y,int h,const char * text,MIC_button func,void * funcData)339 MenuAddVButton (int x, int y, int h, const char *text, MIC_button func, void *funcData)
340 {
341 	return MenuAdd (MenuCreateVButton (x, y, h, text, func, funcData));
342 }								/* MenuAddVButton */
343 
344 /*
345  * add a checkbox item to menu
346  */
347 MENU_ID
MenuAddToggle(int x,int y,int w,const char * text,XBBool * pState)348 MenuAddToggle (int x, int y, int w, const char *text, XBBool * pState)
349 {
350 	return MenuAdd (MenuCreateToggle (x, y, w, text, pState));
351 }								/* MenuAddToggle */
352 
353 /*
354  * add a label/title to menu
355  */
356 MENU_ID
MenuAddLabel(int x,int y,int w,const char * text)357 MenuAddLabel (int x, int y, int w, const char *text)
358 {
359 	return MenuAdd (MenuCreateLabel (x, y, w, text));
360 }								/* MenuAddLabel */
361 
362 /*
363  * add label variant 1 to menu
364  */
365 MENU_ID
MenuAddLabel1(int x,int y,int w,const char * text)366 MenuAddLabel1 (int x, int y, int w, const char *text)
367 {
368 	return MenuAdd (MenuCreateLabel1 (x, y, w, text));
369 }								/* MenuAddLabel1 */
370 
371 /*
372  * add label variant 2 to menu
373  */
374 MENU_ID
MenuAddLabel2(int x,int y,int w,const char * text)375 MenuAddLabel2 (int x, int y, int w, const char *text)
376 {
377 	return MenuAdd (MenuCreateLabel2 (x, y, w, text));
378 }								/* MenuAddLabel2 */
379 
380 /*
381  * add a combobox to menu, check only integer keys
382  */
383 MENU_ID
MenuAddComboInt(int x,int y,int w_text,const char * text,int w,int * value,XBComboEntryList * table)384 MenuAddComboInt (int x, int y, int w_text, const char *text, int w, int *value,
385 				 XBComboEntryList * table)
386 {
387 	return MenuAdd (MenuCreateCombo (x, y, w_text, text, w, value, NULL, NULL, table));
388 }								/* MenuAddComboInt */
389 
390 /*
391  * a simple yes/no combobox to menu
392  */
393 MENU_ID
MenuAddComboBool(int x,int y,int w_text,const char * text,int w,XBBool * value)394 MenuAddComboBool (int x, int y, int w_text, const char *text, int w, XBBool * value)
395 {
396 	return MenuAdd (MenuCreateCombo (x, y, w_text, text, w, (int *)value, NULL, NULL, yesNoTable));
397 }								/* MenuAddComboInt */
398 
399 /*
400  * add a combobox to menu, check only data entry
401  */
402 MENU_ID
MenuAddComboData(int x,int y,int w_text,const char * text,int w,void ** data,XBComboEntryList * table)403 MenuAddComboData (int x, int y, int w_text, const char *text, int w, void **data,
404 				  XBComboEntryList * table)
405 {
406 	return MenuAdd (MenuCreateCombo (x, y, w_text, text, w, NULL, data, NULL, table));
407 }								/* MenuAddComboData */
408 
409 /*
410  * add a combobox to menu, check only atom entry
411  */
412 MENU_ID
MenuAddComboAtom(int x,int y,int w_text,const char * text,int w,XBAtom * atom,XBComboEntryList * table)413 MenuAddComboAtom (int x, int y, int w_text, const char *text, int w, XBAtom * atom,
414 				  XBComboEntryList * table)
415 {
416 	return MenuAdd (MenuCreateCombo (x, y, w_text, text, w, NULL, NULL, atom, table));
417 }								/* MenuAddComboAtom */
418 
419 /*
420  * add a combobox to menu, check all entries
421  */
422 MENU_ID
MenuAddCombo(int x,int y,int w_text,const char * text,int w,int * value,void ** data,XBAtom * atom,XBComboEntryList * table)423 MenuAddCombo (int x, int y, int w_text, const char *text, int w, int *value, void **data,
424 			  XBAtom * atom, XBComboEntryList * table)
425 {
426 	return MenuAdd (MenuCreateCombo (x, y, w_text, text, w, value, data, atom, table));
427 }								/* MenuAddCombo */
428 
429 /*
430  * add a player graphics to menu
431  */
432 MENU_ID
MenuAddPlayer(int x,int y,int w,int sprite,const CFGPlayerGraphics ** cfg,int n_anime,BMSpriteAnimation * anime)433 MenuAddPlayer (int x, int y, int w, int sprite, const CFGPlayerGraphics ** cfg, int n_anime,
434 			   BMSpriteAnimation * anime)
435 {
436 	return MenuAdd (MenuCreatePlayer (x, y, w, sprite, cfg, n_anime, anime));
437 }								/* MenuAddPlayer */
438 
439 /*
440  * add a player graphics to menu
441  */
442 MENU_ID
MenuAddConfigPlayer(int x,int y,int w,int sprite,const CFGPlayerGraphics ** cfg,int n_anime,BMSpriteAnimation * anime,XBRgbValue * pRgb)443 MenuAddConfigPlayer (int x, int y, int w, int sprite, const CFGPlayerGraphics ** cfg, int n_anime,
444 					 BMSpriteAnimation * anime, XBRgbValue * pRgb)
445 {
446 	return MenuAdd (MenuCreateConfigPlayer (x, y, w, sprite, cfg, n_anime, anime, pRgb));
447 }								/* MenuAddPlayer */
448 
449 /*
450  * add an item for string input to menu
451  */
452 MENU_ID
MenuAddString(int x,int y,int w_text,const char * text,int w,char * buffer,size_t len)453 MenuAddString (int x, int y, int w_text, const char *text, int w, char *buffer, size_t len)
454 {
455 	return MenuAdd (MenuCreateString (x, y, w_text, text, w, buffer, len));
456 }								/* MenuAddString */
457 
458 /*
459  * add an item for changing a color to menu
460  */
461 MENU_ID
MenuAddColor(int x,int y,int w,const char * text,XBColor * color,XBRgbValue * pRgb)462 MenuAddColor (int x, int y, int w, const char *text, XBColor * color, XBRgbValue * pRgb)
463 {
464 	return MenuAdd (MenuCreateColor (x, y, w, text, color, pRgb));
465 }								/* MenuAddColor */
466 
467 /*
468  * add an item for assigning a key to menu
469  */
470 MENU_ID
MenuAddKeysym(int x,int y,int w,const char * text,XBAtom * pKey)471 MenuAddKeysym (int x, int y, int w, const char *text, XBAtom * pKey)
472 {
473 	return MenuAdd (MenuCreateKeysym (x, y, w, text, pKey));
474 }								/* MenuAddKeysym */
475 
476 /*
477  * add an invisble item for a poll function
478  */
479 MENU_ID
MenuAddCyclic(MIC_cyclic func,void * par)480 MenuAddCyclic (MIC_cyclic func, void *par)
481 {
482 	return MenuAdd (MenuCreateCyclic (func, par));
483 }								/* MenuAddCyclic */
484 
485 /*
486  * add an item for integer input to menu
487  */
488 MENU_ID
MenuAddInteger(int x,int y,int w_text,const char * text,int w,int * pValue,int min,int max)489 MenuAddInteger (int x, int y, int w_text, const char *text, int w, int *pValue, int min, int max)
490 {
491 	return MenuAdd (MenuCreateInteger (x, y, w_text, text, w, pValue, min, max));
492 }								/* MenuAddInteger */
493 
494 /*
495  * add a name tag for players
496  */
497 MENU_ID
MenuAddTag(int x,int y,int w,const char ** pText)498 MenuAddTag (int x, int y, int w, const char **pText)
499 {
500 	return MenuAdd (MenuCreateTag (x, y, w, pText));
501 }								/* MenuAddTag */
502 
503 /*
504  * add integer tag (counter)
505  */
506 MENU_ID
MenuAddIntTag(int x,int y,int w,int * pNr)507 MenuAddIntTag (int x, int y, int w, int *pNr)
508 {
509 	return MenuAdd (MenuCreateIntTag (x, y, w, pNr));
510 }								/* MenuAddIntTag */
511 
512 /*******************************************
513  * host items for server/client wait menus *
514  *******************************************/
515 
516 /*
517  * add a generic host button
518  */
519 MENU_ID
MenuAddHost(int x,int y,int w,unsigned client,const char ** pText,XBHSFocusFunc focusFunc,XBHSChangeFunc chgFunc,XBHSUpdateFunc upFunc)520 MenuAddHost (int x, int y, int w, unsigned client, const char **pText, XBHSFocusFunc focusFunc,
521 			 XBHSChangeFunc chgFunc, XBHSUpdateFunc upFunc)
522 {
523 	return MenuAdd (MenuCreateHost (x, y, w, client, pText, focusFunc, chgFunc, upFunc));
524 }								/* MenuAddHost */
525 
526 /*
527  * host button (server)
528  */
529 MENU_ID
MenuAddServer(int x,int y,int w,const char ** pText)530 MenuAddServer (int x, int y, int w, const char **pText)
531 {
532 	return MenuAdd (MenuCreateServer (x, y, w, pText));
533 }								/* MenuAddServer */
534 
535 /*
536  * host button (client)
537  */
538 MENU_ID
MenuAddClient(int x,int y,int w,const char ** pText,XBHostState * pState,const int * pPing)539 MenuAddClient (int x, int y, int w, const char **pText, XBHostState * pState, const int *pPing)
540 {
541 	return MenuAdd (MenuCreateClient (x, y, w, pText, pState, pPing));
542 }								/* MenuAddClient */
543 
544 /*
545  * host button (peer)
546  */
547 MENU_ID
MenuAddPeer(int x,int y,int w,const char ** pText,XBHostState * pState,const int * pPing)548 MenuAddPeer (int x, int y, int w, const char **pText, XBHostState * pState, const int *pPing)
549 {
550 	return MenuAdd (MenuCreatePeer (x, y, w, pText, pState, pPing));
551 }								/* MenuAddPeer */
552 
553 /*******************************************
554  * team items for server/client wait menus *
555  *******************************************/
556 
557 /*
558  * team button (generic)
559  */
560 MENU_ID
MenuAddTeam(int x,int y,int w,unsigned id,unsigned player,XBTSFocusFunc focusFunc,XBTSChangeFunc chgFunc,XBTSUpdateFunc upFunc)561 MenuAddTeam (int x, int y, int w, unsigned id, unsigned player, XBTSFocusFunc focusFunc,
562 			 XBTSChangeFunc chgFunc, XBTSUpdateFunc upFunc)
563 {
564 	return MenuAdd (MenuCreateTeam (x, y, w, id, player, focusFunc, chgFunc, upFunc));
565 }								/* MenuAddTeam */
566 
567 /*
568  * team button (server)
569  */
570 MENU_ID
MenuAddServerTeam(int x,int y,int w,XBTeamState * pTeam)571 MenuAddServerTeam (int x, int y, int w, XBTeamState * pTeam)
572 {
573 	return MenuAdd (MenuCreateServerTeam (x, y, w, pTeam));
574 }								/* MenuAddServerTeam */
575 
576 /*
577  * team button (peeer)
578  */
579 MENU_ID
MenuAddPeerTeam(int x,int y,int w,XBTeamState * pTeam)580 MenuAddPeerTeam (int x, int y, int w, XBTeamState * pTeam)
581 {
582 	return MenuAdd (MenuCreatePeerTeam (x, y, w, pTeam));
583 }								/* MenuAddPeerTeam */
584 
585 /*
586  * add statitics header to menu
587  */
588 MENU_ID
MenuAddStatHeader(int x,int y,int w,const char * title)589 MenuAddStatHeader (int x, int y, int w, const char *title)
590 {
591 	return MenuAdd (MenuCreateStatHeader (x, y, w, title));
592 }								/* MenuAddHButton */
593 
594 /*
595  * add table entry to menu
596  */
597 MENU_ID
MenuAddStatEntry(int x,int y,int w,const XBStatData * stat,MIC_button func,void * funcData)598 MenuAddStatEntry (int x, int y, int w, const XBStatData * stat, MIC_button func, void *funcData)
599 {
600 	return MenuAdd (MenuCreateStatEntry (x, y, w, stat, func, funcData));
601 }								/* MenuAddHButton */
602 
603 /*
604  * add table entry to menu
605  */
606 MENU_ID
MenuAddDemoEntry(int x,int y,int w,const CFGDemoEntry * demo,MIC_button func,void * funcData)607 MenuAddDemoEntry (int x, int y, int w, const CFGDemoEntry * demo, MIC_button func, void *funcData)
608 {
609 	return MenuAdd (MenuCreateDemoEntry (x, y, w, demo, func, funcData));
610 }								/* MenuAddHButton */
611 
612 /*
613  * add statitics header to menu
614  */
615 MENU_ID
MenuAddDemoHeader(int x,int y,int w)616 MenuAddDemoHeader (int x, int y, int w)
617 {
618 	return MenuAdd (MenuCreateDemoHeader (x, y, w));
619 }								/* MenuAddHButton */
620 
621 /*
622  * add statitics header to menu
623  */
624 MENU_ID
MenuAddGameEntry(int x,int y,int w,const XBNetworkGame ** game,MIC_button func)625 MenuAddGameEntry (int x, int y, int w, const XBNetworkGame ** game, MIC_button func)
626 {
627 	return MenuAdd (MenuCreateGameEntry (x, y, w, game, func));
628 }								/* MenuAddHButton */
629 
630 /*
631  * add statitics header to menu
632  */
633 MENU_ID
MenuAddGameHeader(int x,int y,int w)634 MenuAddGameHeader (int x, int y, int w)
635 {
636 	return MenuAdd (MenuCreateGameHeader (x, y, w));
637 }								/* MenuAddHButton */
638 
639 /*
640  * XBCC add statitics header to menu
641  */
642 MENU_ID
MenuAddCentralHeader(int x,int y,int w,const char * title)643 MenuAddCentralHeader (int x, int y, int w, const char *title)
644 {
645 	return MenuAdd (MenuCreateCentralHeader (x, y, w, title));
646 }								/* MenuAddHButton */
647 
648 /*
649  * XBCC add table entry to menu
650  */
651 MENU_ID
MenuAddCentralEntry(int x,int y,int w,const XBCentralData * stat,MIC_button func,void * funcData)652 MenuAddCentralEntry (int x, int y, int w, const XBCentralData * stat, MIC_button func,
653 					 void *funcData)
654 {
655 	return MenuAdd (MenuCreateCentralEntry (x, y, w, stat, func, funcData));
656 }								/* MenuAddHButton */
657 
658 /*
659  * XBCC add info header to menu
660  */
661 MENU_ID
MenuAddInfoHeader(int x,int y,int w,const char * title)662 MenuAddInfoHeader (int x, int y, int w, const char *title)
663 {
664 	return MenuAdd (MenuCreateInfoHeader (x, y, w, title));
665 }								/* MenuAddHButton */
666 
667 /*
668  * XBCC add table entry to menu
669  */
670 MENU_ID
MenuAddInfoEntry(int x,int y,int w,const XBCentralInfo * stat,MIC_button func,void * funcData)671 MenuAddInfoEntry (int x, int y, int w, const XBCentralInfo * stat, MIC_button func, void *funcData)
672 {
673 	return MenuAdd (MenuCreateInfoEntry (x, y, w, stat, func, funcData));
674 }								/* MenuAddHButton */
675 
676 /*------------------------------------------------------------------------
677  *
678  * Event handling
679  *
680  *------------------------------------------------------------------------*/
681 
682 /*
683  * redraw routine for menu (used after timer event)
684  */
685 void
MenuUpdateWindow(void)686 MenuUpdateWindow (void)
687 {
688 	XBMenuItem *item;
689 	XBEventData eData;
690 
691 	/* call poll routines for all objects */
692 	for (item = itemFirst; item != NULL; item = item->next) {
693 		if (NULL != item->poll) {
694 			(*item->poll) (item);
695 		}
696 	}
697 	/* shuffle sprites and mark them */
698 	ShuffleAllSprites ();
699 	/* set rectangles to be redrawn */
700 	SetRedrawRectangles ();
701 	/* shuffle sprites and mark them */
702 	MarkAllSprites ();
703 	/* update maze pixmap */
704 	UpdateMaze ();
705 	/* draw sprites into pixmap */
706 	DrawAllSprites ();
707 	/* fade in if neccessary */
708 	if (fadeFlag) {
709 		fadeFlag = XBFalse;
710 		/* inits */
711 		GUI_InitFade (XBFM_IN, PIXH + SCOREH);
712 		/* do it */
713 		while (GUI_DoFade ()) {
714 			while (XBE_TIMER != GUI_WaitEvent (&eData))
715 				continue;
716 		}
717 	}
718 	/* update window from pixmap */
719 	GUI_FlushPixmap (XBTrue);
720 	/* clear the redraw map */
721 	ClearRedrawMap ();
722 }								/* MenuUpdateWindow */
723 
724 /*
725  * move focus to next item in list
726  */
727 static void
MoveFocus(XBMenuKey dir)728 MoveFocus (XBMenuKey dir)
729 {
730 	if (itemFocus != NULL) {
731 		XBMenuItem *newFocus;
732 		switch (dir) {
733 			/* arrow keys */
734 		case XBMK_LEFT:
735 			newFocus = itemFocus->left;
736 			while (newFocus && newFocus->flags & MIF_DEACTIVATED) {
737 				newFocus = newFocus->left;
738 			}
739 			break;
740 		case XBMK_RIGHT:
741 			newFocus = itemFocus->right;
742 			while (newFocus && newFocus->flags & MIF_DEACTIVATED) {
743 				newFocus = newFocus->right;
744 			}
745 			break;
746 		case XBMK_UP:
747 			newFocus = itemFocus->up;
748 			while (newFocus && newFocus->flags & MIF_DEACTIVATED) {
749 				newFocus = newFocus->up;
750 			}
751 			break;
752 		case XBMK_DOWN:
753 			newFocus = itemFocus->down;
754 			while (newFocus && newFocus->flags & MIF_DEACTIVATED) {
755 				newFocus = newFocus->down;
756 			}
757 			break;
758 			/* next in list */
759 		case XBMK_NEXT:
760 			newFocus = itemFocus->next;
761 			while (newFocus != NULL) {
762 				if (newFocus->focus != NULL && !(newFocus->flags & MIF_DEACTIVATED)) {
763 					break;
764 				}
765 				newFocus = newFocus->next;
766 			}
767 			break;
768 			/* previous in list */
769 		case XBMK_PREV:
770 			newFocus = itemFocus->prev;
771 			while (newFocus != NULL) {
772 				if (newFocus->focus != NULL && !(newFocus->flags & MIF_DEACTIVATED)) {
773 					break;
774 				}
775 				newFocus = newFocus->prev;
776 			}
777 			break;
778 		default:
779 			return;
780 		}
781 		if (NULL != newFocus) {
782 			itemFocus->flags &= ~MIF_FOCUS;
783 			newFocus->flags |= MIF_FOCUS;
784 			(*itemFocus->focus) (itemFocus, XBFalse);
785 			(*newFocus->focus) (newFocus, XBTrue);
786 			itemFocus = newFocus;
787 		}
788 	}
789 }								/* MoveFocus */
790 
791 /*
792  * set mouse to position
793  */
794 static void
SetMousePosition(int x,int y)795 SetMousePosition (int x, int y)
796 {
797 	XBMenuItem *newItem = MenuGetMouseItem (x, y);
798 	/* set new focus if needed */
799 	if (NULL != newItem && !(newItem->flags & MIF_DEACTIVATED) && newItem != itemFocus) {
800 		/* take back old focus */
801 		if (NULL != itemFocus) {
802 			itemFocus->flags &= ~MIF_FOCUS;
803 			assert (NULL != itemFocus->focus);
804 			(*itemFocus->focus) (itemFocus, XBFalse);
805 		}
806 		/* set new focus */
807 		itemFocus = newItem;
808 		itemFocus->flags |= MIF_FOCUS;
809 		assert (NULL != itemFocus->focus);
810 		(*itemFocus->focus) (itemFocus, XBTrue);
811 	}
812 }								/* SetMousePosition */
813 
814 /*
815  * determine item under mouse
816  */
817 static void
MouseItem(XBEventCode button,int x,int y)818 MouseItem (XBEventCode button, int x, int y)
819 {
820 	if (itemFocus != NULL && itemFocus == MenuGetMouseItem (x, y) && itemFocus->mouse != NULL) {
821 		(*itemFocus->mouse) (itemFocus, button);
822 	}
823 }								/* MouseItem */
824 
825 /*
826  * edit events
827  */
828 static XBBool
EditEvent(XBEventCode event,XBEventData data)829 EditEvent (XBEventCode event, XBEventData data)
830 {
831 	if (!mapMode) {
832 		return XBFalse;
833 	}
834 	switch (event) {
835 	case XBE_RMOUSE_2:
836 		SetOldBlock ();
837 	case XBE_RMOUSE_1:
838 	case XBE_RMOUSE_3:
839 		setPressed = 0;
840 		break;
841 	case XBE_MOUSE_2:
842 		SetToBlockFree ();
843 	case XBE_MOUSE_1:
844 	case XBE_MOUSE_3:
845 		setPressed = 1;
846 		fprintf (stderr, "mouse 1/3 pressed on  %i %i \n", data.pos.x, data.pos.y);
847 		SetEditMapBlock (data.pos.x, data.pos.y);
848 		return XBFalse;			/* pass mouse buttons on to default */
849 		/* mouse motion event */
850 	case XBE_MOUSE_MOVE:
851 		if (setPressed) {
852 			SetEditMapBlock (data.pos.x, data.pos.y);
853 		}
854 		UpdateMaze ();
855 		return XBFalse;			/* pass mouse move to default */
856 	default:
857 		return XBFalse;
858 	}
859 	return XBTrue;
860 }								/* EditEvent */
861 
862 /*
863  * default events
864  */
865 static XBBool
DefaultEvent(XBEventCode event,XBEventData data)866 DefaultEvent (XBEventCode event, XBEventData data)
867 {
868 	switch (event) {
869 		/* menu keys */
870 	case XBE_MENU:
871 		switch (data.value) {
872 		case XBMK_PREV:
873 		case XBMK_NEXT:
874 		case XBMK_LEFT:
875 		case XBMK_RIGHT:
876 		case XBMK_UP:
877 		case XBMK_DOWN:
878 			MoveFocus (data.value);
879 			break;
880 		case XBMK_SELECT:
881 			SelectItem (itemFocus);
882 			break;
883 		case XBMK_ABORT:
884 			SelectItem (abortItem);
885 			break;
886 		case XBMK_DEFAULT:
887 			SelectItem (defaultItem);
888 			break;
889 		default:
890 			break;
891 		}
892 		break;
893 		/* mouse events */
894 	case XBE_MOUSE_1:
895 	case XBE_MOUSE_2:
896 	case XBE_MOUSE_3:
897 		SetMousePosition (data.pos.x, data.pos.y);
898 		MouseItem (event, data.pos.x, data.pos.y);
899 		break;
900 		/* mouse motion event */
901 	case XBE_MOUSE_MOVE:
902 		SetMousePosition (data.pos.x, data.pos.y);
903 		break;
904 	default:
905 		return XBFalse;
906 	}
907 	return XBTrue;
908 }								/* DefaultEvent */
909 
910 /*
911  * event handling for menus
912  */
913 XBBool
MenuEventLoop(void)914 MenuEventLoop (void)
915 {
916 	int result;
917 	XBEventCode event;
918 	XBEventData data;
919 
920 	/* load background graphics */
921 	MenuLoadTiles ();
922 	/* wait for kb event */
923 	GUI_SetTimer (FRAME_TIME, XBTrue);
924 	GUI_SetKeyboardMode (KB_MENU);
925 	GUI_SetMouseMode (XBTrue);
926 	/* event loop */
927 	while (1) {
928 		/* update window contents */
929 		MenuUpdateWindow ();
930 		/* exec any delayed functions */
931 		if (execFlag) {
932 			execFlag = XBFalse;
933 			result = MenuExecButton ();
934 			/* no menu left start (or quit) game */
935 			if (NULL == itemFirst) {
936 				/* unload background graphics */
937 				MenuUnloadTiles ();
938 				return result;
939 			}
940 		}
941 		/* get event from gui */
942 		while (XBE_TIMER != (event = GUI_WaitEvent (&data))) {
943 			if (!Chat_Event (event, data) &&
944 				!EditEvent (event, data) && !DefaultEvent (event, data)) {
945 				continue;
946 			}
947 			result = MenuExecButton ();
948 			/* no menu left start (or quit) game */
949 			if (NULL == itemFirst) {
950 				/* unload background graphics */
951 				MenuUnloadTiles ();
952 				return result;
953 			}
954 		}
955 	}
956 	/* unload background graphics */
957 	MenuUnloadTiles ();
958 	return XBTrue;
959 }								/* MenuEventLoop */
960 
961 /*
962  * set default item
963  */
964 void
MenuDeleteItemById(MENU_ID id)965 MenuDeleteItemById (MENU_ID id)
966 {
967 	XBMenuItem *itemTemp;
968 	XBMenuItem *item_next;
969 	itemTemp = FindItem (id);
970 	if (itemTemp == NULL) {
971 		return;
972 	}
973 	item_next = itemTemp->next;
974 	DeleteMenuItem (itemTemp);
975 	itemTemp = item_next;
976 }								/* MenuDeleteItemById */
977 
978 /*
979  * end of file mi_tool.c
980  */
981