1 #include "menu.h"
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <ctype.h>
6 #include <GL/gl.h>
7 #include "options.h"
8 #include "sys_stuff.h"
9 
10 
menu_new(void (* callback)(int,void *))11 menuType * menu_new( void (* callback)( int, void * ) )
12 {
13     menuType * menu;
14 
15     DPRINTF("menu_new:\n");
16 
17     menu = malloc(sizeof(menuType));
18     menu->nr           = 0;
19     menu->select_id    = -1;
20     menu->p_select_id  = &(menu->select_id);
21     menu->select_index = 0;
22     menu->textedit_mode = 0;
23     menu->callback     = callback;
24     menu->parent       = (menuType *)0;
25     return menu;
26 }
27 
28 
menu_add_submenu(menuType * menu,char * text,menuType * submenu,int show_subsetting)29 void menu_add_submenu( menuType * menu, char * text, menuType * submenu, int show_subsetting )
30 {
31     DPRINTF("menu_add_submenu:\n");
32     if(menu->nr<MAX_MENU_ENTRY_NUM){
33         menu->entry[menu->nr].type     = ENTRY_TYPE_SUBMENU;
34         strcpy( menu->entry[menu->nr].text, text);
35         menu->entry[menu->nr].settingtext[0] = 0;
36         menu->entry[menu->nr].submenu  = submenu;
37         menu->entry[menu->nr].text_obj = (textObj *)0;
38 //    menu->entry[menu->nr].settingtext_obj = (textObj *)0;
39         menu->entry[menu->nr].fontname = options_menu_fontname;
40         menu->entry[menu->nr].fontsize = 32;
41         menu->entry[menu->nr].show_subsetting = show_subsetting;
42         menu->entry[menu->nr].arg      = (void *) 0;
43         if(submenu!=(menuType *)0){
44             submenu->callback     = menu->callback;
45             submenu->p_select_id  = menu->p_select_id;
46             submenu->parent       = menu;
47             submenu->parent_entry = &(menu->entry[menu->nr]);
48         }
49         menu->nr++;
50     } else {
51         printf("menu_add_submenu: too many menu entries - ignoring this entry\n");
52     }
53 }
54 
55 
menu_add_entry(menuType * menu,char * text,int id)56 void menu_add_entry( menuType * menu, char * text, int id )
57 {
58     DPRINTF("menu_add_entry:\n");
59     if(menu->nr<MAX_MENU_ENTRY_NUM){
60         menu->entry[menu->nr].type     = ENTRY_TYPE_ID;
61         strcpy( menu->entry[menu->nr].text, text );
62         menu->entry[menu->nr].settingtext[0] = 0;
63         menu->entry[menu->nr].id       = id;
64         menu->entry[menu->nr].text_obj = (textObj *)0;
65 //    menu->entry[menu->nr].settingtext_obj = (textObj *)0;
66         menu->entry[menu->nr].fontname = options_menu_fontname;
67         menu->entry[menu->nr].fontsize = 32;
68         menu->entry[menu->nr].arg      = (void *) 0;
69         menu->nr++;
70     } else {
71         printf("menu_add_entry: too many menu entries - ignoring this entry\n");
72     }
73 }
74 
75 
menu_add_arg_entry(menuType * menu,char * text,int id,void * arg)76 void menu_add_arg_entry( menuType * menu, char * text, int id, void * arg )
77 {
78     DPRINTF("menu_add_arg_entry:\n");
79     if(menu->nr<MAX_MENU_ENTRY_NUM){
80         menu->entry[menu->nr].type     = ENTRY_TYPE_ID;
81         strcpy( menu->entry[menu->nr].text, text );
82         menu->entry[menu->nr].settingtext[0] = 0;
83         menu->entry[menu->nr].id       = id;
84         menu->entry[menu->nr].text_obj = (textObj *)0;
85         //    menu->entry[menu->nr].settingtext_obj = (textObj *)0;
86         menu->entry[menu->nr].fontname = options_menu_fontname;
87         menu->entry[menu->nr].fontsize = 32;
88         menu->entry[menu->nr].arg      = arg;
89         menu->nr++;
90     } else {
91         printf("menu_add_arg_entry: too many menu entries - ignoring this entry\n");
92     }
93 }
94 
95 
menu_add_textfield(menuType * menu,char * text,int id,int fixedlen)96 void menu_add_textfield( menuType * menu, char * text, int id, int fixedlen )
97 {
98     DPRINTF("menu_add_arg_entry:\n");
99     if(menu->nr<MAX_MENU_ENTRY_NUM){
100         menu->entry[menu->nr].type     = ENTRY_TYPE_TEXTFIELD;
101         strcpy( menu->entry[menu->nr].text, text );
102         menu->entry[menu->nr].settingtext[0] = 0;
103         menu->entry[menu->nr].id       = id;
104         menu->entry[menu->nr].text_obj = (textObj *)0;
105         //    menu->entry[menu->nr].settingtext_obj = (textObj *)0;
106         menu->entry[menu->nr].fontname = options_menu_fontname;
107         menu->entry[menu->nr].fontsize = 32;
108         menu->entry[menu->nr].arg      = (void *)0;
109         menu->entry[menu->nr].fixedlen = fixedlen;
110         menu->nr++;
111     } else {
112         printf("menu_add_textfield: too many menu entries - ignoring this entry\n");
113     }
114 }
115 
116 
menu_add_exit(menuType * menu,char * text)117 void menu_add_exit( menuType * menu, char * text )
118 {
119     DPRINTF("menu_add_exit:\n");
120     if(menu->nr<MAX_MENU_ENTRY_NUM){
121         menu->entry[menu->nr].type     = ENTRY_TYPE_EXIT;
122         strcpy( menu->entry[menu->nr].text, text );
123         menu->entry[menu->nr].settingtext[0] = 0;
124         menu->entry[menu->nr].text_obj = (textObj *)0;
125 //    menu->entry[menu->nr].settingtext_obj = (textObj *)0;
126         menu->entry[menu->nr].fontname = options_menu_fontname;
127         menu->entry[menu->nr].fontsize = 32;
128         menu->entry[menu->nr].arg      = (void *) 0;
129         menu->nr++;
130     } else {
131         printf("menu_add_exit: too many menu entries - ignoring this entry\n");
132     }
133 }
134 
135 
menu_entry_set_text(menuEntry * entry,char * text)136 void menu_entry_set_text( menuEntry * entry, char * text )
137 {
138     char str[256];
139     strcpy( entry->text, text );
140     if( entry->text_obj != (textObj *)0 ){
141         if( entry->show_subsetting && entry->settingtext[0]!=0 ){
142             sprintf(str,"%s : %s",entry->text,entry->settingtext);
143             textObj_setText( entry->text_obj, str );
144 //            textObj_setText( entry->text_obj, text );
145         } else {
146             textObj_setText( entry->text_obj, text );
147         }
148     }
149 }
150 
151 
menu_entry_set_settingtext(menuEntry * entry,char * text)152 void menu_entry_set_settingtext( menuEntry * entry, char * text )
153 {
154     char str[256];
155     strcpy( entry->settingtext, text );
156     if( entry->text_obj != (textObj *)0 ){
157         if( entry->show_subsetting && entry->settingtext[0]!=0 ){
158             sprintf(str,"%s : %s",entry->text,entry->settingtext);
159             textObj_setText( entry->text_obj, str );
160 /*            sprintf(str," : %s",entry->settingtext);
161             if( entry->settingtext_obj != (textObj *)0 ){
162                 textObj_setText( entry->settingtext_obj, str );
163             } else {
164                 entry->settingtext_obj=textObj_new( str, entry->fontname, entry->fontsize );
165             }*/
166         } else {
167             textObj_setText( entry->text_obj, text );
168         }
169     }
170 }
171 
172 
menu_create_textobj(menuEntry * entry)173 static void menu_create_textobj( menuEntry * entry )
174 {
175     char str[256];
176     if( entry->text_obj == (textObj *)0 ){
177         if( entry->show_subsetting && entry->settingtext[0]!=0 ){
178             sprintf(str,"%s : %s",entry->text,entry->settingtext);
179             entry->text_obj = textObj_new( str, entry->fontname, entry->fontsize );
180 /*            entry->text_obj = textObj_new( entry->text, entry->fontname, entry->fontsize );
181             sprintf(str," : %s",entry->settingtext);
182             entry->settingtext_obj = textObj_new( str, entry->fontname, entry->fontsize );*/
183         } else {
184             entry->text_obj = textObj_new( entry->text, entry->fontname, entry->fontsize );
185         }
186 //        textObj_toggle3D(entry->text_obj);
187     }
188 }
189 
menu_select_by_coord(menuType * menu,int x,int y)190 void menu_select_by_coord( menuType * menu, int x, int y )
191 /* selects the menupoint under the pos x,y */
192 {
193     int i,x1,y1,x2,y2, all_height;
194 
195     if(!menu->textedit_mode){
196         all_height=0;
197         for(i=0;i<menu->nr;i++){
198             all_height+=menu->entry[i].fontsize;
199         }
200 
201         for(i=0;i<menu->nr;i++){
202             //        fprintf( stderr, "menu->entry[i].text_obj = %d\n", menu->entry[i].text_obj );
203             if( menu->entry[i].text_obj == (textObj *)0 ){
204                 menu_create_textobj( &(menu->entry[i]) );
205             }
206             x1 = -menu->entry[i].text_obj->quad_w/2;
207             y1 = all_height/2-i*menu->entry[i].fontsize-menu->entry[i].text_obj->quad_h/2;
208             x2 = +menu->entry[i].text_obj->quad_w/2;
209             y2 = all_height/2-i*menu->entry[i].fontsize+menu->entry[i].text_obj->quad_h/2;
210             if( x<=x2 && x>=x1 && y<=y2 && y>=y1 ){
211                 menu->select_index=i;
212                 *(menu->p_select_id)=menu->entry[i].id;
213             }
214         }
215     }
216 }
217 
218 
menu_select_next(menuType * menu)219 void menu_select_next( menuType * menu )
220 /* selects the next menupoint in the current submenu */
221 {
222     if(!menu->textedit_mode){
223         (menu->select_index)++;
224         if( menu->select_index >= menu->nr ) menu->select_index=0;
225         *(menu->p_select_id) = menu->entry[menu->select_index].id;
226     }
227 }
228 
menu_select_prev(menuType * menu)229 void menu_select_prev( menuType * menu )
230 /* selects the previous menupoint in the current submenu */
231 {
232     if(!menu->textedit_mode){
233         (menu->select_index)--;
234         if( menu->select_index < 0 ) menu->select_index=(menu->nr)-1;
235         *(menu->p_select_id) = menu->entry[menu->select_index].id;
236     }
237 }
238 
menu_choose(menuType ** menu)239 void menu_choose(menuType ** menu)
240 {
241     DPRINTF("menu_choose:\n");
242     if( (*menu)->entry[(*menu)->select_index].type==ENTRY_TYPE_SUBMENU ) {
243 
244         DPRINTF("menu_choose: switch submenu\n");
245 //        menu_texObj_cleanup(menu);
246         (*menu)=(*menu)->entry[(*menu)->select_index].submenu;
247 
248     } else if( (*menu)->entry[(*menu)->select_index].type==ENTRY_TYPE_ID ) {
249 
250         DPRINTF("menu_choose: id=%d\n",(*menu)->entry[(*menu)->select_index].id);
251         if( (*menu)->parent_entry != 0 ){
252             if( (*menu)->parent_entry->show_subsetting ){
253                 menu_entry_set_settingtext( (*menu)->parent_entry, (*menu)->entry[(*menu)->select_index].text );
254             }
255         }
256         (*menu)->callback( (*menu)->entry[(*menu)->select_index].id,
257                            (*menu)->entry[(*menu)->select_index].arg );
258         menu_exit(menu);
259 
260     } else if( (*menu)->entry[(*menu)->select_index].type==ENTRY_TYPE_TEXTFIELD ) {
261         DPRINTF("menu_choose: ENTRY_TYPE_TEXTFIELD\n");
262         if(!(*menu)->textedit_mode){
263             DPRINTF("menu_choose: ENTRY_TYPE_TEXTFIELD - !textedit_mode\n");
264             (*menu)->textedit_mode=1;
265         } else {
266             DPRINTF("menu_choose: ENTRY_TYPE_TEXTFIELD - textedit_mode\n");
267             (*menu)->textedit_mode=0;
268             strcpy((*menu)->entry[(*menu)->select_index].text,
269                    (*menu)->entry[(*menu)->select_index].text_obj->str);
270             /* give the entered string as arg */
271             (*menu)->entry[(*menu)->select_index].arg = (void *)&((*menu)->entry[(*menu)->select_index].text[(*menu)->entry[(*menu)->select_index].fixedlen]);
272             DPRINTF("printing arg:\n");
273             DPRINTF("%s\n",(char *)((*menu)->entry[(*menu)->select_index].arg));
274             (*menu)->callback( (*menu)->entry[(*menu)->select_index].id,
275                                (*menu)->entry[(*menu)->select_index].arg );
276         }
277     } else if( (*menu)->entry[(*menu)->select_index].type==ENTRY_TYPE_EXIT ) {
278 
279         menu_exit(menu);
280 
281     }
282 }
283 
284 
menu_exit(menuType ** menu)285 void menu_exit(menuType ** menu)
286 {
287     DPRINTF("menu_exit:\n");
288     if(!(*menu)->textedit_mode){
289 /*    if( (*menu)->parent != (menuType *)0 ){*/
290         DPRINTF("menu_exit: switch to parent\n");
291         menu_texObj_cleanup(*menu);
292         *menu=(*menu)->parent;
293         DPRINTF("menu_exit: switch to parent - end\n");
294 /*    } else {
295         fprintf(stderr,"menu_exit: cleanup only\n");
296         menu_texObj_cleanup(*menu);
297         }*/
298     } else {
299         textObj_setText( (*menu)->entry[(*menu)->select_index].text_obj, (*menu)->entry[(*menu)->select_index].text );
300         (*menu)->textedit_mode=0;
301     }
302 }
303 
304 
305 
menu_text_keystroke(menuType * menu,int key)306 void menu_text_keystroke( menuType * menu, int key )
307 {
308     if(menu->textedit_mode){
309         switch(key){
310         case 8:
311             if(strlen(menu->entry[menu->select_index].text_obj->str) > menu->entry[menu->select_index].fixedlen)
312                 textObj_delete_last( menu->entry[menu->select_index].text_obj );
313             break;
314         default:
315             if (isprint(key))
316                 textObj_append_char( menu->entry[menu->select_index].text_obj, key );
317             break;
318         }
319     }
320 }
321 
322 
323 
menu_draw_entry(menuEntry * entry)324 static void menu_draw_entry( menuEntry * entry )
325 {
326     if( entry->text_obj == (textObj *)0 ){
327         menu_create_textobj( entry );
328     }
329     textObj_draw_centered(entry->text_obj);
330 /*    if( entry->show_subsetting ){
331         textObj_draw_bound(entry->text_obj,        HBOUND_RIGHT, VBOUND_CENTER );
332         if(entry->settingtext_obj != (textObj *)0 ){
333             textObj_draw_bound(entry->settingtext_obj, HBOUND_LEFT,  VBOUND_CENTER );
334         }
335     } else {
336         textObj_draw_bound(entry->text_obj, HBOUND_CENTER, VBOUND_CENTER );
337     }*/
338 }
339 
menu_draw(menuType * menu)340 void menu_draw( menuType * menu )
341 {
342     int i,all_height;
343 
344 //    fprintf(stderr,"menu_draw:\n");
345 
346 //    fprintf(stderr,"menu_draw: calc total height\n");
347     all_height=0;
348     for(i=0;i<menu->nr;i++){
349         all_height+=menu->entry[i].fontsize;
350     }
351 
352 //    fprintf(stderr,"menu_draw: draw\n");
353     glPushMatrix();
354     glTranslatef(0,all_height/2,0);
355 //    for(i=0;i<1/*menu->nr*/;i++){
356     for(i=0;i<menu->nr;i++){
357         /* hilight the entry with id=*p_select_id */
358 //        fprintf(stderr,"menu_draw: draw entry#%d\n",i);
359         if( i==menu->select_index ){     /* selected menu entry */
360             if(menu->textedit_mode){     /* if textedit-field */
361                 glColor3f(1.0,0.0,0.0);
362                 menu_draw_entry(&(menu->entry[i]));
363             } else {
364                 glPushMatrix();
365                 glScalef(1.1,1.1,1.0);
366                 glBlendFunc( GL_ZERO, GL_ONE_MINUS_SRC_COLOR );
367                 glColor3f(1.0,1.0,1.0);
368                 glTranslatef(2,2,0);
369                 menu_draw_entry(&(menu->entry[i]));
370                 glTranslatef(-4,0,0);
371                 menu_draw_entry(&(menu->entry[i]));
372                 glTranslatef(0,-4,0);
373                 menu_draw_entry(&(menu->entry[i]));
374                 glTranslatef(4,0,0);
375                 menu_draw_entry(&(menu->entry[i]));
376                 glTranslatef(-2,2,0);
377                 glBlendFunc(GL_ONE,GL_ONE);
378                 glColor3f(1.0,1.0,0.0);
379                 menu_draw_entry(&(menu->entry[i]));
380                 glPopMatrix();
381             }
382         } else {         /* normal menu entry */
383             glPushMatrix();
384             glBlendFunc(GL_ZERO,GL_ONE_MINUS_SRC_COLOR);
385             glColor3f(1.0,1.0,1.0);
386             glTranslatef(2,2,0);
387             menu_draw_entry(&(menu->entry[i]));
388             glTranslatef(-4,0,0);
389             menu_draw_entry(&(menu->entry[i]));
390             glTranslatef(0,-4,0);
391             menu_draw_entry(&(menu->entry[i]));
392             glTranslatef(4,0,0);
393             menu_draw_entry(&(menu->entry[i]));
394             glTranslatef(-2,2,0);
395             glBlendFunc(GL_ONE,GL_ONE);
396             glColor3f(1.0,1.0,1.0);
397             menu_draw_entry(&(menu->entry[i]));
398             glPopMatrix();
399         }
400 
401         glTranslatef(0,-menu->entry[i].fontsize,0);
402     }
403     glPopMatrix();
404 //    fprintf(stderr,"menu_draw: end\n");
405 }
406 
407 
menu_texObj_cleanup(menuType * menu)408 void menu_texObj_cleanup(menuType * menu)
409 /* releases the gl-lists and the allocated textures */
410 {
411     int i;
412 
413     DPRINTF("menu_texObj_cleanup:\n");
414     if( menu != (menuType *)0 ){
415         for ( i=0 ; i<menu->nr ; i++ ) {
416             DPRINTF("menu_texObj_cleanup: i=%d (%s)\n",i,menu->entry[i].text);
417 
418             if( menu->entry[i].text_obj != (textObj *)0 )
419                 textObj_delete(menu->entry[i].text_obj);
420             DPRINTF("menu_texObj_cleanup: 1\n");
421 //            if( menu->entry[i].settingtext_obj != (textObj *)0 )
422 //                textObj_delete(menu->entry[i].settingtext_obj);
423 
424             if( menu->entry[i].type == ENTRY_TYPE_SUBMENU ){
425                 DPRINTF("menu_texObj_cleanup: menu_texObj_cleanup\n");
426                 menu_texObj_cleanup(menu->entry[i].submenu);
427             }
428             DPRINTF("menu_texObj_cleanup: 2\n");
429 
430             if( menu->entry[i].text_obj != (textObj *)0 )
431                 free(menu->entry[i].text_obj);
432 
433             DPRINTF("menu_texObj_cleanup: 3\n");
434             menu->entry[i].text_obj = (textObj *)0;
435             DPRINTF("menu_texObj_cleanup: 4\n");
436         }
437     }
438 }
439