1 /* $Id: menubar.c,v 1.3 2004-12-19 15:21:11 btb Exp $ */
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
16 static char rcsid[] = "$Id: menubar.c,v 1.3 2004-12-19 15:21:11 btb Exp $";
50 int (*user_function)(void);
60 grs_bitmap * Background;
66 static int num_menus = 0;
68 static int menubar_hid;
70 #define CMENU (Menu[0].CurrentItem+1)
72 //------------------------- Show a menu item -------------------
74 void item_show( MENU * menu, int n )
76 ITEM * item = &menu->Item[n];
78 gr_set_current_canvas(NULL);
79 // If this is a seperator, then draw it.
80 if ( item->Text[0] == '-' )
82 gr_setcolor( CBLACK );
83 gr_urect( item->x, item->y+item->h/2, item->x+item->w-1, item->y+item->h/2 );
87 if ( menu->CurrentItem==n && menu->ShowBar )
89 if ( menu != &Menu[0] )
91 gr_setcolor( CBLACK );
92 gr_urect( item->x+1, item->y+1, item->x+menu->w-2, item->y+item->h-2 );
94 gr_set_fontcolor( CWHITE, CBLACK );
96 if ( menu != &Menu[0] )
99 gr_urect( item->x+1, item->y+1, item->x+menu->w-2, item->y+item->h-2 );
101 gr_set_fontcolor( CBLACK, CGREY );
104 if ( menu != &Menu[0] )
107 gr_ustring( item->x+1, item->y+1, item->Text );
109 gr_ustring( item->x+1, item->y+1, item->InactiveText );
112 gr_ustring( item->x, item->y, item->Text );
114 gr_ustring( item->x, item->y, item->InactiveText );
118 //---------------------------- Show a menu ---------------------
120 void menu_show( MENU * menu )
126 gr_set_current_canvas(NULL);
127 // Don't save background it if it's already drawn
128 if (!menu->Displayed)
130 // Save the background
131 gr_bm_ubitblt(menu->w, menu->h, 0, 0, menu->x, menu->y, &(grd_curscreen->sc_canvas.cv_bitmap), menu->Background);
133 // Draw the menu background
134 gr_setcolor( CGREY );
135 gr_urect( menu->x, menu->y, menu->x + menu->w - 1, menu->y + menu->h - 1 );
136 if ( menu != &Menu[0] )
138 gr_setcolor( CBLACK );
139 gr_ubox( menu->x, menu->y, menu->x + menu->w - 1, menu->y + menu->h - 1 );
145 for (i=0; i< menu->NumItems; i++ )
146 item_show( menu, i );
150 // Mark as displayed.
154 //-------------------------- Hide a menu -----------------------
156 void menu_hide( MENU * menu )
159 // Can't hide if it's not already drawn
160 if (!menu->Displayed) return;
164 // Restore the background
167 gr_bm_ubitblt(menu->w, menu->h, menu->x, menu->y, 0, 0, menu->Background, &(grd_curscreen->sc_canvas.cv_bitmap));
176 //------------------------- Move the menu bar ------------------
178 void menu_move_bar_to( MENU * menu, int number )
182 old_item = menu->CurrentItem;
183 menu->CurrentItem = number;
185 if (menu->Displayed && (number != old_item))
189 item_show( menu, old_item );
190 item_show( menu, number );
196 //------------------------ Match keypress to item ------------------
197 int menu_match_keypress( MENU * menu, int keypress )
203 if ((keypress & KEY_CTRLED) || (keypress & KEY_SHIFTED))
208 c = key_to_ascii(keypress);
210 for (i=0; i< menu->NumItems; i++ )
212 letter = strrchr( menu->Item[i].Text, CC_UNDERLINE );
216 if (c==tolower(*letter))
224 int menu_is_mouse_on( ITEM * item )
226 if ((Mouse.x >= item->x) &&
227 (Mouse.x < item->x + item->w ) &&
228 (Mouse.y >= item->y) &&
229 (Mouse.y <= item->y + item->h ) )
235 int menu_check_mouse_item( MENU * menu )
239 for (i=0; i<menu->NumItems; i++ )
241 if (menu_is_mouse_on( &menu->Item[i] ))
243 if (menu->Item[i].Text[0] == '-')
257 for (i=1; i<num_menus; i++)
258 menu_hide( &Menu[i] );
262 menu_show( &Menu[0] );
267 static state2_alt_down;
269 void do_state_0( int keypress )
275 if (Menu[0].Displayed==0)
276 menu_show( &Menu[0] );
278 if ( keypress & KEY_ALTED ) {
279 i = menu_match_keypress( &Menu[0], keypress );
282 Menu[0].CurrentItem = i;
285 Menu[ CMENU ].ShowBar = 1;
286 Menu[ CMENU ].Active = 1;
289 menu_show( &Menu[ CMENU ] );
290 menu_show( &Menu[0] );
294 for (i=0; i<num_menus; i++ )
295 for (j=0; j< Menu[i].NumItems; j++ )
297 if ( Menu[i].Item[j].Hotkey == keypress )
299 if (Menu[i].Item[j].user_function)
300 Menu[i].Item[j].user_function();
306 if (keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] || ((keypress & 0xFF) == KEY_LALT) )
307 //if ( (keypress & 0xFF) == KEY_LALT )
311 menu_show( &Menu[0] );
315 i = menu_check_mouse_item( &Menu[0] );
317 if ( B1_PRESSED && (i > -1))
319 Menu[0].CurrentItem = i;
321 Menu[ CMENU ].ShowBar = 1;
323 Menu[ CMENU ].Active = 1;
325 menu_show( &Menu[ CMENU ] );
326 menu_show( &Menu[0] );
331 void do_state_1( int keypress )
335 if (!keyd_pressed[KEY_LALT] && !keyd_pressed[KEY_RALT] )
338 //state2_alt_down = 0;
339 //Menu[0].ShowBar = 1;
340 //Menu[0].Active = 1;
341 //menu_show( &Menu[0] );
346 i = menu_match_keypress( &Menu[0], keypress );
350 Menu[0].CurrentItem = i;
353 Menu[ CMENU ].ShowBar = 1;
354 Menu[ CMENU ].Active = 1;
357 menu_show( &Menu[ CMENU ] );
358 menu_show( &Menu[0] );
361 i = menu_check_mouse_item( &Menu[0] );
363 if ( (i == -1) && B1_JUST_RELEASED )
369 if ( B1_PRESSED && (i > -1))
371 Menu[0].CurrentItem = i;
373 Menu[ CMENU ].ShowBar = 1;
374 Menu[ CMENU ].Active = 1;
377 menu_show( &Menu[ CMENU ] );
378 menu_show( &Menu[0] );
382 void do_state_2(int keypress)
386 if (keyd_pressed[KEY_LALT] || keyd_pressed[KEY_RALT] )
389 if (!keyd_pressed[KEY_LALT] && !keyd_pressed[KEY_RALT] && state2_alt_down )
403 i = Menu[0].CurrentItem-1;
404 if (i < 0 ) i = Menu[0].NumItems-1;
405 menu_move_bar_to( &Menu[0], i );
409 i = Menu[0].CurrentItem+1;
410 if (i >= Menu[0].NumItems ) i = 0;
411 menu_move_bar_to( &Menu[0], i );
418 Menu[ CMENU ].ShowBar = 1;
419 Menu[ CMENU ].Active = 1;
421 menu_show( &Menu[ 0 ] );
422 menu_show( &Menu[ CMENU ] );
426 i = menu_match_keypress( &Menu[0], keypress );
430 Menu[0].CurrentItem = i;
433 Menu[ CMENU ].ShowBar = 1;
434 Menu[ CMENU ].Active = 1;
436 menu_show( &Menu[ CMENU ] );
437 menu_show( &Menu[0] );
441 i = menu_check_mouse_item( &Menu[0] );
443 if ( (i == -1) && B1_JUST_RELEASED )
450 if ( B1_PRESSED && (i > -1))
452 Menu[0].CurrentItem = i;
455 Menu[ CMENU ].ShowBar = 1;
456 Menu[ CMENU ].Active = 1;
458 menu_show( &Menu[ CMENU ] );
459 menu_show( &Menu[0] );
469 void do_state_3( int keypress )
481 i = Menu[ CMENU ].CurrentItem;
484 if ( i >= Menu[ CMENU ].NumItems )
486 } while( Menu[CMENU].Item[i].Text[0] == '-');
487 menu_move_bar_to( &Menu[ CMENU ], i );
491 i = Menu[ CMENU ].CurrentItem;
496 i = Menu[ CMENU ].NumItems-1;
497 } while( Menu[CMENU].Item[i].Text[0] == '-');
498 menu_move_bar_to( &Menu[ CMENU ], i );
502 menu_hide( &Menu[ CMENU ] );
503 i = Menu[0].CurrentItem+1;
504 if (i >= Menu[0].NumItems ) i = 0;
505 menu_move_bar_to( &Menu[0], i );
506 Menu[CMENU].ShowBar = 1;
507 Menu[CMENU].Active = 1;
508 menu_show( &Menu[CMENU] );
512 menu_hide( &Menu[ CMENU ] );
513 i = Menu[0].CurrentItem-1;
514 if (i < 0 ) i = Menu[0].NumItems-1;
515 menu_move_bar_to( &Menu[0], i );
516 Menu[ CMENU ].ShowBar = 1;
517 Menu[CMENU].Active = 1;
518 menu_show( &Menu[ CMENU ] );
525 if (Menu[CMENU].Item[ Menu[CMENU].CurrentItem ].user_function)
526 Menu[CMENU].Item[ Menu[CMENU].CurrentItem ].user_function();
531 i = menu_match_keypress( &Menu[ CMENU ], keypress );
535 menu_move_bar_to( &Menu[ CMENU ], i );
539 if (Menu[CMENU].Item[ Menu[CMENU].CurrentItem ].user_function)
540 Menu[CMENU].Item[ Menu[CMENU].CurrentItem ].user_function();
543 i = menu_check_mouse_item( &Menu[CMENU] );
548 menu_move_bar_to( &Menu[ CMENU ], i );
549 else if ( B1_JUST_RELEASED )
551 menu_move_bar_to( &Menu[ CMENU ], i );
555 if (Menu[CMENU].Item[ Menu[CMENU].CurrentItem ].user_function)
556 Menu[CMENU].Item[ Menu[CMENU].CurrentItem ].user_function();
560 i = menu_check_mouse_item( &Menu[0] );
562 if ( B1_PRESSED && (i > -1))
564 if ( Menu[0].CurrentItem != i) {
565 menu_hide( &Menu[ CMENU ] );
566 menu_move_bar_to( &Menu[0], i );
567 Menu[ CMENU ].ShowBar = 1;
568 Menu[CMENU].Active = 1;
569 menu_show( &Menu[ CMENU ] );
574 if ( B1_JUST_RELEASED )
586 void menubar_do( int keypress )
588 if (menubar_hid) return;
591 do_state_0(last_keypress);
599 do_state_1(last_keypress);
602 do_state_2(last_keypress);
605 do_state_3(last_keypress);
614 void CommaParse( int n, char * dest, char * source )
616 int i = 0, j=0, cn = 0;
618 // Go to the n'th comma
620 if (source[i++] == ',' )
622 // Read all the whitespace
623 while ( source[i]==' ' || source[i]=='\t' || source[i]==13 || source[i]==10 )
626 // Read up until the next comma
627 while ( source[i] != ',' )
629 dest[j] = source[i++];
637 //translate '&' characters to the underline character
638 void ul_xlate(char *s)
640 while ((s=strchr(s,'&'))!=NULL)
645 void menubar_init( char * file )
655 num_menus = state = 0;
657 for (i=0; i < MAXMENUS; i++ )
659 Menu[i].x = Menu[i].y = Menu[i].w = Menu[i].h = 0;
661 Menu[i].CurrentItem = 0;
662 Menu[i].NumItems = 0;
663 Menu[i].Displayed = 0;
664 Menu[i].Background = 0;
665 for (j=0; j< MAXITEMS; j++ )
667 Menu[i].Item[j].x = Menu[i].Item[j].y = Menu[i].Item[j].w = Menu[i].Item[j].h = 0;
668 Menu[i].Item[j].Text = NULL;
669 Menu[i].Item[j].Hotkey = -1;
670 Menu[i].Item[j].user_function = NULL;
674 infile = fopen( file, "rt" );
678 while ( fgets( buffer, 200, infile) != NULL )
680 if ( buffer[0] == ';' ) continue;
682 //mprintf( 0, "%s\n", buffer );
684 CommaParse( 0, buf1, buffer );
686 if (menu >= MAXMENUS)
687 Error("Too many menus (%d).",menu);
689 CommaParse( 1, buf1, buffer );
691 if (item >= MAXITEMS)
692 Error("Too many items (%d) in menu %d.",item+1,menu);
694 CommaParse( 2, buf1, buffer );
699 sprintf( buf2, " %s ", buf1 );
700 Menu[menu].Item[item].Text = strdup(buf2);
702 Menu[menu].Item[item].Text = strdup(buf1);
704 Menu[menu].Item[item].InactiveText = strdup(Menu[menu].Item[item].Text);
707 for (i=0; i<=strlen(Menu[menu].Item[item].Text); i++ )
709 np = Menu[menu].Item[item].Text[i];
710 if (np != CC_UNDERLINE)
711 Menu[menu].Item[item].InactiveText[j++] = np;
714 CommaParse( 3, buf1, buffer );
715 if (buf1[0]=='{' && buf1[1] =='}')
716 Menu[menu].Item[item].Hotkey = -1;
718 i = DecodeKeyText(buf1);
720 Error("Unknown key, %s, in %s\n", buf1, file );
722 Menu[menu].Item[item].Hotkey = i;
725 CommaParse( 4, buf1, buffer );
729 Menu[menu].Item[item].user_function = func_get(buf1, &np);
731 // if (!strcmp(buf1,"do-wall-dialog")) {
732 // mprintf( 0, "Found function %s\n", buf1);
733 // mprintf( 0, "User function %s\n", Menu[menu].Item[item].user_function);
736 if (Menu[menu].Item[item].user_function==NULL)
738 Error( "Unknown function, %s, in %s\n", buf1, file );
739 //MessageBox( -2, -2, 1, buffer, "Ok" );
743 Menu[menu].Item[item].x = Menu[menu].x;
744 Menu[menu].Item[item].y = Menu[menu].y;
746 if ( Menu[menu].Item[item].Text[0] == '-' )
750 gr_get_string_size( Menu[menu].Item[item].Text, &w, &h, &aw );
758 Menu[0].Item[item].x = Menu[0].x + Menu[0].w;
760 Menu[0].Item[item].y = Menu[0].y;
762 Menu[item+1].x = Menu[0].x + Menu[0].w;
763 Menu[item+1].y = Menu[0].h - 2;
765 Menu[0].Item[item].w = w;
766 Menu[0].Item[item].h = h;
771 if ( w > Menu[menu].w )
774 for (i=0; i< Menu[menu].NumItems; i++ )
775 Menu[menu].Item[i].w = Menu[menu].w;
777 Menu[menu].Item[item].w = Menu[menu].w;
778 Menu[menu].Item[item].x = Menu[menu].x;
779 Menu[menu].Item[item].y = Menu[menu].y+Menu[menu].h;
780 Menu[menu].Item[item].h = h;
784 if ( item >= Menu[menu].NumItems )
786 Menu[menu].NumItems = item+1;
789 if ( menu >= num_menus )
799 for (i=0; i<num_menus; i++ )
800 Menu[i].Background = gr_create_bitmap(Menu[i].w, Menu[i].h );
810 menu_hide( &Menu[0] );
816 menu_show( &Menu[0] );
824 //menu_hide( &Menu[0] );
826 for (i=0; i<num_menus; i++ )
827 gr_free_bitmap( Menu[i].Background );