1 #include <stdio.h>
2 #include <string.h>
3 #include <ctype.h>
4 #include <stdlib.h>
5 #include <sys/types.h>
6
7 #ifdef __MSW__
8 # include <windows.h>
9 #endif
10
11 #include <GL/gl.h>
12
13 #include "../include/string.h"
14 #include "v3dgl.h"
15 #include "v3dtex.h"
16
17 #include "gw.h"
18 #include "stategl.h"
19 #include "image.h"
20 #include "menu.h"
21
22
23 /* Utilities */
24 void SARMenuGLStateReset(gw_display_struct *display);
25 void *SARMenuGetObject(sar_menu_struct *m, int n);
26 void *SARMenuGetObjectByID(
27 sar_menu_struct *m, int id, int *n
28 );
29 Boolean SARMenuObjectIsSensitive(sar_menu_struct *m, int n);
30
31 /* Menu */
32 sar_menu_struct *SARMenuNew(
33 sar_menu_type type, const char *name, const char *bg_image
34 );
35 void SARMenuLoadBackgroundImage(sar_menu_struct *m);
36 void SARMenuUnloadBackgroundImage(sar_menu_struct *m);
37 void SARMenuDelete(sar_menu_struct *m);
38
39 /* Label */
40 int SARMenuLabelNew(
41 sar_menu_struct *m,
42 float x, float y,
43 int width, int height,
44 const char *label,
45 sar_menu_color_struct *fg_color, GWFont *font,
46 const sar_image_struct *image
47 );
48
49 /* Button */
50 int SARMenuButtonNew(
51 sar_menu_struct *m,
52 float x, float y,
53 int width, int height,
54 const char *label,
55 sar_menu_color_struct *fg_color, GWFont *font,
56 const sar_image_struct *unarmed_image,
57 const sar_image_struct *armed_image,
58 const sar_image_struct *highlighted_image,
59 void *client_data, int id,
60 void (*func_cb)(void *, int, void *)
61 );
62
63 /* Progress Bar */
64 int SARMenuProgressNew(
65 sar_menu_struct *m,
66 float x, float y,
67 int width, int height,
68 const char *label,
69 sar_menu_color_struct *fg_color,
70 GWFont *font,
71 const sar_image_struct *bg_image,
72 const sar_image_struct *fg_image,
73 float progress
74 );
75 void SARMenuProgressSet(
76 gw_display_struct *display, sar_menu_struct *m, int n,
77 float progress, Boolean redraw
78 );
79
80 /* Message Box */
81 int SARMenuMessageBoxNew(
82 sar_menu_struct *m,
83 float x, float y,
84 float width, float height,
85 sar_menu_color_struct *fg_color, GWFont *font,
86 const sar_image_struct **bg_image, /* Pointer to 9 images */
87 void *client_data, int id,
88 const char *message
89 );
90 void SARMenuMessageBoxSet(
91 gw_display_struct *display, sar_menu_struct *m, int n,
92 const char *message, Boolean redraw
93 );
94
95 /* List */
96 int SARMenuListNew(
97 sar_menu_struct *m,
98 float x, float y,
99 float width, float height,
100 sar_menu_color_struct *fg_color, GWFont *font,
101 const char *label,
102 const sar_image_struct **bg_image,
103 void *client_data, int id,
104 void (*select_cb)(void *, int, void *, int, void *, void *),
105 void (*activate_cb)(void *, int, void *, int, void *, void *)
106 );
107 int SARMenuListAppendItem(
108 sar_menu_struct *m, int n,
109 const char *name,
110 void *client_data,
111 sar_menu_flags_t flags
112 );
113 sar_menu_list_item_struct *SARMenuListGetItemByNumber(
114 sar_menu_list_struct *list, int i
115 );
116 void SARMenuListSelect(
117 gw_display_struct *display, sar_menu_struct *m, int n,
118 int i,
119 Boolean scroll, Boolean redraw
120 );
121 void SARMenuListDeleteAllItems(sar_menu_struct *m, int n);
122
123 /* Multi-purpose Display */
124 int SARMenuMDisplayNew(
125 sar_menu_struct *m,
126 float x, float y,
127 float width, float height,
128 const sar_image_struct **bg_image, /* Pointer to 9 images */
129 void *client_data, int id,
130 void (*draw_cb)(
131 void *, /* Display */
132 void *, /* Menu */
133 void *, /* This Object */
134 int, /* ID Code */
135 void *, /* Data */
136 int, int, int, int /* x_min, y_min, x_max, y_max */
137 )
138 );
139 void SARMenuMDisplayDraw(
140 gw_display_struct *display, sar_menu_struct *m, int n
141 );
142
143 /* Switch */
144 int SARMenuSwitchNew(
145 sar_menu_struct *m,
146 float x, float y,
147 int width, int height,
148 sar_menu_color_struct *fg_color, GWFont *font,
149 const char *label,
150 const sar_image_struct *bg_image,
151 const sar_image_struct *switch_off_image,
152 const sar_image_struct *switch_on_image,
153 Boolean state,
154 void *client_data, int id,
155 void (*switch_cb)(void *, int, void *, Boolean)
156 );
157 Boolean SARMenuSwitchGetValue(sar_menu_struct *m, int n);
158 void SARMenuSwitchSetValue(
159 gw_display_struct *display, sar_menu_struct *m, int n,
160 Boolean state, Boolean redraw
161 );
162
163 /* Spin */
164 int SARMenuSpinNew(
165 sar_menu_struct *m,
166 float x, float y,
167 float width, float height,
168 sar_menu_color_struct *label_color,
169 sar_menu_color_struct *value_color,
170 GWFont *font,
171 GWFont *value_font,
172 const char *label,
173 const sar_image_struct *label_image,
174 const sar_image_struct *value_image,
175 const sar_image_struct *dec_armed_image,
176 const sar_image_struct *dec_unarmed_image,
177 const sar_image_struct *inc_armed_image,
178 const sar_image_struct *inc_unarmed_image,
179 void *client_data, int id,
180 void (*change_cb)(void *, int, void *, char *)
181 );
182 void SARMenuSpinSetValueType(
183 sar_menu_struct *m, int n, int type
184 );
185 int SARMenuSpinAddValue(
186 sar_menu_struct *m, int n, const char *value
187 );
188 char *SARMenuSpinGetCurrentValue(
189 sar_menu_struct *m, int n, int *sel_num
190 );
191 void SARMenuSpinSelectValueIndex(
192 gw_display_struct *display, sar_menu_struct *m, int n,
193 int value_num,
194 Boolean redraw
195 );
196 void SARMenuSpinSetValueIndex(
197 gw_display_struct *display, sar_menu_struct *m, int n,
198 int value_num, const char *value,
199 Boolean redraw
200 );
201 void SARMenuSpinDeleteAllValues(sar_menu_struct *m, int n);
202 void SARMenuSpinDoInc(
203 gw_display_struct *display, sar_menu_struct *m, int n,
204 Boolean redraw
205 );
206 void SARMenuSpinDoDec(
207 gw_display_struct *display, sar_menu_struct *m, int n,
208 Boolean redraw
209 );
210
211 /* Slider */
212 int SARMenuSliderNew(
213 sar_menu_struct *m,
214 float x, float y,
215 float width, float height,
216 sar_menu_color_struct *label_color,
217 GWFont *font,
218 const char *label,
219 const sar_image_struct *label_image,
220 const sar_image_struct *trough_image,
221 const sar_image_struct *handle_image,
222 void *client_data, int id,
223 void (*change_cb)(void *, int, void *, float)
224 );
225 void SARMenuSliderSetValueBounds(
226 gw_display_struct *display, sar_menu_struct *m, int n,
227 float lower, float upper,
228 Boolean redraw
229 );
230 void SARMenuSliderSetValue(
231 gw_display_struct *display, sar_menu_struct *m, int n,
232 float value,
233 Boolean redraw
234 );
235 float SARMenuSliderGetValue(sar_menu_struct *m, int n);
236
237 /* Object Common */
238 void SARMenuObjectSetSensitive(
239 gw_display_struct *display, sar_menu_struct *m, int n,
240 Boolean sensitive, Boolean redraw
241 );
242 void SARMenuObjectDelete(sar_menu_struct *m, int n);
243
244 /* Drawing */
245 static const char *SARMenuMessageBoxDrawString(
246 gw_display_struct *display,
247 int x, int y,
248 const char *buf_ptr,
249 int visible_columns, int font_width,
250 Boolean sensitive,
251 Boolean draw_line,
252 const sar_menu_color_struct *c_def,
253 const sar_menu_color_struct *c_bold,
254 const sar_menu_color_struct *c_ul
255 );
256 static int SARMenuMessageBoxTotalLines(
257 const char *buf_ptr, int visible_columns
258 );
259 void SARMenuDrawWindowBG(
260 gw_display_struct *display,
261 const sar_image_struct **bg_image, /* Total 9 images */
262 const sar_menu_color_struct *base_color, /* Set NULL to use image as base */
263 int x, int y,
264 int width, int height,
265 Boolean draw_base,
266 Boolean draw_shadow,
267 Boolean is_selected
268 );
269 static void SARMenuDoDrawObject(
270 gw_display_struct *display, sar_menu_struct *m,
271 int n, /* Object number on m */
272 Boolean draw_shadows
273 );
274 void SARMenuDrawObject(
275 gw_display_struct *display, sar_menu_struct *m,
276 int n /* Object number on m */
277 );
278 void SARMenuDrawAll(
279 gw_display_struct *display, sar_menu_struct *m
280 );
281
282 /* Manage Pointer */
283 int SARMenuManagePointer(
284 gw_display_struct *display, sar_menu_struct *m,
285 int x, int y, gw_event_type type, int btn_num
286 );
287
288 /* Manage Key */
289 int SARMenuManageKey(
290 gw_display_struct *display,
291 sar_menu_struct *m,
292 int key, Boolean state
293 );
294
295
296 #define ATOI(s) (((s) != NULL) ? atoi(s) : 0)
297 #define ATOL(s) (((s) != NULL) ? atol(s) : 0)
298 #define ATOF(s) (((s) != NULL) ? atof(s) : 0.0f)
299 #define STRDUP(s) (((s) != NULL) ? strdup(s) : NULL)
300
301 #define MAX(a,b) (((a) > (b)) ? (a) : (b))
302 #define MIN(a,b) (((a) < (b)) ? (a) : (b))
303 #define CLIP(a,l,h) (MIN(MAX((a),(l)),(h)))
304 #define STRLEN(s) (((s) != NULL) ? ((int)strlen(s)) : 0)
305
306 #define ISCR(c) (((c) == '\n') || ((c) == '\r'))
307
308 #define IS_CHAR_ESC_START(c) ((c) == '<')
309 #define IS_CHAR_ESC_END(c) ((c) == '>')
310
311
312 /* Default spacings (in pixels) */
313 #define DEF_XMARGIN 5
314 #define DEF_YMARGIN 5
315
316 /* List object */
317 #define DEF_LIST_XMARGIN 25
318 #define DEF_LIST_YMARGIN 20
319
320 /* Message box object */
321 #define DEF_MB_XMARGIN 25
322 #define DEF_MB_YMARGIN 20
323
324 #define DEF_WIDTH 100
325 #define DEF_HEIGHT 100
326
327 #define DEF_PROGRESS_HEIGHT 25
328
329 #define DEF_SCROLL_CURSOR_WIDTH 16
330 #define DEF_SCROLL_CURSOR_HEIGHT 16
331
332 #define DEF_SWITCH_WIDTH 48
333 #define DEF_SWITCH_HEIGHT 48
334
335
336 #define DO_REDRAW_MENU(d,m) { \
337 SARMenuDrawAll((d), (m)); \
338 GWSwapBuffer(d); \
339 }
340
341 #define DO_REDRAW_OBJECT(d,m,n) { \
342 if((m)->always_full_redraw) \
343 SARMenuDrawAll((d), (m)); \
344 else \
345 SARMenuDrawObject((d),(m),(n)); \
346 GWSwapBuffer(d); \
347 }
348
349
350 /*
351 * Resets gl states for 2d menu system drawing, this function
352 * should be called at startup and whenever the menu system is
353 * re-entered or needs the gl state to be reset to expected values.
354 */
SARMenuGLStateReset(gw_display_struct * display)355 void SARMenuGLStateReset(gw_display_struct *display)
356 {
357 state_gl_struct *s;
358
359 if(display == NULL)
360 return;
361
362 s = &display->state_gl;
363
364 /* Set up GL states for 2d drawing */
365 GWOrtho2D(display);
366
367 StateGLDisableF(s, GL_DEPTH_TEST, True);
368 StateGLDepthMask(s, GL_TRUE);
369 StateGLDepthFunc(s, GL_ALWAYS);
370
371 StateGLDisableF(s, GL_ALPHA_TEST, True);
372 StateGLAlphaFunc(s, GL_GREATER, 0.5f);
373
374 StateGLDisableF(s, GL_CULL_FACE, True);
375 StateGLShadeModel(s, GL_FLAT);
376
377 StateGLDisableF(s, GL_BLEND, True);
378 StateGLDisableF(s, GL_FOG, True);
379 StateGLDisableF(s, GL_TEXTURE_1D, True);
380 StateGLDisableF(s, GL_TEXTURE_2D, True);
381 StateGLDisableF(s, GL_COLOR_MATERIAL, True);
382 StateGLDisableF(s, GL_LIGHTING, True);
383 StateGLDisableF(s, GL_LIGHT0, True);
384 StateGLDisableF(s, GL_LIGHT1, True);
385 StateGLDisableF(s, GL_LIGHT2, True);
386 StateGLDisableF(s, GL_LIGHT3, True);
387 StateGLDisableF(s, GL_LIGHT4, True);
388 StateGLDisableF(s, GL_LIGHT5, True);
389 StateGLDisableF(s, GL_LIGHT6, True);
390 StateGLDisableF(s, GL_LIGHT7, True);
391 StateGLDisableF(s, GL_POINT_SMOOTH, True);
392 StateGLDisableF(s, GL_LINE_SMOOTH, True);
393 StateGLDisableF(s, GL_POLYGON_OFFSET_FILL, True);
394 StateGLDisableF(s, GL_POLYGON_OFFSET_LINE, True);
395 StateGLDisableF(s, GL_POLYGON_OFFSET_POINT, True);
396 StateGLDisableF(s, GL_SCISSOR_TEST, True);
397
398 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
399 glPixelStorei(GL_PACK_ALIGNMENT, 1);
400 }
401
402
403 /*
404 * Returns the pointer to the object n on menu m.
405 *
406 * Returns NULL on error.
407 */
SARMenuGetObject(sar_menu_struct * m,int n)408 void *SARMenuGetObject(sar_menu_struct *m, int n)
409 {
410 if(m == NULL)
411 return(NULL);
412 else if((n < 0) || (n >= m->total_objects))
413 return(NULL);
414 else
415 return(m->object[n]);
416 }
417
418 /*
419 * Returns the object who's id matches the specified id.
420 */
SARMenuGetObjectByID(sar_menu_struct * m,int id,int * n)421 void *SARMenuGetObjectByID(sar_menu_struct *m, int id, int *n)
422 {
423 int i;
424 void *o;
425
426 if(n != NULL)
427 *n = -1;
428
429 if(m == NULL)
430 return(NULL);
431
432 for(i = 0; i < m->total_objects; i++)
433 {
434 o = m->object[i];
435 if(o == NULL)
436 continue;
437
438 switch(SAR_MENU_OBJECT_TYPE(o))
439 {
440 case SAR_MENU_OBJECT_TYPE_BUTTON:
441 if(SAR_MENU_BUTTON(o)->id == id)
442 {
443 if(n != NULL)
444 *n = i;
445 return(o);
446 }
447 break;
448
449 case SAR_MENU_OBJECT_TYPE_LIST:
450 if(SAR_MENU_LIST(o)->id == id)
451 {
452 if(n != NULL)
453 *n = i;
454 return(o);
455 }
456 break;
457
458 case SAR_MENU_OBJECT_TYPE_MESSAGE_BOX:
459 if(SAR_MENU_MESSAGE_BOX(o)->id == id)
460 {
461 if(n != NULL)
462 *n = i;
463 return(o);
464 }
465 break;
466
467 case SAR_MENU_OBJECT_TYPE_MDISPLAY:
468 if(SAR_MENU_MDISPLAY(o)->id == id)
469 {
470 if(n != NULL)
471 *n = i;
472 return(o);
473 }
474 break;
475
476 case SAR_MENU_OBJECT_TYPE_SWITCH:
477 if(SAR_MENU_SWITCH(o)->id == id)
478 {
479 if(n != NULL)
480 *n = i;
481 return(o);
482 }
483 break;
484
485 case SAR_MENU_OBJECT_TYPE_SPIN:
486 if(SAR_MENU_SPIN(o)->id == id)
487 {
488 if(n != NULL)
489 *n = i;
490 return(o);
491 }
492 break;
493
494 case SAR_MENU_OBJECT_TYPE_SLIDER:
495 if(SAR_MENU_SLIDER(o)->id == id)
496 {
497 if(n != NULL)
498 *n = i;
499 return(o);
500 }
501 break;
502
503 case SAR_MENU_OBJECT_TYPE_MAP:
504 if(SAR_MENU_MAP(o)->id == id)
505 {
506 if(n != NULL)
507 *n = i;
508 return(o);
509 }
510 break;
511
512 case SAR_MENU_OBJECT_TYPE_OBJVIEW:
513 if(SAR_MENU_OBJVIEW(o)->id == id)
514 {
515 if(n != NULL)
516 *n = i;
517 return(o);
518 }
519 break;
520 }
521 }
522
523 return(NULL);
524 }
525
526 /*
527 * Returns True if the object n on menu m is sensitive.
528 */
SARMenuObjectIsSensitive(sar_menu_struct * m,int n)529 Boolean SARMenuObjectIsSensitive(sar_menu_struct *m, int n)
530 {
531 void *o = SARMenuGetObject(m, n);
532 if(o == NULL)
533 return(False);
534
535 switch(SAR_MENU_OBJECT_TYPE(o))
536 {
537 case SAR_MENU_OBJECT_TYPE_LABEL:
538 return(SAR_MENU_LABEL(o)->sensitive);
539 case SAR_MENU_OBJECT_TYPE_BUTTON:
540 return(SAR_MENU_BUTTON(o)->sensitive);
541 case SAR_MENU_OBJECT_TYPE_PROGRESS:
542 return(SAR_MENU_PROGRESS(o)->sensitive);
543 case SAR_MENU_OBJECT_TYPE_MESSAGE_BOX:
544 return(SAR_MENU_MESSAGE_BOX(o)->sensitive);
545 case SAR_MENU_OBJECT_TYPE_LIST:
546 return(SAR_MENU_LIST(o)->sensitive);
547 case SAR_MENU_OBJECT_TYPE_MDISPLAY:
548 return(SAR_MENU_MDISPLAY(o)->sensitive);
549 case SAR_MENU_OBJECT_TYPE_SWITCH:
550 return(SAR_MENU_SWITCH(o)->sensitive);
551 case SAR_MENU_OBJECT_TYPE_SPIN:
552 return(SAR_MENU_SPIN(o)->sensitive);
553 case SAR_MENU_OBJECT_TYPE_SLIDER:
554 return(SAR_MENU_SLIDER(o)->sensitive);
555 case SAR_MENU_OBJECT_TYPE_MAP:
556 return(SAR_MENU_MAP(o)->sensitive);
557 case SAR_MENU_OBJECT_TYPE_OBJVIEW:
558 return(SAR_MENU_OBJVIEW(o)->sensitive);
559 default:
560 return(False);
561 }
562 }
563
564
565 /*
566 * Creates a new menu.
567 */
SARMenuNew(sar_menu_type type,const char * name,const char * bg_image)568 sar_menu_struct *SARMenuNew(
569 sar_menu_type type, const char *name, const char *bg_image
570 )
571 {
572 sar_menu_struct *m = SAR_MENU(calloc(
573 1, sizeof(sar_menu_struct)
574 ));
575 if(m == NULL)
576 return(NULL);
577
578 m->type = type;
579 m->name = STRDUP(name);
580 m->always_full_redraw = False;
581 m->bg_image_path = STRDUP(bg_image);
582 m->bg_image = NULL;
583
584 m->object = NULL;
585 m->total_objects = 0;
586 m->selected_object = -1;
587
588 return(m);
589 }
590
591 /*
592 * Loads background image as needed on menu m.
593 */
SARMenuLoadBackgroundImage(sar_menu_struct * m)594 void SARMenuLoadBackgroundImage(sar_menu_struct *m)
595 {
596 const char *path;
597
598 if(m == NULL)
599 return;
600
601 /* Get background image file path */
602 path = m->bg_image_path;
603 if(path == NULL)
604 return;
605
606 /* Load new background image only if the menu does not already
607 * have one
608 */
609 if(m->bg_image == NULL)
610 m->bg_image = SARImageNewFromFile(path);
611 }
612
613 /*
614 * Unloads background image as needed on menu m.
615 */
SARMenuUnloadBackgroundImage(sar_menu_struct * m)616 void SARMenuUnloadBackgroundImage(sar_menu_struct *m)
617 {
618 if(m == NULL)
619 return;
620
621 SARImageDelete(m->bg_image);
622 m->bg_image = NULL;
623 }
624
625 /*
626 * Deletes the Menu.
627 */
SARMenuDelete(sar_menu_struct * m)628 void SARMenuDelete(sar_menu_struct *m)
629 {
630 int i;
631
632 if(m == NULL)
633 return;
634
635 /* Delete all objects on this menu */
636 for(i = 0; i < m->total_objects; i++)
637 SARMenuObjectDelete(m, i);
638 free(m->object);
639 m->object = NULL;
640 m->total_objects = 0;
641
642 free(m->name);
643 m->name = NULL;
644
645 free(m->bg_image_path);
646 m->bg_image_path = NULL;
647
648 SARImageDelete(m->bg_image);
649 m->bg_image = NULL;
650
651 free(m);
652 }
653
654 /*
655 * Allocates a new label on menu m.
656 *
657 * Returns its index number or -1 on error.
658 */
SARMenuLabelNew(sar_menu_struct * m,float x,float y,int width,int height,const char * label,sar_menu_color_struct * fg_color,GWFont * font,const sar_image_struct * image)659 int SARMenuLabelNew(
660 sar_menu_struct *m,
661 float x, float y,
662 int width, int height,
663 const char *label,
664 sar_menu_color_struct *fg_color,
665 GWFont *font,
666 const sar_image_struct *image
667 )
668 {
669 int i, n;
670 sar_menu_label_struct *label_ptr;
671
672
673 if(m == NULL)
674 return(-1);
675
676 if(m->total_objects < 0)
677 m->total_objects = 0;
678
679 for(i = 0; i < m->total_objects; i++)
680 {
681 if(m->object[i] == NULL)
682 break;
683 }
684 if(i < m->total_objects)
685 {
686 n = i;
687 }
688 else
689 {
690 n = m->total_objects;
691 m->total_objects = n + 1;
692 m->object = (void **)realloc(
693 m->object,
694 m->total_objects * sizeof(void *)
695 );
696 if(m->object == NULL)
697 {
698 m->total_objects = 0;
699 return(-3);
700 }
701 }
702
703 /* Allocate structure */
704 m->object[n] = label_ptr = SAR_MENU_LABEL(calloc(
705 1, sizeof(sar_menu_label_struct)
706 ));
707 if(label_ptr == NULL)
708 return(-3);
709
710 /* Load label values */
711 label_ptr->type = SAR_MENU_OBJECT_TYPE_LABEL;
712 label_ptr->x = x;
713 label_ptr->y = y;
714 label_ptr->width = width;
715 label_ptr->height = height;
716 label_ptr->sensitive = True;
717 label_ptr->image = image;
718 memcpy(&label_ptr->color, fg_color, sizeof(sar_menu_color_struct));
719 label_ptr->font = font;
720 label_ptr->label = STRDUP(label);
721 label_ptr->align = SAR_MENU_LABEL_ALIGN_CENTER;
722
723 /* Select this object if it is the first one */
724 if(m->total_objects == 1)
725 m->selected_object = 0;
726
727 return(n);
728 }
729
730 /*
731 * Allocates a new button on menu m.
732 *
733 * Returns its index number or -1 on error.
734 */
SARMenuButtonNew(sar_menu_struct * m,float x,float y,int width,int height,const char * label,sar_menu_color_struct * fg_color,GWFont * font,const sar_image_struct * unarmed_image,const sar_image_struct * armed_image,const sar_image_struct * highlighted_image,void * client_data,int id,void (* func_cb)(void *,int,void *))735 int SARMenuButtonNew(
736 sar_menu_struct *m,
737 float x, float y,
738 int width, int height,
739 const char *label,
740 sar_menu_color_struct *fg_color, GWFont *font,
741 const sar_image_struct *unarmed_image,
742 const sar_image_struct *armed_image,
743 const sar_image_struct *highlighted_image,
744 void *client_data, int id,
745 void (*func_cb)(void *, int, void *)
746 )
747 {
748 int i, n;
749 sar_menu_button_struct *button;
750
751
752 if(m == NULL)
753 return(-1);
754
755 if(m->total_objects < 0)
756 m->total_objects = 0;
757
758 for(i = 0; i < m->total_objects; i++)
759 {
760 if(m->object[i] == NULL)
761 break;
762 }
763 if(i < m->total_objects)
764 {
765 n = i;
766 }
767 else
768 {
769 n = m->total_objects;
770 m->total_objects = n + 1;
771 m->object = (void **)realloc(
772 m->object,
773 m->total_objects * sizeof(void *)
774 );
775 if(m->object == NULL)
776 {
777 m->total_objects = 0;
778 return(-3);
779 }
780 }
781
782 /* Allocate structure */
783 m->object[n] = button = SAR_MENU_BUTTON(calloc(
784 1, sizeof(sar_menu_button_struct)
785 ));
786 if(button == NULL)
787 return(-3);
788
789 /* Load button values */
790 button->type = SAR_MENU_OBJECT_TYPE_BUTTON;
791 button->x = x;
792 button->y = y;
793 button->width = width;
794 button->height = height;
795 button->sensitive = True;
796 button->unarmed_image = unarmed_image;
797 button->armed_image = armed_image;
798 button->highlighted_image = highlighted_image;
799 memcpy(&button->color, fg_color, sizeof(sar_menu_color_struct));
800 button->font = font;
801 button->label = STRDUP(label);
802 button->client_data = client_data;
803 button->id = id;
804 button->func_cb = func_cb;
805
806 /* Select this object if it is the first one */
807 if(m->total_objects == 1)
808 m->selected_object = 0;
809
810 return(n);
811 }
812
813 /*
814 * Allocates a new progress bar on menu m.
815 *
816 * Returns its index number or -1 on error.
817 */
SARMenuProgressNew(sar_menu_struct * m,float x,float y,int width,int height,const char * label,sar_menu_color_struct * fg_color,GWFont * font,const sar_image_struct * bg_image,const sar_image_struct * fg_image,float progress)818 int SARMenuProgressNew(
819 sar_menu_struct *m,
820 float x, float y,
821 int width, int height,
822 const char *label,
823 sar_menu_color_struct *fg_color, GWFont *font,
824 const sar_image_struct *bg_image,
825 const sar_image_struct *fg_image,
826 float progress
827 )
828 {
829 int i, n;
830 sar_menu_progress_struct *pb;
831
832
833 if(m == NULL)
834 return(-1);
835
836 if(m->total_objects < 0)
837 m->total_objects = 0;
838
839 for(i = 0; i < m->total_objects; i++)
840 {
841 if(m->object[i] == NULL)
842 break;
843 }
844 if(i < m->total_objects)
845 {
846 n = i;
847 }
848 else
849 {
850 n = m->total_objects;
851 m->total_objects = n + 1;
852 m->object = (void **)realloc(
853 m->object,
854 m->total_objects * sizeof(void *)
855 );
856 if(m->object == NULL)
857 {
858 m->total_objects = 0;
859 return(-3);
860 }
861 }
862
863 /* Allocate structure */
864 m->object[n] = pb = SAR_MENU_PROGRESS(calloc(
865 1, sizeof(sar_menu_progress_struct)
866 ));
867 if(pb == NULL)
868 return(-3);
869
870 /* Load progress bar values */
871 pb->type = SAR_MENU_OBJECT_TYPE_PROGRESS;
872 pb->x = x;
873 pb->y = y;
874 pb->width = width;
875 pb->height = height;
876 pb->sensitive = True;
877 pb->bg_image = bg_image;
878 pb->fg_image = fg_image;
879 memcpy(&pb->color, fg_color, sizeof(sar_menu_color_struct));
880 pb->font = font;
881 pb->label = STRDUP(label);
882 pb->progress = progress;
883
884 /* Select this object if it is the first one */
885 if(m->total_objects == 1)
886 m->selected_object = 0;
887
888 return(n);
889 }
890
891 /*
892 * Sets the new value for the progress bar.
893 */
SARMenuProgressSet(gw_display_struct * display,sar_menu_struct * m,int n,float progress,Boolean redraw)894 void SARMenuProgressSet(
895 gw_display_struct *display, sar_menu_struct *m, int n,
896 float progress, Boolean redraw
897 )
898 {
899 Boolean changed = False;
900 sar_menu_progress_struct *pb = SAR_MENU_PROGRESS(
901 SARMenuGetObject(m, n)
902 );
903 if(!SAR_MENU_IS_PROGRESS(pb))
904 return;
905
906 if(pb->progress != progress)
907 {
908 pb->progress = CLIP(progress, 0.0f, 1.0f);
909 changed = True;
910 }
911
912 if(changed && redraw)
913 DO_REDRAW_OBJECT(display, m, n)
914 }
915
916
917 /*
918 * Create message box on menu m.
919 */
SARMenuMessageBoxNew(sar_menu_struct * m,float x,float y,float width,float height,sar_menu_color_struct * fg_color,GWFont * font,const sar_image_struct ** bg_image,void * client_data,int id,const char * message)920 int SARMenuMessageBoxNew(
921 sar_menu_struct *m,
922 float x, float y,
923 float width, float height,
924 sar_menu_color_struct *fg_color,
925 GWFont *font,
926 const sar_image_struct **bg_image, /* Pointer to 9 images */
927 void *client_data, int id,
928 const char *message
929 )
930 {
931 int i, n;
932 sar_menu_color_struct *c;
933 sar_menu_message_box_struct *mesgbox;
934
935
936 if(m == NULL)
937 return(-1);
938
939 if(m->total_objects < 0)
940 m->total_objects = 0;
941
942 for(i = 0; i < m->total_objects; i++)
943 {
944 if(m->object[i] == NULL)
945 break;
946 }
947 if(i < m->total_objects)
948 {
949 n = i;
950 }
951 else
952 {
953 n = m->total_objects;
954 m->total_objects = n + 1;
955 m->object = (void **)realloc(
956 m->object,
957 m->total_objects * sizeof(void *)
958 );
959 if(m->object == NULL)
960 {
961 m->total_objects = 0;
962 return(-3);
963 }
964 }
965
966 /* Allocate structure */
967 m->object[n] = mesgbox = SAR_MENU_MESSAGE_BOX(calloc(
968 1, sizeof(sar_menu_message_box_struct)
969 ));
970 if(mesgbox == NULL)
971 return(-3);
972
973 /* Load message box values */
974 mesgbox->type = SAR_MENU_OBJECT_TYPE_MESSAGE_BOX;
975 mesgbox->id = id;
976 mesgbox->client_data = client_data;
977 mesgbox->x = x;
978 mesgbox->y = y;
979 mesgbox->width = width;
980 mesgbox->height = height;
981 mesgbox->sensitive = True;
982 mesgbox->bg_image = bg_image;
983 memcpy(&mesgbox->color, fg_color, sizeof(sar_menu_color_struct));
984 c = &mesgbox->bold_color;
985 c->a = 1.0f;
986 c->r = 1.0f;
987 c->g = 1.0f;
988 c->b = 0.0f;
989 c = &mesgbox->underline_color;
990 c->a = 1.0f;
991 c->r = 0.5f;
992 c->g = 0.5f;
993 c->b = 1.0f;
994 mesgbox->font = font;
995 mesgbox->message = STRDUP(message);
996 mesgbox->scrolled_line = 0;
997
998 /* Select this object if it is the first one */
999 if(m->total_objects == 1)
1000 m->selected_object = 0;
1001
1002 return(n);
1003 }
1004
1005 /*
1006 * Set the message for the message box.
1007 */
SARMenuMessageBoxSet(gw_display_struct * display,sar_menu_struct * m,int n,const char * message,Boolean redraw)1008 void SARMenuMessageBoxSet(
1009 gw_display_struct *display, sar_menu_struct *m, int n,
1010 const char *message, Boolean redraw
1011 )
1012 {
1013 sar_menu_message_box_struct *mesgbox = SAR_MENU_MESSAGE_BOX(
1014 SARMenuGetObject(m, n)
1015 );
1016 if(!SAR_MENU_IS_MESSAGE_BOX(mesgbox))
1017 return;
1018
1019 free(mesgbox->message);
1020 mesgbox->message = STRDUP(message);
1021
1022 mesgbox->scrolled_line = 0;
1023
1024 if(redraw)
1025 DO_REDRAW_OBJECT(display, m, n)
1026 }
1027
1028
1029 /*
1030 * Create list on menu m.
1031 *
1032 * Returns its index number or -1 on error.
1033 */
SARMenuListNew(sar_menu_struct * m,float x,float y,float width,float height,sar_menu_color_struct * fg_color,GWFont * font,const char * label,const sar_image_struct ** bg_image,void * client_data,int id,void (* select_cb)(void *,int,void *,int,void *,void *),void (* activate_cb)(void *,int,void *,int,void *,void *))1034 int SARMenuListNew(
1035 sar_menu_struct *m,
1036 float x, float y,
1037 float width, float height,
1038 sar_menu_color_struct *fg_color, GWFont *font,
1039 const char *label,
1040 const sar_image_struct **bg_image, /* Pointer to 9 images */
1041 void *client_data, int id,
1042 void (*select_cb)(void *, int, void *, int, void *, void *),
1043 void (*activate_cb)(void *, int, void *, int, void *, void *)
1044 )
1045 {
1046 int i, n;
1047 sar_menu_list_struct *list;
1048
1049
1050 if(m == NULL)
1051 return(-1);
1052
1053 if(m->total_objects < 0)
1054 m->total_objects = 0;
1055
1056 for(i = 0; i < m->total_objects; i++)
1057 {
1058 if(m->object[i] == NULL)
1059 break;
1060 }
1061 if(i < m->total_objects)
1062 {
1063 n = i;
1064 }
1065 else
1066 {
1067 n = m->total_objects;
1068 m->total_objects = n + 1;
1069 m->object = (void **)realloc(
1070 m->object,
1071 m->total_objects * sizeof(void *)
1072 );
1073 if(m->object == NULL)
1074 {
1075 m->total_objects = 0;
1076 return(-3);
1077 }
1078 }
1079
1080 /* Allocate structure */
1081 m->object[n] = list = SAR_MENU_LIST(calloc(
1082 1, sizeof(sar_menu_list_struct)
1083 ));
1084 if(list == NULL)
1085 return(-3);
1086
1087 /* Set values */
1088 list->type = SAR_MENU_OBJECT_TYPE_LIST;
1089 list->id = id;
1090 list->client_data = client_data;
1091 list->x = x;
1092 list->y = y;
1093 list->width = width;
1094 list->height = height;
1095 list->sensitive = True;
1096 list->bg_image = bg_image;
1097 memcpy(&list->color, fg_color, sizeof(sar_menu_color_struct));
1098 list->font = font;
1099 list->label = STRDUP(label);
1100 list->item = NULL;
1101 list->total_items = 0;
1102 list->items_visable = 0; /* Calculated when drawn or managed */
1103 list->scrolled_item = 0;
1104 list->selected_item = -1;
1105 list->select_cb = select_cb;
1106 list->activate_cb = activate_cb;
1107
1108 /* Select this object if it is the first one */
1109 if(m->total_objects == 1)
1110 m->selected_object = 0;
1111
1112 return(n);
1113 }
1114
1115 /*
1116 * Appends item to the list object n on menu m.
1117 *
1118 * Returns the item number or -1 on error.
1119 */
SARMenuListAppendItem(sar_menu_struct * m,int n,const char * name,void * client_data,sar_menu_flags_t flags)1120 int SARMenuListAppendItem(
1121 sar_menu_struct *m, int n,
1122 const char *name,
1123 void *client_data,
1124 sar_menu_flags_t flags
1125 )
1126 {
1127 int item_num;
1128 sar_menu_list_item_struct *item;
1129 sar_menu_list_struct *list = SAR_MENU_LIST(SARMenuGetObject(m, n));
1130 if(!SAR_MENU_IS_LIST(list))
1131 return(-2);
1132
1133 item_num = MAX(list->total_items, 0);
1134 list->total_items = item_num + 1;
1135 list->item = (sar_menu_list_item_struct **)realloc(
1136 list->item,
1137 list->total_items * sizeof(sar_menu_list_item_struct *)
1138 );
1139 if(list->item == NULL)
1140 {
1141 list->total_items = 0;
1142 return(-3);
1143 }
1144
1145 list->item[item_num] = item = SAR_MENU_LIST_ITEM(calloc(
1146 1, sizeof(sar_menu_list_item_struct)
1147 ));
1148 if(item == NULL)
1149 return(-3);
1150
1151 /* Set item values */
1152 item->flags = flags;
1153 item->name = STRDUP(name);
1154 item->client_data = client_data;
1155
1156 return(item_num);
1157 }
1158
1159 /*
1160 * Returns the pointer to the item number i or -1 on error.
1161 */
SARMenuListGetItemByNumber(sar_menu_list_struct * list,int i)1162 sar_menu_list_item_struct *SARMenuListGetItemByNumber(
1163 sar_menu_list_struct *list, int i
1164 )
1165 {
1166 if(list == NULL)
1167 return(NULL);
1168 else if((i < 0) || (i >= list->total_items))
1169 return(NULL);
1170 else
1171 return(list->item[i]);
1172 }
1173
1174 /*
1175 * Selects the list item specified by i.
1176 */
SARMenuListSelect(gw_display_struct * display,sar_menu_struct * m,int n,int i,Boolean scroll,Boolean redraw)1177 void SARMenuListSelect(
1178 gw_display_struct *display, sar_menu_struct *m, int n,
1179 int i,
1180 Boolean scroll, Boolean redraw
1181 )
1182 {
1183 Boolean selection_changed = False;
1184 sar_menu_list_item_struct *item;
1185 sar_menu_list_struct *list = SAR_MENU_LIST(SARMenuGetObject(m, n));
1186 if(!SAR_MENU_IS_LIST(list))
1187 return;
1188
1189 if((i < 0) || (i >= list->total_items))
1190 return;
1191
1192 /* Change in selected item? */
1193 if(i != list->selected_item)
1194 {
1195 list->selected_item = i;
1196 selection_changed = True;
1197 }
1198
1199 /* Scroll to selected item? */
1200 if(scroll)
1201 {
1202 list->scrolled_item = i;
1203 if((i + list->items_visable) > list->total_items)
1204 list->scrolled_item = MAX(
1205 list->total_items - list->items_visable,
1206 0
1207 );
1208 selection_changed = True;
1209 }
1210
1211 /* Redraw as needed and requested */
1212 if(selection_changed && redraw)
1213 DO_REDRAW_OBJECT(display, m, n)
1214
1215 /* Call select callback */
1216 item = SARMenuListGetItemByNumber(list, i);
1217 if((item != NULL) && selection_changed &&
1218 (list->select_cb != NULL)
1219 )
1220 list->select_cb(
1221 list, /* This Object */
1222 list->id, /* ID Code */
1223 list->client_data, /* Data */
1224 list->selected_item, /* Selected Item */
1225 item, /* Item */
1226 item->client_data /* Item Data */
1227 );
1228 }
1229
1230 /*
1231 * Deletes all items allocated on list object n on menu m.
1232 *
1233 * Client data on each item should have been taken care of
1234 * by the calling function.
1235 */
SARMenuListDeleteAllItems(sar_menu_struct * m,int n)1236 void SARMenuListDeleteAllItems(sar_menu_struct *m, int n)
1237 {
1238 int i;
1239 sar_menu_list_item_struct *item;
1240 sar_menu_list_struct *list = SAR_MENU_LIST(SARMenuGetObject(m, n));
1241 if(!SAR_MENU_IS_LIST(list))
1242 return;
1243
1244 /* Iterate through each item on the list object */
1245 for(i = 0; i < list->total_items; i++)
1246 {
1247 item = list->item[i];
1248 if(item == NULL)
1249 continue;
1250
1251 free(item->name);
1252 item->name = NULL;
1253
1254 /* Calling function needs to free client_data */
1255 if(item->client_data != NULL)
1256 fprintf(
1257 stderr,
1258 "SARMenuListDeleteAllItems(): Client data on item %i on list object %i of menu \"%s\" is not NULL.\n",
1259 i, n, m->name
1260 );
1261
1262 free(item);
1263 list->item[i] = item = NULL;
1264 }
1265 free(list->item);
1266 list->item = NULL;
1267 list->total_items = 0;
1268 list->scrolled_item = 0;
1269 list->selected_item = -1;
1270 }
1271
1272
1273 /*
1274 * Create multi-purpose display object on menu m.
1275 *
1276 * Returns its index number or -1 on error.
1277 */
SARMenuMDisplayNew(sar_menu_struct * m,float x,float y,float width,float height,const sar_image_struct ** bg_image,void * client_data,int id,void (* draw_cb)(void *,void *,void *,int,void *,int,int,int,int))1278 int SARMenuMDisplayNew(
1279 sar_menu_struct *m,
1280 float x, float y,
1281 float width, float height,
1282 const sar_image_struct **bg_image, /* Pointer to 9 images */
1283 void *client_data, int id,
1284 void (*draw_cb)(
1285 void *, /* Display */
1286 void *, /* Menu */
1287 void *, /* This Object */
1288 int, /* ID Code */
1289 void *, /* Data */
1290 int, int, int, int /* x_min, y_min, x_max, y_max */
1291 )
1292 )
1293 {
1294 int i, n;
1295 sar_menu_mdisplay_struct *mdpy;
1296
1297
1298 if(m == NULL)
1299 return(-1);
1300
1301 if(m->total_objects < 0)
1302 m->total_objects = 0;
1303
1304 for(i = 0; i < m->total_objects; i++)
1305 {
1306 if(m->object[i] == NULL)
1307 break;
1308 }
1309 if(i < m->total_objects)
1310 {
1311 n = i;
1312 }
1313 else
1314 {
1315 n = m->total_objects;
1316 m->total_objects = n + 1;
1317 m->object = (void **)realloc(
1318 m->object,
1319 m->total_objects * sizeof(void *)
1320 );
1321 if(m->object == NULL)
1322 {
1323 m->total_objects = 0;
1324 return(-3);
1325 }
1326 }
1327
1328 /* Allocate structure */
1329 m->object[n] = mdpy = SAR_MENU_MDISPLAY(calloc(
1330 1, sizeof(sar_menu_mdisplay_struct)
1331 ));
1332 if(mdpy == NULL)
1333 return(-3);
1334
1335 /* Set mdisplay values */
1336 mdpy->type = SAR_MENU_OBJECT_TYPE_MDISPLAY;
1337 mdpy->x = x;
1338 mdpy->y = y;
1339 mdpy->width = width;
1340 mdpy->height = height;
1341 mdpy->sensitive = True;
1342 mdpy->bg_image = bg_image;
1343 mdpy->client_data = client_data;
1344 mdpy->id = id;
1345 mdpy->draw_cb = draw_cb;
1346
1347 /* Select this object if it is the first one */
1348 if(m->total_objects == 1)
1349 m->selected_object = 0;
1350
1351 return(n);
1352 }
1353
1354 /*
1355 * Redraws the multi-purpose display.
1356 */
SARMenuMDisplayDraw(gw_display_struct * display,sar_menu_struct * m,int n)1357 void SARMenuMDisplayDraw(
1358 gw_display_struct *display, sar_menu_struct *m, int n
1359 )
1360 {
1361
1362 }
1363
1364
1365 /*
1366 * Create switch object on menu m.
1367 *
1368 * Returns its index number or -1 on error.
1369 */
SARMenuSwitchNew(sar_menu_struct * m,float x,float y,int width,int height,sar_menu_color_struct * fg_color,GWFont * font,const char * label,const sar_image_struct * bg_image,const sar_image_struct * switch_off_image,const sar_image_struct * switch_on_image,Boolean state,void * client_data,int id,void (* switch_cb)(void *,int,void *,Boolean))1370 int SARMenuSwitchNew(
1371 sar_menu_struct *m,
1372 float x, float y,
1373 int width, int height,
1374 sar_menu_color_struct *fg_color, GWFont *font,
1375 const char *label,
1376 const sar_image_struct *bg_image,
1377 const sar_image_struct *switch_off_image,
1378 const sar_image_struct *switch_on_image,
1379 Boolean state,
1380 void *client_data, int id,
1381 void (*switch_cb)(void *, int, void *, Boolean)
1382 )
1383 {
1384 int i, n;
1385 sar_menu_switch_struct *sw;
1386
1387
1388 if(m == NULL)
1389 return(-1);
1390
1391 if(m->total_objects < 0)
1392 m->total_objects = 0;
1393
1394 for(i = 0; i < m->total_objects; i++)
1395 {
1396 if(m->object[i] == NULL)
1397 break;
1398 }
1399 if(i < m->total_objects)
1400 {
1401 n = i;
1402 }
1403 else
1404 {
1405 n = m->total_objects;
1406 m->total_objects = n + 1;
1407 m->object = (void **)realloc(
1408 m->object,
1409 m->total_objects * sizeof(void *)
1410 );
1411 if(m->object == NULL)
1412 {
1413 m->total_objects = 0;
1414 return(-3);
1415 }
1416 }
1417
1418 /* Allocate structure */
1419 m->object[n] = sw = SAR_MENU_SWITCH(calloc(
1420 1, sizeof(sar_menu_switch_struct)
1421 ));
1422 if(sw == NULL)
1423 return(-3);
1424
1425 /* Set switch values */
1426 sw->type = SAR_MENU_OBJECT_TYPE_SWITCH;
1427 sw->x = x;
1428 sw->y = y;
1429 sw->width = width;
1430 sw->height = height;
1431 sw->sensitive = True;
1432 sw->bg_image = bg_image;
1433 sw->switch_off_image = switch_off_image;
1434 sw->switch_on_image = switch_on_image;
1435 memcpy(&sw->color, fg_color, sizeof(sar_menu_color_struct));
1436 sw->font = font;
1437 sw->label = STRDUP(label);
1438 sw->state = state;
1439 sw->client_data = client_data;
1440 sw->id = id;
1441 sw->switch_cb = switch_cb;
1442
1443 /* Select this object if it is the first one */
1444 if(m->total_objects == 1)
1445 m->selected_object = 0;
1446
1447 return(n);
1448 }
1449
1450 /*
1451 * Get state of the switch object n on menu m.
1452 */
SARMenuSwitchGetValue(sar_menu_struct * m,int n)1453 Boolean SARMenuSwitchGetValue(sar_menu_struct *m, int n)
1454 {
1455 sar_menu_switch_struct *sw = SAR_MENU_SWITCH(
1456 SARMenuGetObject(m, n)
1457 );
1458 if(!SAR_MENU_IS_SWITCH(sw))
1459 return(False);
1460
1461 return(sw->state);
1462 }
1463
1464 /*
1465 * Set state of switch object n on menu m.
1466 */
SARMenuSwitchSetValue(gw_display_struct * display,sar_menu_struct * m,int n,Boolean state,Boolean redraw)1467 void SARMenuSwitchSetValue(
1468 gw_display_struct *display, sar_menu_struct *m, int n,
1469 Boolean state, Boolean redraw
1470 )
1471 {
1472 Boolean change = False;
1473 sar_menu_switch_struct *sw = SAR_MENU_SWITCH(
1474 SARMenuGetObject(m, n)
1475 );
1476 if(!SAR_MENU_IS_SWITCH(sw))
1477 return;
1478
1479 if(sw->state != state)
1480 {
1481 sw->state = state;
1482 change = True;
1483 }
1484
1485 if(change)
1486 {
1487 if(redraw)
1488 DO_REDRAW_OBJECT(display, m, n)
1489
1490 if(sw->switch_cb != NULL)
1491 sw->switch_cb(
1492 sw, /* This Object */
1493 sw->id, /* ID Code */
1494 sw->client_data, /* Data */
1495 sw->state /* Value */
1496 );
1497 }
1498 }
1499
1500
1501 /*
1502 * Create spin object on menu m.
1503 *
1504 * Returns the object's index or -1 on error.
1505 */
SARMenuSpinNew(sar_menu_struct * m,float x,float y,float width,float height,sar_menu_color_struct * label_color,sar_menu_color_struct * value_color,GWFont * font,GWFont * value_font,const char * label,const sar_image_struct * label_image,const sar_image_struct * value_image,const sar_image_struct * dec_armed_image,const sar_image_struct * dec_unarmed_image,const sar_image_struct * inc_armed_image,const sar_image_struct * inc_unarmed_image,void * client_data,int id,void (* change_cb)(void *,int,void *,char *))1506 int SARMenuSpinNew(
1507 sar_menu_struct *m,
1508 float x, float y,
1509 float width, float height,
1510 sar_menu_color_struct *label_color,
1511 sar_menu_color_struct *value_color,
1512 GWFont *font, GWFont *value_font,
1513 const char *label,
1514 const sar_image_struct *label_image,
1515 const sar_image_struct *value_image,
1516 const sar_image_struct *dec_armed_image,
1517 const sar_image_struct *dec_unarmed_image,
1518 const sar_image_struct *inc_armed_image,
1519 const sar_image_struct *inc_unarmed_image,
1520 void *client_data, int id,
1521 void (*change_cb)(void *, int, void *, char *)
1522 )
1523 {
1524 int i, n;
1525 sar_menu_spin_struct *spin;
1526
1527
1528 if(m == NULL)
1529 return(-1);
1530
1531 if(m->total_objects < 0)
1532 m->total_objects = 0;
1533
1534 for(i = 0; i < m->total_objects; i++)
1535 {
1536 if(m->object[i] == NULL)
1537 break;
1538 }
1539 if(i < m->total_objects)
1540 {
1541 n = i;
1542 }
1543 else
1544 {
1545 n = m->total_objects;
1546 m->total_objects = n + 1;
1547 m->object = (void **)realloc(
1548 m->object,
1549 m->total_objects * sizeof(void *)
1550 );
1551 if(m->object == NULL)
1552 {
1553 m->total_objects = 0;
1554 return(-3);
1555 }
1556 }
1557
1558 /* Allocate structure */
1559 m->object[n] = spin = SAR_MENU_SPIN(calloc(
1560 1, sizeof(sar_menu_spin_struct)
1561 ));
1562 if(spin == NULL)
1563 return(-3);
1564
1565 /* Set spin values */
1566 spin->type = SAR_MENU_OBJECT_TYPE_SPIN;
1567 spin->x = x;
1568 spin->y = y;
1569 spin->width = width;
1570 spin->height = height;
1571 spin->sensitive = True;
1572 spin->label_image = label_image;
1573 spin->value_image = value_image;
1574 spin->dec_armed_image = dec_armed_image;
1575 spin->dec_unarmed_image = dec_unarmed_image;
1576 spin->inc_armed_image = inc_armed_image;
1577 spin->inc_unarmed_image = inc_unarmed_image;
1578 memcpy(&spin->label_color, label_color, sizeof(sar_menu_color_struct));
1579 memcpy(&spin->value_color, value_color, sizeof(sar_menu_color_struct));
1580 spin->font = font;
1581 spin->value_font = value_font;
1582 spin->dec_state = SAR_MENU_BUTTON_STATE_UNARMED;
1583 spin->inc_state = SAR_MENU_BUTTON_STATE_UNARMED;
1584 spin->label = STRDUP(label);
1585 spin->value_type = SAR_MENU_SPIN_TYPE_STRING;
1586 spin->allow_warp = True;
1587 spin->step = 1.0;
1588 spin->value = NULL;
1589 spin->total_values = 0;
1590 spin->cur_value = -1;
1591 spin->client_data = client_data;
1592 spin->id = id;
1593 spin->change_cb = change_cb;
1594
1595 /* Select this object if it is the first one */
1596 if(m->total_objects == 1)
1597 m->selected_object = 0;
1598
1599 return(n);
1600 }
1601
1602 /*
1603 * Set value type for spin object n on menu m.
1604 */
SARMenuSpinSetValueType(sar_menu_struct * m,int n,int type)1605 void SARMenuSpinSetValueType(
1606 sar_menu_struct *m, int n, int type
1607 )
1608 {
1609 sar_menu_spin_struct *spin = SAR_MENU_SPIN(
1610 SARMenuGetObject(m, n)
1611 );
1612 if(!SAR_MENU_IS_SPIN(spin))
1613 return;
1614
1615 spin->value_type = type;
1616 }
1617
1618 /*
1619 * Adds value to spin object n on menu m.
1620 *
1621 * If the spin object is set to SAR_MENU_SPIN_TYPE_NUMERIC then
1622 * this will update its current value, otherwise a new value will
1623 * be appended to the spin object's list of values.
1624 */
SARMenuSpinAddValue(sar_menu_struct * m,int n,const char * value)1625 int SARMenuSpinAddValue(
1626 sar_menu_struct *m, int n, const char *value
1627 )
1628 {
1629 int vn;
1630 sar_menu_spin_struct *spin = SAR_MENU_SPIN(
1631 SARMenuGetObject(m, n)
1632 );
1633 if(!SAR_MENU_IS_SPIN(spin))
1634 return(-1);
1635
1636 /* Handle by value type */
1637 switch(spin->value_type)
1638 {
1639 case SAR_MENU_SPIN_TYPE_STRING:
1640 /* Allocate one more pointer */
1641 vn = MAX(spin->total_values, 0);
1642 spin->total_values = vn + 1;
1643 spin->value = (char **)realloc(
1644 spin->value,
1645 spin->total_values * sizeof(char *)
1646 );
1647 if(spin->value == NULL)
1648 {
1649 spin->total_values = 0;
1650 spin->cur_value = -1;
1651 return(-3);
1652 }
1653 /* Now value_num should be a valid pointer, allocate a new
1654 * value for it
1655 */
1656 spin->value[vn] = STRDUP(value);
1657 break;
1658
1659 case SAR_MENU_SPIN_TYPE_NUMERIC:
1660 /* Have at least one value? */
1661 if(spin->total_values < 1)
1662 {
1663 /* Need to allocate just one value */
1664 vn = 0;
1665 spin->total_values = vn + 1;
1666 spin->value = (char **)realloc(
1667 spin->value,
1668 spin->total_values * sizeof(char *)
1669 );
1670 if(spin->value == NULL)
1671 {
1672 spin->total_values = 0;
1673 spin->cur_value = -1;
1674 return(-3);
1675 }
1676
1677 spin->value[vn] = NULL;
1678 }
1679 else
1680 {
1681 vn = 0;
1682 }
1683 /* Now value_num should be a valid pointer, allocate a new
1684 * value string for it.
1685 */
1686 free(spin->value[vn]);
1687 spin->value[vn] = STRDUP(value);
1688 break;
1689 }
1690
1691 /* Update current value */
1692 if(spin->total_values > 0)
1693 {
1694 if(spin->cur_value < 0)
1695 spin->cur_value = 0;
1696 }
1697
1698 return(0);
1699 }
1700
1701 /*
1702 * Returns the Spin's current value.
1703 */
SARMenuSpinGetCurrentValue(sar_menu_struct * m,int n,int * sel_num)1704 char *SARMenuSpinGetCurrentValue(
1705 sar_menu_struct *m, int n, int *sel_num
1706 )
1707 {
1708 int vn;
1709 sar_menu_spin_struct *spin = SAR_MENU_SPIN(
1710 SARMenuGetObject(m, n)
1711 );
1712
1713 if(sel_num != NULL)
1714 *sel_num = -1;
1715
1716 if(!SAR_MENU_IS_SPIN(spin))
1717 return(NULL);
1718
1719 vn = spin->cur_value;
1720 if((vn < 0) || (vn >= spin->total_values))
1721 {
1722 return(NULL);
1723 }
1724 else
1725 {
1726 if(sel_num != NULL)
1727 *sel_num = vn;
1728 return(spin->value[vn]);
1729 }
1730 }
1731
1732 /*
1733 * Spins the spin to the value specified by value_num.
1734 */
SARMenuSpinSelectValueIndex(gw_display_struct * display,sar_menu_struct * m,int n,int value_num,Boolean redraw)1735 void SARMenuSpinSelectValueIndex(
1736 gw_display_struct *display, sar_menu_struct *m, int n,
1737 int value_num,
1738 Boolean redraw
1739 )
1740 {
1741 sar_menu_spin_struct *spin = SAR_MENU_SPIN(
1742 SARMenuGetObject(m, n)
1743 );
1744 if(!SAR_MENU_IS_SPIN(spin))
1745 return;
1746
1747 if((value_num < 0) || (value_num >= spin->total_values))
1748 return;
1749
1750 if(value_num != spin->cur_value)
1751 {
1752 spin->cur_value = value_num;
1753
1754 if(redraw)
1755 DO_REDRAW_OBJECT(display, m, n)
1756
1757 if(spin->change_cb != NULL)
1758 spin->change_cb(
1759 spin, /* This Object */
1760 spin->id, /* ID Code */
1761 spin->client_data, /* Data */
1762 spin->value[value_num] /* Value */
1763 );
1764 }
1765 }
1766
1767 /*
1768 * Sets the spin value specified by value_num to the new value
1769 * specified by value.
1770 */
SARMenuSpinSetValueIndex(gw_display_struct * display,sar_menu_struct * m,int n,int value_num,const char * value,Boolean redraw)1771 void SARMenuSpinSetValueIndex(
1772 gw_display_struct *display, sar_menu_struct *m, int n,
1773 int value_num, const char *value,
1774 Boolean redraw
1775 )
1776 {
1777 Boolean need_change = False;
1778 sar_menu_spin_struct *spin = SAR_MENU_SPIN(
1779 SARMenuGetObject(m, n)
1780 );
1781 if(!SAR_MENU_IS_SPIN(spin))
1782 return;
1783
1784 if((value_num < 0) || (value_num >= spin->total_values))
1785 return;
1786
1787 if(value == NULL)
1788 value = "";
1789
1790 if(spin->value[value_num] != NULL)
1791 need_change = (strcmp(spin->value[value_num], value)) ?
1792 True : False;
1793 else
1794 need_change = True;
1795 if(need_change)
1796 {
1797 free(spin->value[value_num]);
1798 spin->value[value_num] = STRDUP(value);
1799
1800 if(redraw)
1801 DO_REDRAW_OBJECT(display, m, n)
1802
1803 if(spin->change_cb != NULL)
1804 spin->change_cb(
1805 spin, /* This Object */
1806 spin->id, /* ID Code */
1807 spin->client_data, /* Data */
1808 spin->value[value_num] /* Value */
1809 );
1810 }
1811 }
1812
1813 /*
1814 * Deletes all values on spin n on menu m.
1815 */
SARMenuSpinDeleteAllValues(sar_menu_struct * m,int n)1816 void SARMenuSpinDeleteAllValues(sar_menu_struct *m, int n)
1817 {
1818 sar_menu_spin_struct *spin = SAR_MENU_SPIN(
1819 SARMenuGetObject(m, n)
1820 );
1821 if(!SAR_MENU_IS_SPIN(spin))
1822 return;
1823
1824 strlistfree(spin->value, spin->total_values);
1825 spin->value = NULL;
1826 spin->total_values = 0;
1827 spin->cur_value = -1;
1828 }
1829
1830 /*
1831 * Spin increment procedure.
1832 */
SARMenuSpinDoInc(gw_display_struct * display,sar_menu_struct * m,int n,Boolean redraw)1833 void SARMenuSpinDoInc(
1834 gw_display_struct *display, sar_menu_struct *m, int n,
1835 Boolean redraw
1836 )
1837 {
1838 int prev_value_num;
1839 char *value_ptr;
1840 sar_menu_spin_struct *spin = SAR_MENU_SPIN(
1841 SARMenuGetObject(m, n)
1842 );
1843 if((display == NULL) || (spin == NULL))
1844 return;
1845
1846 if(!SAR_MENU_IS_SPIN(spin))
1847 return;
1848
1849 /* Record previous value number */
1850 prev_value_num = spin->cur_value;
1851
1852 /* Increment by value type */
1853 switch(spin->value_type)
1854 {
1855 case SAR_MENU_SPIN_TYPE_STRING:
1856 if(spin->allow_warp ? True :
1857 (spin->cur_value < (spin->total_values - 1))
1858 )
1859 {
1860 spin->cur_value++;
1861 if(spin->cur_value >= spin->total_values)
1862 spin->cur_value = 0;
1863
1864 if(redraw)
1865 DO_REDRAW_OBJECT(display, m, n)
1866
1867 if((spin->cur_value >= 0) &&
1868 (spin->cur_value < spin->total_values)
1869 )
1870 value_ptr = spin->value[spin->cur_value];
1871 else
1872 value_ptr = NULL;
1873
1874 /* Call change callback? */
1875 if((spin->change_cb != NULL) &&
1876 (prev_value_num != spin->cur_value) &&
1877 (value_ptr != NULL)
1878 )
1879 spin->change_cb(
1880 spin, /* This Object */
1881 spin->id, /* ID Code */
1882 spin->client_data, /* Data */
1883 value_ptr /* Value */
1884 );
1885 }
1886 break;
1887
1888 case SAR_MENU_SPIN_TYPE_NUMERIC:
1889 /* TODO */
1890 break;
1891 }
1892 }
1893
1894 /*
1895 * Spin increment procedure.
1896 */
SARMenuSpinDoDec(gw_display_struct * display,sar_menu_struct * m,int n,Boolean redraw)1897 void SARMenuSpinDoDec(
1898 gw_display_struct *display, sar_menu_struct *m, int n,
1899 Boolean redraw
1900 )
1901 {
1902 int prev_value_num;
1903 char *value_ptr;
1904 sar_menu_spin_struct *spin = SAR_MENU_SPIN(
1905 SARMenuGetObject(m, n)
1906 );
1907 if((display == NULL) || (spin == NULL))
1908 return;
1909
1910 if(!SAR_MENU_IS_SPIN(spin))
1911 return;
1912
1913 /* Record previous value number */
1914 prev_value_num = spin->cur_value;
1915
1916 /* Decrement by value type */
1917 switch(spin->value_type)
1918 {
1919 case SAR_MENU_SPIN_TYPE_STRING:
1920 if(spin->allow_warp ? True :
1921 (spin->cur_value > 0)
1922 )
1923 {
1924 spin->cur_value--;
1925 if(spin->cur_value < 0)
1926 spin->cur_value = spin->total_values - 1;
1927
1928 if(redraw)
1929 DO_REDRAW_OBJECT(display, m, n)
1930
1931 if((spin->cur_value >= 0) &&
1932 (spin->cur_value < spin->total_values)
1933 )
1934 value_ptr = spin->value[spin->cur_value];
1935 else
1936 value_ptr = NULL;
1937
1938 /* Call change callback? */
1939 if((spin->change_cb != NULL) &&
1940 (prev_value_num != spin->cur_value) &&
1941 (value_ptr != NULL)
1942 )
1943 spin->change_cb(
1944 spin, /* This Object */
1945 spin->id, /* ID Code */
1946 spin->client_data, /* Data */
1947 value_ptr /* Value */
1948 );
1949 }
1950 break;
1951
1952 case SAR_MENU_SPIN_TYPE_NUMERIC:
1953 /* TODO */
1954 break;
1955 }
1956 }
1957
1958
1959 /*
1960 * Create slider object on menu m.
1961 *
1962 * Returns the object's index or -1 on error.
1963 */
SARMenuSliderNew(sar_menu_struct * m,float x,float y,float width,float height,sar_menu_color_struct * label_color,GWFont * font,const char * label,const sar_image_struct * label_image,const sar_image_struct * trough_image,const sar_image_struct * handle_image,void * client_data,int id,void (* change_cb)(void *,int,void *,float))1964 int SARMenuSliderNew(
1965 sar_menu_struct *m,
1966 float x, float y,
1967 float width, float height,
1968 sar_menu_color_struct *label_color,
1969 GWFont *font,
1970 const char *label,
1971 const sar_image_struct *label_image,
1972 const sar_image_struct *trough_image,
1973 const sar_image_struct *handle_image,
1974 void *client_data, int id,
1975 void (*change_cb)(void *, int, void *, float)
1976 )
1977 {
1978 int i, n;
1979 sar_menu_slider_struct *slider;
1980
1981
1982 if(m == NULL)
1983 return(-1);
1984
1985 if(m->total_objects < 0)
1986 m->total_objects = 0;
1987
1988 for(i = 0; i < m->total_objects; i++)
1989 {
1990 if(m->object[i] == NULL)
1991 break;
1992 }
1993 if(i < m->total_objects)
1994 {
1995 n = i;
1996 }
1997 else
1998 {
1999 n = m->total_objects;
2000 m->total_objects = n + 1;
2001 m->object = (void **)realloc(
2002 m->object,
2003 m->total_objects * sizeof(void *)
2004 );
2005 if(m->object == NULL)
2006 {
2007 m->total_objects = 0;
2008 return(-3);
2009 }
2010 }
2011
2012 /* Allocate structure */
2013 m->object[n] = slider = SAR_MENU_SLIDER(calloc(
2014 1, sizeof(sar_menu_slider_struct)
2015 ));
2016 if(slider == NULL)
2017 return(-3);
2018
2019 /* Set slider values */
2020 slider->type = SAR_MENU_OBJECT_TYPE_SLIDER;
2021 slider->x = x;
2022 slider->y = y;
2023 slider->width = width;
2024 slider->height = height;
2025 slider->sensitive = True;
2026 slider->label_image = label_image;
2027 slider->trough_image = trough_image;
2028 slider->handle_image = handle_image;
2029 memcpy(&slider->label_color, label_color, sizeof(sar_menu_color_struct));
2030 slider->font = font;
2031 slider->label = STRDUP(label);
2032 slider->value = 0.0f;
2033 slider->lower = 0.0f;
2034 slider->upper = 1.0f;
2035 slider->drag_button = 0;
2036 slider->client_data = client_data;
2037 slider->id = id;
2038 slider->change_cb = change_cb;
2039
2040 /* Select this object if it is the first one */
2041 if(m->total_objects == 1)
2042 m->selected_object = 0;
2043
2044 return(n);
2045 }
2046
2047 /*
2048 * Sets the lower and upper value bounds for the slider.
2049 */
SARMenuSliderSetValueBounds(gw_display_struct * display,sar_menu_struct * m,int n,float lower,float upper,Boolean redraw)2050 void SARMenuSliderSetValueBounds(
2051 gw_display_struct *display, sar_menu_struct *m, int n,
2052 float lower, float upper,
2053 Boolean redraw
2054 )
2055 {
2056 Boolean change = False;
2057 sar_menu_slider_struct *slider = SAR_MENU_SLIDER(
2058 SARMenuGetObject(m, n)
2059 );
2060 if((display == NULL) || (slider == NULL))
2061 return;
2062
2063 if(!SAR_MENU_IS_SLIDER(slider))
2064 return;
2065
2066 /* Set value only if the new value is different */
2067 if((slider->lower != lower) || (slider->upper != upper))
2068 {
2069 slider->upper = upper;
2070 slider->lower = lower;
2071 slider->value = CLIP(slider->value, slider->lower, slider->upper);
2072 change = True;
2073 }
2074
2075 /* Check if there is a change in the value, if there is then
2076 * redraw and call change callback.
2077 */
2078 if(change)
2079 {
2080 if(redraw)
2081 DO_REDRAW_OBJECT(display, m, n)
2082
2083 if(slider->change_cb != NULL)
2084 slider->change_cb(
2085 slider, /* This Object */
2086 slider->id, /* ID Code */
2087 slider->client_data, /* Data */
2088 slider->value /* Value */
2089 );
2090 }
2091 }
2092
2093 /*
2094 * Sets the value for the slider.
2095 */
SARMenuSliderSetValue(gw_display_struct * display,sar_menu_struct * m,int n,float value,Boolean redraw)2096 void SARMenuSliderSetValue(
2097 gw_display_struct *display, sar_menu_struct *m, int n,
2098 float value,
2099 Boolean redraw
2100 )
2101 {
2102 Boolean change = False;
2103 sar_menu_slider_struct *slider = SAR_MENU_SLIDER(
2104 SARMenuGetObject(m, n)
2105 );
2106 if((display == NULL) || (slider == NULL))
2107 return;
2108
2109 if(!SAR_MENU_IS_SLIDER(slider))
2110 return;
2111
2112 /* Set value only if the new value is different */
2113 if(slider->value != value)
2114 {
2115 slider->value = CLIP(value, slider->lower, slider->upper);
2116 change = True;
2117 }
2118
2119 /* Check if there is a change in the value, if there is then
2120 * redraw and call change callback
2121 */
2122 if(change)
2123 {
2124 if(redraw)
2125 DO_REDRAW_OBJECT(display, m, n)
2126
2127 if(slider->change_cb != NULL)
2128 slider->change_cb(
2129 slider, /* This Object */
2130 slider->id, /* ID Code */
2131 slider->client_data, /* Data */
2132 slider->value /* Value */
2133 );
2134 }
2135 }
2136
2137 /*
2138 * Returns the current value of the slider.
2139 */
SARMenuSliderGetValue(sar_menu_struct * m,int n)2140 float SARMenuSliderGetValue(sar_menu_struct *m, int n)
2141 {
2142 sar_menu_slider_struct *slider = SAR_MENU_SLIDER(
2143 SARMenuGetObject(m, n)
2144 );
2145 if(slider == NULL)
2146 return(0.0f);
2147
2148 if(!SAR_MENU_IS_SLIDER(slider))
2149 return(0.0f);
2150
2151 return(slider->value);
2152 }
2153
2154
2155 /*
2156 * Sets object n sensitive or insensitive.
2157 */
SARMenuObjectSetSensitive(gw_display_struct * display,sar_menu_struct * m,int n,Boolean sensitive,Boolean redraw)2158 void SARMenuObjectSetSensitive(
2159 gw_display_struct *display, sar_menu_struct *m, int n,
2160 Boolean sensitive, Boolean redraw
2161 )
2162 {
2163 sar_menu_label_struct *label_ptr;
2164 sar_menu_button_struct *button;
2165 sar_menu_progress_struct *progress;
2166 sar_menu_message_box_struct *mesgbox;
2167 sar_menu_list_struct *list;
2168 sar_menu_mdisplay_struct *mdpy;
2169 sar_menu_switch_struct *sw;
2170 sar_menu_spin_struct *spin;
2171 sar_menu_slider_struct *slider;
2172 sar_menu_map_struct *map;
2173 sar_menu_objview_struct *objview;
2174 Boolean changed = False;
2175 void *o = SARMenuGetObject(m, n);
2176 if(o == NULL)
2177 return;
2178
2179 switch(SAR_MENU_OBJECT_TYPE(o))
2180 {
2181 case SAR_MENU_OBJECT_TYPE_LABEL:
2182 label_ptr = SAR_MENU_LABEL(o);
2183 if(label_ptr->sensitive != sensitive)
2184 {
2185 label_ptr->sensitive = sensitive;
2186 changed = True;
2187 }
2188 break;
2189 case SAR_MENU_OBJECT_TYPE_BUTTON:
2190 button = SAR_MENU_BUTTON(o);
2191 if(button->sensitive != sensitive)
2192 {
2193 button->sensitive = sensitive;
2194 changed = True;
2195 }
2196 break;
2197 case SAR_MENU_OBJECT_TYPE_PROGRESS:
2198 progress = SAR_MENU_PROGRESS(o);
2199 if(progress->sensitive != sensitive)
2200 {
2201 progress->sensitive = sensitive;
2202 changed = True;
2203 }
2204 break;
2205 case SAR_MENU_OBJECT_TYPE_MESSAGE_BOX:
2206 mesgbox = SAR_MENU_MESSAGE_BOX(o);
2207 if(mesgbox->sensitive != sensitive)
2208 {
2209 mesgbox->sensitive = sensitive;
2210 changed = True;
2211 }
2212 break;
2213 case SAR_MENU_OBJECT_TYPE_LIST:
2214 list = SAR_MENU_LIST(o);
2215 if(list->sensitive != sensitive)
2216 {
2217 list->sensitive = sensitive;
2218 changed = True;
2219 }
2220 break;
2221 case SAR_MENU_OBJECT_TYPE_MDISPLAY:
2222 mdpy = SAR_MENU_MDISPLAY(o);
2223 if(mdpy->sensitive != sensitive)
2224 {
2225 mdpy->sensitive = sensitive;
2226 changed = True;
2227 }
2228 break;
2229 case SAR_MENU_OBJECT_TYPE_SWITCH:
2230 sw = SAR_MENU_SWITCH(o);
2231 if(sw->sensitive != sensitive)
2232 {
2233 sw->sensitive = sensitive;
2234 changed = True;
2235 }
2236 break;
2237 case SAR_MENU_OBJECT_TYPE_SPIN:
2238 spin = SAR_MENU_SPIN(o);
2239 if(spin->sensitive != sensitive)
2240 {
2241 spin->sensitive = sensitive;
2242 changed = True;
2243 }
2244 break;
2245 case SAR_MENU_OBJECT_TYPE_SLIDER:
2246 slider = SAR_MENU_SLIDER(o);
2247 if(slider->sensitive != sensitive)
2248 {
2249 slider->sensitive = sensitive;
2250 changed = True;
2251 }
2252 break;
2253 case SAR_MENU_OBJECT_TYPE_MAP:
2254 map = SAR_MENU_MAP(o);
2255 if(map->sensitive != sensitive)
2256 {
2257 map->sensitive = sensitive;
2258 changed = True;
2259 }
2260 break;
2261 case SAR_MENU_OBJECT_TYPE_OBJVIEW:
2262 objview = SAR_MENU_OBJVIEW(o);
2263 if(objview->sensitive != sensitive)
2264 {
2265 objview->sensitive = sensitive;
2266 changed = True;
2267 }
2268 break;
2269 }
2270
2271 if(redraw && changed)
2272 DO_REDRAW_OBJECT(display, m, n)
2273 }
2274
2275 /*
2276 * Destroys object n on menu m.
2277 */
SARMenuObjectDelete(sar_menu_struct * m,int n)2278 void SARMenuObjectDelete(sar_menu_struct *m, int n)
2279 {
2280 void *o = SARMenuGetObject(m, n);
2281 if(o != NULL)
2282 {
2283 sar_menu_object_type type;
2284 sar_menu_label_struct *label_ptr;
2285 sar_menu_button_struct *button;
2286 sar_menu_progress_struct *progress_ptr;
2287 sar_menu_message_box_struct *mesgbox;
2288 sar_menu_list_struct *list;
2289 sar_menu_mdisplay_struct *mdpy;
2290 sar_menu_switch_struct *sw;
2291 sar_menu_spin_struct *spin;
2292 sar_menu_slider_struct *slider;
2293 sar_menu_map_struct *map;
2294 sar_menu_objview_struct *objview;
2295
2296
2297 type = SAR_MENU_OBJECT_TYPE(o);
2298 switch(type)
2299 {
2300 case SAR_MENU_OBJECT_TYPE_LABEL:
2301 label_ptr = SAR_MENU_LABEL(o);
2302 label_ptr->image = NULL; /* Shared */
2303 free(label_ptr->label);
2304 free(label_ptr);
2305 break;
2306
2307 case SAR_MENU_OBJECT_TYPE_BUTTON:
2308 button = SAR_MENU_BUTTON(o);
2309 button->unarmed_image = NULL; /* Shared */
2310 button->armed_image = NULL; /* Shared */
2311 button->highlighted_image = NULL; /* Shared */
2312 free(button->label);
2313 free(button);
2314 break;
2315
2316 case SAR_MENU_OBJECT_TYPE_PROGRESS:
2317 progress_ptr = SAR_MENU_PROGRESS(o);
2318 progress_ptr->bg_image = NULL; /* Shared */
2319 progress_ptr->fg_image = NULL; /* Shared */
2320 free(progress_ptr->label);
2321 free(progress_ptr);
2322 break;
2323
2324 case SAR_MENU_OBJECT_TYPE_MESSAGE_BOX:
2325 mesgbox = SAR_MENU_MESSAGE_BOX(o);
2326 mesgbox->bg_image = NULL; /* Shared */
2327 free(mesgbox->message);
2328 free(mesgbox);
2329 break;
2330
2331 case SAR_MENU_OBJECT_TYPE_LIST:
2332 list = SAR_MENU_LIST(o);
2333 SARMenuListDeleteAllItems(m, n);
2334 list->bg_image = NULL; /* Shared */
2335 free(list->item);
2336 free(list->label);
2337 free(list);
2338 break;
2339
2340 case SAR_MENU_OBJECT_TYPE_MDISPLAY:
2341 mdpy = SAR_MENU_MDISPLAY(o);
2342 mdpy->bg_image = NULL; /* Shared */
2343 free(mdpy);
2344 break;
2345
2346 case SAR_MENU_OBJECT_TYPE_SWITCH:
2347 sw = SAR_MENU_SWITCH(o);
2348 sw->bg_image = NULL; /* Shared */
2349 sw->switch_off_image = NULL; /* Shared */
2350 sw->switch_on_image = NULL; /* Shared */
2351 free(sw->label);
2352 free(sw);
2353 break;
2354
2355 case SAR_MENU_OBJECT_TYPE_SPIN:
2356 spin = SAR_MENU_SPIN(o);
2357 SARMenuSpinDeleteAllValues(m, n);
2358 spin->label_image = NULL; /* Shared */
2359 spin->value_image = NULL; /* Shared */
2360 spin->dec_armed_image = NULL; /* Shared */
2361 spin->dec_unarmed_image = NULL; /* Shared */
2362 spin->inc_armed_image = NULL; /* Shared */
2363 spin->inc_unarmed_image = NULL; /* Shared */
2364 free(spin->label);
2365 free(spin);
2366 break;
2367
2368 case SAR_MENU_OBJECT_TYPE_SLIDER:
2369 slider = SAR_MENU_SLIDER(o);
2370 slider->label_image = NULL; /* Shared */
2371 slider->trough_image = NULL; /* Shared */
2372 slider->handle_image = NULL; /* Shared */
2373 free(slider->label);
2374 free(slider);
2375 break;
2376
2377 case SAR_MENU_OBJECT_TYPE_MAP:
2378 map = SAR_MENU_MAP(o);
2379 SARMenuMapDeleteAllMarkings(map);
2380 V3DTextureDestroy(map->bg_tex);
2381 map->bg_tex = NULL;
2382 free(map->title);
2383 map->title = NULL;
2384 free(map);
2385 break;
2386
2387 case SAR_MENU_OBJECT_TYPE_OBJVIEW:
2388 objview = SAR_MENU_OBJVIEW(o);
2389 free(objview->title);
2390 objview->title = NULL;
2391 free(objview->message);
2392 objview->message = NULL;
2393 if(objview->obj_list != NULL)
2394 {
2395 GLuint list = (GLuint)objview->obj_list;
2396 glDeleteLists(list, 1);
2397 objview->obj_list = NULL;
2398 }
2399 V3DGLResourceDelete(
2400 (v3d_glresource_struct *)objview->obj_glres
2401 );
2402 objview->obj_glres = NULL;
2403 free(objview->objimg);
2404 objview->objimg = NULL;
2405 free(objview);
2406 break;
2407
2408
2409 default:
2410 fprintf(
2411 stderr,
2412 "SARMenuObjectDelete(): Destroying unknown type `%i'\n",
2413 type
2414 );
2415 free(o);
2416 break;
2417 }
2418
2419 m->object[n] = NULL;
2420 }
2421 }
2422
2423
2424 /*
2425 * Draws one line of string starting at buf_ptr and does not
2426 * draw more than the number of whole word characters specified by
2427 * visible_columns.
2428 *
2429 * Returns the pointer to the next word that lies within buf_ptr
2430 * or NULL if a '\0' character was encountered while drawing the
2431 * string.
2432 */
SARMenuMessageBoxDrawString(gw_display_struct * display,int x,int y,const char * buf_ptr,int visible_columns,int font_width,Boolean sensitive,Boolean draw_line,const sar_menu_color_struct * c_def,const sar_menu_color_struct * c_bold,const sar_menu_color_struct * c_ul)2433 static const char *SARMenuMessageBoxDrawString(
2434 gw_display_struct *display,
2435 int x, int y,
2436 const char *buf_ptr,
2437 int visible_columns, int font_width,
2438 Boolean sensitive,
2439 Boolean draw_line,
2440 const sar_menu_color_struct *c_def,
2441 const sar_menu_color_struct *c_bold,
2442 const sar_menu_color_struct *c_ul
2443 )
2444 {
2445 char c;
2446 int characters_drawn;
2447 const char *s, *buf_stop;
2448
2449
2450 if((display == NULL) || (buf_ptr == NULL) || (visible_columns < 1))
2451 return(NULL);
2452
2453 /* If given buffer points to a end of buffer then return NULL */
2454 if(*buf_ptr == '\0')
2455 return(NULL);
2456
2457 /* If given string points to a newline then just return the
2458 * pointer to the next character. This will effectivly draw one
2459 * empty line.
2460 */
2461 if(ISCR(*buf_ptr))
2462 return(buf_ptr + 1);
2463
2464 /* Seek past initial spaces */
2465 while(ISBLANK(*buf_ptr))
2466 buf_ptr++;
2467
2468 /* Probe to end of line and mark it by setting buf_stop to point
2469 * to that end.
2470 */
2471 buf_stop = NULL;
2472 s = buf_ptr;
2473 for(characters_drawn = 0; characters_drawn < visible_columns;)
2474 {
2475 c = *s;
2476
2477 /* End of buffer? */
2478 if(c == '\0')
2479 {
2480 buf_stop = s;
2481 break;
2482 }
2483 /* Blank character? */
2484 else if(ISBLANK(c))
2485 {
2486 /* Mark end of buffer at this blank character and count it
2487 * as one character drawn (regardless of how many blank
2488 * characters follow).
2489 */
2490 buf_stop = s;
2491 characters_drawn++;
2492
2493 /* Seek past this and any following blank characters */
2494 while(ISBLANK(*s))
2495 s++;
2496 }
2497 /* New line? */
2498 else if(ISCR(c))
2499 {
2500 buf_stop = s;
2501 break;
2502 }
2503 /* Escape sequence? */
2504 else if(IS_CHAR_ESC_START(c))
2505 {
2506 /* Skip this character */
2507 s++;
2508
2509 /* Seek to end of escape sequence or end of buffer */
2510 while((*s != '\0') &&
2511 !IS_CHAR_ESC_END(*s)
2512 )
2513 s++;
2514 if(*s != '\0')
2515 s++;
2516 }
2517 /* Regular character */
2518 else
2519 {
2520 /* Mark this as a character to be drawn and increment to
2521 * next character.
2522 */
2523 characters_drawn++;
2524 s++;
2525 }
2526 }
2527
2528 /* If end of buffer was not found then assume it is at s */
2529 if(buf_stop == NULL)
2530 buf_stop = s;
2531
2532
2533 /* Draw from buf_ptr to (but not including) buf_stop */
2534 characters_drawn = 0;
2535 s = buf_ptr;
2536 while(s < buf_stop)
2537 {
2538 c = *s;
2539
2540 /* End of buffer? */
2541 if(c == '\0')
2542 {
2543 break;
2544 }
2545 /* Blank character? */
2546 else if(ISBLANK(c))
2547 {
2548 /* Draw one blank character and seek to next non-blank
2549 * character (regardless of how many blank characters
2550 * follow).
2551 */
2552 if(draw_line)
2553 GWDrawCharacter(
2554 display,
2555 x + (characters_drawn * font_width),
2556 y,
2557 c
2558 );
2559 characters_drawn++;
2560
2561 /* Seek past this and any following blank characters */
2562 while(ISBLANK(*s))
2563 s++;
2564 }
2565 /* Escape sequence? */
2566 else if(IS_CHAR_ESC_START(c))
2567 {
2568 int n;
2569 char tag_name[256];
2570
2571
2572 /* Skip this character */
2573 s++;
2574
2575 /* Seek to end of escape sequence or end of buffer */
2576 n = 0;
2577 while((*s != '\0') &&
2578 !IS_CHAR_ESC_END(*s)
2579 )
2580 {
2581 if(n < 254)
2582 {
2583 tag_name[n] = *s;
2584 n++;
2585 }
2586 s++;
2587 }
2588 if(*s != '\0')
2589 s++;
2590
2591 /* Null terminate tag_name */
2592 tag_name[n] = '\0';
2593
2594 /* Handle tag */
2595 /* Default? */
2596 if(!strcasecmp(tag_name, "default") ||
2597 !strcasecmp(tag_name, "plain") ||
2598 !strcasecmp(tag_name, "regular")
2599 )
2600 {
2601 if(c_def != NULL)
2602 {
2603 if(sensitive)
2604 glColor4f(
2605 c_def->r,
2606 c_def->g,
2607 c_def->b,
2608 c_def->a
2609 );
2610 else
2611 glColor4f(
2612 c_def->r * 0.75f,
2613 c_def->g * 0.75f,
2614 c_def->b * 0.75f,
2615 c_def->a
2616 );
2617 }
2618 }
2619 /* Bold? */
2620 else if(!strcasecmp(tag_name, "bold"))
2621 {
2622 if(c_bold != NULL)
2623 {
2624 if(sensitive)
2625 glColor4f(
2626 c_bold->r,
2627 c_bold->g,
2628 c_bold->b,
2629 c_bold->a
2630 );
2631 else
2632 glColor4f(
2633 c_bold->r * 0.75f,
2634 c_bold->g * 0.75f,
2635 c_bold->b * 0.75f,
2636 c_bold->a
2637 );
2638 }
2639 }
2640 /* Underline? */
2641 else if(!strcasecmp(tag_name, "underline") ||
2642 !strcasecmp(tag_name, "underlined")
2643 )
2644 {
2645 if(c_ul != NULL)
2646 {
2647 if(sensitive)
2648 glColor4f(
2649 c_ul->r,
2650 c_ul->g,
2651 c_ul->b,
2652 c_ul->a
2653 );
2654 else
2655 glColor4f(
2656 c_ul->r * 0.75f,
2657 c_ul->g * 0.75f,
2658 c_ul->b * 0.75f,
2659 c_ul->a
2660 );
2661 }
2662 }
2663
2664 }
2665 else
2666 {
2667 /* Actually draw this character? */
2668 if(draw_line)
2669 GWDrawCharacter(
2670 display,
2671 x + (characters_drawn * font_width),
2672 y,
2673 c
2674 );
2675 characters_drawn++;
2676 s++;
2677 }
2678 }
2679
2680 /* Return the pointer to the next character that was not
2681 * drawn.
2682 */
2683 return(buf_stop);
2684 }
2685
2686 /*
2687 * Returns the total number of lines by seeking through the given
2688 * buffer.
2689 */
SARMenuMessageBoxTotalLines(const char * buf_ptr,int visible_columns)2690 static int SARMenuMessageBoxTotalLines(
2691 const char *buf_ptr, int visible_columns
2692 )
2693 {
2694 char c;
2695 int line_count = 0, characters_drawn;
2696 const char *s, *buf_stop;
2697
2698
2699 if((buf_ptr == NULL) || (visible_columns < 1))
2700 return(line_count);
2701
2702 /* Iterate until end of buffer */
2703 while((buf_ptr != NULL) ? (*buf_ptr != '\0') : False)
2704 {
2705 /* Set s to point to the start of current line */
2706 s = buf_ptr;
2707
2708 /* If s is on a newline then seek to next character and
2709 * count this as one line.
2710 */
2711 if(ISCR(*s))
2712 {
2713 buf_ptr = s + 1;
2714 line_count++;
2715 continue;
2716 }
2717
2718 /* Seek past initial spaces */
2719 while(ISBLANK(*s))
2720 s++;
2721
2722 /* Reset stop buffer and seek to end of `line'. Remember that
2723 * characters_drawn represents the number of characters that
2724 * would be drawn to fit on one line with whole words. Not the
2725 * the actual characters drawn since nothing is being drawn in
2726 * this function.
2727 */
2728 buf_stop = NULL;
2729 for(characters_drawn = 0; characters_drawn < visible_columns;)
2730 {
2731 c = *s;
2732
2733 /* End of buffer? */
2734 if(c == '\0')
2735 {
2736 buf_stop = s;
2737 break;
2738 }
2739 /* Blank character? */
2740 else if(ISBLANK(c))
2741 {
2742 /* Count blank character as one character drawn and
2743 * seek to next non-blank character.
2744 */
2745 buf_stop = s;
2746 characters_drawn++;
2747
2748 /* Seek past this and any following blank characters */
2749 while(ISBLANK(*s))
2750 s++;
2751 }
2752 /* New line? */
2753 else if(ISCR(c))
2754 {
2755 buf_stop = s;
2756 break;
2757 }
2758 /* Escape sequence? */
2759 else if(IS_CHAR_ESC_START(c))
2760 {
2761 /* Skip this character */
2762 s++;
2763
2764 /* Seek to end of escape sequence or end of buffer */
2765 while((*s != '\0') &&
2766 !IS_CHAR_ESC_END(*s)
2767 )
2768 s++;
2769 if(*s != '\0')
2770 s++;
2771 }
2772 /* Regular character */
2773 else
2774 {
2775 /* Mark this as a character to be drawn and increment
2776 * to next character.
2777 */
2778 characters_drawn++;
2779 s++;
2780 }
2781 }
2782 /* If not able to find end of line pointer then assume end of
2783 * line is at current position of s.
2784 */
2785 if(buf_stop == NULL)
2786 buf_stop = s;
2787
2788 /* End of line reached, count this as one line and set buffer
2789 * to start of next line.
2790 */
2791 line_count++;
2792 buf_ptr = buf_stop;
2793 }
2794
2795 return(line_count);
2796 }
2797
2798 /*
2799 * Redraws a `window' comprised of 9 images where the first image
2800 * (index 0) is the background and the second image (index 1) through
2801 * the 9th image (index 8) are the 8 decoration edges starting from
2802 * the upper left corner.
2803 */
SARMenuDrawWindowBG(gw_display_struct * display,const sar_image_struct ** bg_image,const sar_menu_color_struct * base_color,int x,int y,int width,int height,Boolean draw_base,Boolean draw_shadow,Boolean is_selected)2804 void SARMenuDrawWindowBG(
2805 gw_display_struct *display,
2806 const sar_image_struct **bg_image, /* Total 9 images */
2807 const sar_menu_color_struct *base_color, /* Set NULL to use image as base */
2808 int x, int y,
2809 int width, int height,
2810 Boolean draw_base,
2811 Boolean draw_shadow,
2812 Boolean is_selected
2813 )
2814 {
2815 int corner_width = 0, corner_height = 0;
2816 int vframe_width = 0, hframe_height = 0;
2817 const sar_image_struct *img;
2818 int win_width, win_height;
2819
2820
2821 if((display == NULL) || (bg_image == NULL))
2822 return;
2823
2824 GWContextGet(
2825 display, GWContextCurrent(display),
2826 NULL, NULL,
2827 NULL, NULL,
2828 &win_width, &win_height
2829 );
2830
2831 /* Get upper left corner image */
2832 img = bg_image[1];
2833 if(img != NULL)
2834 {
2835 /* Get size of each corner by assuming they're all the same
2836 * and take the size of the upper left corner image.
2837 */
2838 corner_width = MAX(img->width, 0);
2839 corner_height = MAX(img->height, 0);
2840 }
2841
2842 /* Get upper horizontal frame image */
2843 img = bg_image[2];
2844 if(img != NULL)
2845 {
2846 /* Get height of both horizontal frames by taking the size of
2847 * the upper horizontal frame image.
2848 */
2849 hframe_height = MAX(img->height, 0);
2850 }
2851
2852 /* Get right vertical frame image */
2853 img = bg_image[4];
2854 if(img != NULL)
2855 {
2856 /* Get width of both vertical frames by taking the size of
2857 * the right vertical frame image.
2858 */
2859 vframe_width = MAX(img->width, 0);
2860 }
2861
2862 /* Adjust given geometry to fit `with in' the decorations */
2863 x += corner_width;
2864 y += corner_height;
2865 width = MAX(width - (2 * corner_width), 0);
2866 height = MAX(height - (2 * corner_height), 0);
2867
2868 if((width < 1) || (height < 1))
2869 return;
2870
2871 /* Draw shadow */
2872 if(draw_shadow)
2873 {
2874 StateGLBoolean alpha_test = display->state_gl.alpha_test,
2875 blend = display->state_gl.blend;
2876
2877 /* Set up GL states */
2878 StateGLDisable(&display->state_gl, GL_ALPHA_TEST);
2879 StateGLEnable(&display->state_gl, GL_BLEND);
2880 StateGLBlendFunc(
2881 &display->state_gl, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
2882 );
2883 glColor4f(0.0f, 0.0f, 0.0f, 0.25f);
2884
2885 glBegin(GL_QUADS);
2886 {
2887 glVertex2i(
2888 (GLint)(x + width + (0.5 * corner_width)),
2889 (GLint)(win_height - (y + height + (1.5 * corner_height)))
2890 );
2891 glVertex2i(
2892 (GLint)(x + width + (1.5 * corner_width)),
2893 (GLint)(win_height - (y + height + (1.5 * corner_height)))
2894 );
2895 glVertex2i(
2896 (GLint)(x + width + (1.5 * corner_width)),
2897 (GLint)(win_height - (y - (0.5 * corner_height)))
2898 );
2899 glVertex2i(
2900 (GLint)(x + width + (0.5 * corner_width)),
2901 (GLint)(win_height - (y - (0.5 * corner_height)))
2902 );
2903
2904 glVertex2i(
2905 (GLint)(x - (0.5 * corner_width)),
2906 (GLint)(win_height - (y + height + (1.5 * corner_height)))
2907 );
2908 glVertex2i(
2909 (GLint)(x + width + (0.5 * corner_width)),
2910 (GLint)(win_height - (y + height + (1.5 * corner_height)))
2911 );
2912 glVertex2i(
2913 (GLint)(x + width + (0.5 * corner_width)),
2914 (GLint)(win_height - (y + height + (0.5 * corner_height)))
2915 );
2916 glVertex2i(
2917 (GLint)(x - (0.5 * corner_width)),
2918 (GLint)(win_height - (y + height + (0.5 * corner_height)))
2919 );
2920 }
2921 glEnd();
2922
2923 /* Restore GL states */
2924 if(alpha_test)
2925 StateGLEnable(&display->state_gl, GL_ALPHA_TEST);
2926 if(!blend)
2927 StateGLDisable(&display->state_gl, GL_BLEND);
2928 }
2929
2930 /* Draw base image at center, scaled to fit the width and height
2931 * regardless of the actual image size
2932 */
2933 if(draw_base)
2934 {
2935 if(base_color != NULL)
2936 {
2937 glColor4f(
2938 base_color->r,
2939 base_color->g,
2940 base_color->b,
2941 base_color->a
2942 );
2943 glBegin(GL_QUADS);
2944 {
2945 glVertex2i(x - 1, win_height - (y - 1));
2946 glVertex2i(x - 1, win_height - (y + height + 2));
2947 glVertex2i(x + width + 2, win_height - (y + height + 2));
2948 glVertex2i(x + width + 2, win_height - (y - 1));
2949 }
2950 glEnd();
2951 }
2952 else
2953 {
2954 img = bg_image[0];
2955 SARImageDraw(
2956 display, img,
2957 x - 1, y - 1, width + 2, height + 2
2958 );
2959 }
2960
2961 /* Draw selection rectangle? */
2962 if(is_selected)
2963 {
2964 glColor4f(0.0f, 0.5f, 0.0f, 1.0f);
2965 glBegin(GL_LINE_LOOP);
2966 {
2967 int margin = 1;
2968 glVertex2i(x + margin, win_height - (y + margin));
2969 glVertex2i(x + margin, win_height - (y + height - margin));
2970 glVertex2i(x + width - margin, win_height - (y + height - margin));
2971 glVertex2i(x + width - margin, win_height - (y + margin));
2972 }
2973 glEnd();
2974 }
2975 }
2976
2977 /* Draw frame decorations (not including corners) next */
2978 img = bg_image[2];
2979 SARImageDraw(
2980 display, img,
2981 x - 1, y - hframe_height,
2982 width + 2, hframe_height
2983 );
2984
2985 img = bg_image[4];
2986 SARImageDraw(
2987 display, img,
2988 x + width, y - 1,
2989 vframe_width, height + 2
2990 );
2991
2992 img = bg_image[6];
2993 SARImageDraw(
2994 display, img,
2995 x - 1, y + height,
2996 width + 2, hframe_height
2997 );
2998
2999 img = bg_image[8];
3000 SARImageDraw(
3001 display, img,
3002 x - vframe_width, y - 1,
3003 vframe_width, height + 2
3004 );
3005
3006
3007 /* Draw corners */
3008 img = bg_image[1];
3009 SARImageDraw(
3010 display, img,
3011 x - corner_width, y - corner_height,
3012 corner_width, corner_height
3013 );
3014
3015 img = bg_image[3];
3016 SARImageDraw(
3017 display, img,
3018 x + width, y - corner_height,
3019 corner_width, corner_height
3020 );
3021
3022 img = bg_image[5];
3023 SARImageDraw(
3024 display, img,
3025 x + width, y + height,
3026 corner_width, corner_height
3027 );
3028
3029 img = bg_image[7];
3030 SARImageDraw(
3031 display, img,
3032 x - corner_width, y + height,
3033 corner_width, corner_height
3034 );
3035 }
3036
3037
3038 /*
3039 * Draws the specified object n.
3040 */
SARMenuDoDrawObject(gw_display_struct * display,sar_menu_struct * m,int n,Boolean draw_shadows)3041 static void SARMenuDoDrawObject(
3042 gw_display_struct *display, sar_menu_struct *m,
3043 int n, /* Object number on m */
3044 Boolean draw_shadows
3045 )
3046 {
3047 Boolean draw_selected_rect = True, is_selected;
3048 int i, x, y, xc, yc, w = 10, h = 10, width, height, len, type;
3049 int fw, fh;
3050 int items_visable, chars_per_row;
3051 const char *cstrptr;
3052 const sar_menu_color_struct *c;
3053 void *o;
3054 sar_menu_label_struct *label_ptr;
3055 sar_menu_button_struct *button;
3056 sar_menu_progress_struct *progress_ptr;
3057 sar_menu_message_box_struct *mesgbox;
3058 sar_menu_list_struct *list;
3059 sar_menu_mdisplay_struct *mdpy;
3060 sar_menu_switch_struct *sw;
3061 sar_menu_spin_struct *spin;
3062 sar_menu_slider_struct *slider;
3063 sar_menu_map_struct *map;
3064 sar_menu_objview_struct *objview;
3065
3066 static u_int8_t scroll_cursor_up_bm[] = {
3067 0xff, 0xff, 0x80, 0x01, 0xbf, 0xfd, 0xbf, 0xfd, 0x9f, 0xf9, 0x9f, 0xf9,
3068 0x8f, 0xf1, 0x8f, 0xf1, 0x87, 0xe1, 0x87, 0xe1, 0x83, 0xc1, 0x83, 0xc1,
3069 0x81, 0x81, 0x81, 0x81, 0x80, 0x01, 0xff, 0xff
3070 };
3071
3072 static u_int8_t scroll_cursor_down_bm[] = {
3073 0xff, 0xff, 0x80, 0x01, 0x81, 0x81, 0x81, 0x81, 0x83, 0xc1, 0x83, 0xc1,
3074 0x87, 0xe1, 0x87, 0xe1, 0x8f, 0xf1, 0x8f, 0xf1, 0x9f, 0xf9, 0x9f, 0xf9,
3075 0xbf, 0xfd, 0xbf, 0xfd, 0x80, 0x01, 0xff, 0xff
3076 };
3077 #if 0
3078 static u_int8_t scroll_cursor_left_bm[] = {
3079 0xff, 0xff, 0x80, 0x01, 0x80, 0x0d, 0x80, 0x3d, 0x80, 0xfd, 0x83, 0xfd,
3080 0x8f, 0xfd, 0xbf, 0xfd, 0xbf, 0xfd, 0x8f, 0xfd, 0x83, 0xfd, 0x80, 0xfd,
3081 0x80, 0x3d, 0x80, 0x0d, 0x80, 0x01, 0xff, 0xff
3082 };
3083 #endif
3084 #if 0
3085 static u_int8_t scroll_cursor_right_bm[] = {
3086 0xff, 0xff, 0x80, 0x01, 0xb0, 0x01, 0xbc, 0x01, 0xbf, 0x01, 0xbf, 0xc1,
3087 0xbf, 0xf1, 0xbf, 0xfd, 0xbf, 0xfd, 0xbf, 0xf1, 0xbf, 0xc1, 0xbf, 0x01,
3088 0xbc, 0x01, 0xb0, 0x01, 0x80, 0x01, 0xff, 0xff
3089 };
3090 #endif
3091 const sar_image_struct *image;
3092
3093
3094 if((display == NULL) || (m == NULL))
3095 return;
3096
3097 o = SARMenuGetObject(m, n);
3098 if(o == NULL)
3099 return;
3100
3101 type = SAR_MENU_OBJECT_TYPE(o);
3102
3103 is_selected = (m->selected_object == n) ? True : False;
3104
3105 GWContextGet(
3106 display, GWContextCurrent(display),
3107 NULL, NULL,
3108 NULL, NULL,
3109 &width, &height
3110 );
3111
3112 #define DO_DRAW_IMAGE \
3113 { if(image != NULL) { \
3114 SARImageDraw( \
3115 display, image, \
3116 (int)(x - (w / 2)), \
3117 (int)(y - (h / 2)), \
3118 w, h \
3119 ); \
3120 } }
3121
3122 switch(type)
3123 {
3124 /* ******************************************************** */
3125 case SAR_MENU_OBJECT_TYPE_LABEL:
3126 label_ptr = SAR_MENU_LABEL(o);
3127 w = label_ptr->width;
3128 h = label_ptr->height;
3129 x = (int)(label_ptr->x * width) + label_ptr->offset_x;
3130 y = (int)(label_ptr->y * height) + label_ptr->offset_y;
3131
3132 /* Draw label background image */
3133 image = label_ptr->image;
3134 DO_DRAW_IMAGE
3135
3136 /* Draw label text */
3137 if(label_ptr->label != NULL)
3138 {
3139 const char *s = label_ptr->label;
3140 int xp, yp,
3141 lines = strlines(s),
3142 longest_line = strlongestline(s);
3143
3144 GWGetFontSize(label_ptr->font, NULL, NULL, &fw, &fh);
3145
3146 /* Autocalculate width and height as needed */
3147 if(w <= 0)
3148 w = fw * longest_line;
3149 if(h <= 0)
3150 h = fh * lines;
3151
3152 /* Set label text font and color */
3153 GWSetFont(display, label_ptr->font);
3154 c = &label_ptr->color;
3155 if(label_ptr->sensitive)
3156 glColor4f(c->r, c->g, c->b, c->a);
3157 else
3158 glColor4f(
3159 c->r * 0.75f,
3160 c->g * 0.75f,
3161 c->b * 0.75f,
3162 c->a
3163 );
3164
3165 /* Get starting position to draw label text */
3166 xp = x - (fw * longest_line / 2);
3167 yp = y - (fh * lines / 2);
3168
3169 /* Draw each line of the label text*/
3170 while(*s != '\0')
3171 {
3172 /* New line? */
3173 if(ISCR(*s))
3174 {
3175 /* Restore x position and increment y position
3176 * to the next line
3177 */
3178 switch(label_ptr->align)
3179 {
3180 case SAR_MENU_LABEL_ALIGN_RIGHT:
3181 s++;
3182 xp = x + (fw * longest_line / 2) -
3183 (fw * strlinelen(s));
3184 yp += fh;
3185 break;
3186 case SAR_MENU_LABEL_ALIGN_LEFT:
3187 s++;
3188 xp = x - (fw * longest_line / 2);
3189 yp += fh;
3190 break;
3191 default: /* SAR_MENU_LABEL_ALIGN_CENTER */
3192 s++;
3193 xp = x - (fw * strlinelen(s) / 2);
3194 yp += fh;
3195 break;
3196 }
3197 }
3198 else
3199 {
3200 /* Draw current character */
3201 GWDrawCharacter(display, xp, yp, *s);
3202 s++;
3203 xp += fw;
3204 }
3205 }
3206 }
3207 break;
3208
3209 /* ******************************************************** */
3210 case SAR_MENU_OBJECT_TYPE_BUTTON:
3211 button = SAR_MENU_BUTTON(o);
3212 w = button->width;
3213 h = button->height;
3214 x = (int)(button->x * width) + button->offset_x;
3215 y = (int)(button->y * height) + button->offset_y;
3216 /* Select image to use based on button state */
3217 switch(button->state)
3218 {
3219 case SAR_MENU_BUTTON_STATE_HIGHLIGHTED:
3220 image = button->highlighted_image;
3221 break;
3222
3223 case SAR_MENU_BUTTON_STATE_ARMED:
3224 image = button->armed_image;
3225 break;
3226
3227 default:
3228 image = button->unarmed_image;
3229 break;
3230 }
3231 /* If image is not available, then fall back to unarmed
3232 * image.
3233 */
3234 if(image == NULL)
3235 image = button->unarmed_image;
3236 DO_DRAW_IMAGE
3237
3238 /* Draw label */
3239 cstrptr = button->label;
3240 if(cstrptr != NULL)
3241 {
3242 int x_min, x_max, y_min, y_max;
3243
3244 x_min = x - (w / 2);
3245 x_max = x_min + w;
3246 y_min = y - (h / 2);
3247 y_max = y_min + h;
3248
3249 len = STRLEN(cstrptr);
3250 GWGetFontSize(button->font, NULL, NULL, &fw, &fh);
3251 GWSetFont(display, button->font);
3252 c = &button->color;
3253 if(button->sensitive)
3254 glColor4f(c->r, c->g, c->b, c->a);
3255 else
3256 glColor4f(
3257 c->r * 0.75f,
3258 c->g * 0.75f,
3259 c->b * 0.75f,
3260 c->a
3261 );
3262 GWDrawString(
3263 display,
3264 x - (len * fw / 2),
3265 y - (fh / 2),
3266 cstrptr
3267 );
3268
3269 /* Do not draw outlines for buttons */
3270 }
3271 break;
3272
3273 /* ******************************************************** */
3274 case SAR_MENU_OBJECT_TYPE_PROGRESS:
3275 progress_ptr = SAR_MENU_PROGRESS(o);
3276
3277 x = (int)(progress_ptr->x * width);
3278 y = (int)(progress_ptr->y * height);
3279
3280 if(progress_ptr->width > 0)
3281 w = progress_ptr->width;
3282 else
3283 /* w = width - (2 * DEF_XMARGIN); */
3284 w = width; /* Butt left to right end */
3285
3286 if(progress_ptr->height > 0)
3287 h = progress_ptr->height;
3288 else
3289 h = DEF_PROGRESS_HEIGHT;
3290
3291 xc = MAX(x - (w / 2), 0);
3292 yc = MAX(y - (h / 2), 0);
3293 if((yc + h) > height)
3294 yc = height - h;
3295
3296 /* Draw progress background */
3297 SARImageDraw(display, progress_ptr->bg_image, xc, yc, w, h);
3298 #if 0
3299 if(GL_TRUE)
3300 {
3301 StateGLBoolean alpha_test = display->state_gl.alpha_test;
3302 StateGLBoolean blend = display->state_gl.blend;
3303
3304 /* Set up GL states */
3305 StateGLDisable(&display->state_gl, GL_ALPHA_TEST);
3306 StateGLEnable(&display->state_gl, GL_BLEND);
3307 StateGLBlendFunc(
3308 &display->state_gl, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA
3309 );
3310
3311 glColor4f(0.0f, 0.0f, 0.0f, 0.25f);
3312 glBegin(GL_QUADS);
3313 {
3314 glVertex2i(xc, height - yc);
3315 glVertex2i(xc, height - (yc + h));
3316 glVertex2i(xc + w, height - (yc + h));
3317 glVertex2i(xc + w, height - yc);
3318 }
3319 glEnd();
3320
3321 /* Restore GL states */
3322 if(alpha_test)
3323 StateGLEnable(&display->state_gl, GL_ALPHA_TEST);
3324 if(!blend)
3325 StateGLDisable(&display->state_gl, GL_BLEND);
3326 }
3327 #endif
3328 /* Draw progress foreground */
3329 SARImageDraw(
3330 display, progress_ptr->fg_image,
3331 xc, yc,
3332 (int)(w * progress_ptr->progress), h
3333 );
3334 break;
3335
3336 /* ******************************************************** */
3337 case SAR_MENU_OBJECT_TYPE_MESSAGE_BOX:
3338 mesgbox = SAR_MENU_MESSAGE_BOX(o);
3339
3340 x = (int)(mesgbox->x * width);
3341 y = (int)(mesgbox->y * height);
3342
3343 w = (int)(mesgbox->width * width);
3344 if(w <= 0)
3345 w = width - (2 * DEF_MB_XMARGIN);
3346 if(w <= 0)
3347 w = DEF_MB_XMARGIN;
3348
3349 if(mesgbox->height > 0)
3350 h = (int)(mesgbox->height * height);
3351 else
3352 h = DEF_HEIGHT;
3353 if(h <= 0)
3354 h = DEF_MB_YMARGIN;
3355
3356 xc = MAX(x - (w / 2), 0);
3357 yc = MAX(y - (h / 2), 0);
3358
3359 SARMenuDrawWindowBG(
3360 display, mesgbox->bg_image, NULL,
3361 xc, yc,
3362 w, h,
3363 True, /* Draw base */
3364 draw_shadows, /* Draw shadow */
3365 (Boolean)((draw_selected_rect && is_selected) ? True : False)
3366 );
3367
3368 GWGetFontSize(
3369 mesgbox->font,
3370 NULL, NULL,
3371 &fw, &fh
3372 );
3373
3374 GWSetFont(display, mesgbox->font);
3375 c = &mesgbox->color;
3376 if(mesgbox->sensitive)
3377 glColor4f(c->r, c->g, c->b, c->a);
3378 else
3379 glColor4f(
3380 c->r * 0.75f,
3381 c->g * 0.75f,
3382 c->b * 0.75f,
3383 c->a
3384 );
3385
3386 /* Has message to be drawn? */
3387 if(mesgbox->message != NULL)
3388 {
3389 Boolean actually_draw_line;
3390 const char *buf_ptr;
3391 int lines_processed = 0, lines_drawn = 0;
3392 int lines_to_skip = mesgbox->scrolled_line;
3393 int mesg_x, mesg_y,
3394 lines_visable, columns_visable, scroll_width;
3395 const sar_menu_color_struct *c_b = &mesgbox->bold_color,
3396 *c_u = &mesgbox->underline_color;
3397
3398 /* Calculate width (height) of scroll indicator */
3399 scroll_width = fh + (2 * DEF_MB_YMARGIN);
3400
3401 /* Calculate lines visable */
3402 if(fh > 0)
3403 lines_visable = (h - (2 * DEF_MB_YMARGIN)) / fh;
3404 else
3405 lines_visable = 0;
3406 if(lines_visable < 0)
3407 lines_visable = 0;
3408
3409 /* Calculate columns visable (include margin for arrows) */
3410 if(fw > 0)
3411 columns_visable = (w - DEF_SCROLL_CURSOR_WIDTH
3412 - (2 * DEF_MB_XMARGIN)) / fw;
3413 else
3414 columns_visable = 1;
3415 /* Must have atleast one column visible */
3416 if(columns_visable < 1)
3417 columns_visable = 1;
3418
3419 /* Draw scroll up and scroll down arrows */
3420 glRasterPos2i(
3421 xc + w - DEF_SCROLL_CURSOR_WIDTH - DEF_MB_XMARGIN,
3422 height - (yc + DEF_SCROLL_CURSOR_HEIGHT + DEF_MB_YMARGIN)
3423 );
3424 glBitmap(
3425 DEF_SCROLL_CURSOR_WIDTH,
3426 DEF_SCROLL_CURSOR_HEIGHT,
3427 0.0, 0.0,
3428 DEF_SCROLL_CURSOR_WIDTH, 0.0,
3429 scroll_cursor_up_bm
3430 );
3431 glRasterPos2i(
3432 xc + w - DEF_SCROLL_CURSOR_WIDTH - DEF_MB_XMARGIN,
3433 height - (y + (h / 2) - DEF_MB_YMARGIN)
3434 );
3435 glBitmap(
3436 DEF_SCROLL_CURSOR_WIDTH,
3437 DEF_SCROLL_CURSOR_HEIGHT,
3438 0.0, 0.0,
3439 DEF_SCROLL_CURSOR_WIDTH, 0.0,
3440 scroll_cursor_down_bm
3441 );
3442
3443 /* Get pointer to start of message buffer and begin
3444 * drawing lines.
3445 */
3446 buf_ptr = mesgbox->message;
3447 lines_processed = 0;
3448 mesg_x = xc + DEF_MB_XMARGIN;
3449 mesg_y = yc + DEF_MB_YMARGIN;
3450 do
3451 {
3452 actually_draw_line = (lines_processed >= lines_to_skip) ?
3453 True : False;
3454
3455 buf_ptr = SARMenuMessageBoxDrawString(
3456 display,
3457 mesg_x, mesg_y,
3458 buf_ptr,
3459 columns_visable, fw,
3460 mesgbox->sensitive,
3461 actually_draw_line,
3462 c, /* Foreground color */
3463 c_b, /* Bold color */
3464 c_u /* Underline color */
3465 );
3466 lines_processed++;
3467
3468 if(actually_draw_line)
3469 {
3470 lines_drawn++;
3471 mesg_y += fh;
3472 }
3473 }
3474 while((buf_ptr != NULL) && (lines_drawn < lines_visable));
3475 }
3476 break;
3477
3478 /* ******************************************************** */
3479 case SAR_MENU_OBJECT_TYPE_LIST:
3480 list = SAR_MENU_LIST(o);
3481
3482 x = (int)(list->x * width);
3483 y = (int)(list->y * height);
3484
3485 w = (int)(list->width * width);
3486 if(w <= 0)
3487 w = width - (2 * DEF_LIST_XMARGIN);
3488 if(w <= 0)
3489 w = DEF_LIST_XMARGIN;
3490
3491 if(list->height > 0)
3492 h = (int)(list->height * height);
3493 else
3494 h = DEF_HEIGHT;
3495 if(h <= 0)
3496 h = DEF_LIST_YMARGIN;
3497
3498 xc = MAX(x - (w / 2), 0);
3499 yc = MAX(y - (h / 2), 0);
3500
3501 SARMenuDrawWindowBG(
3502 display, list->bg_image, NULL,
3503 xc, yc,
3504 w, h,
3505 True, /* Draw base */
3506 draw_shadows, /* Draw shadow */
3507 (Boolean)((draw_selected_rect && is_selected) ? True : False)
3508 );
3509
3510 GWGetFontSize(
3511 list->font,
3512 NULL, NULL,
3513 &fw, &fh
3514 );
3515 /* Calculate items visible, remember to subtract three
3516 * items for borders and heading.
3517 */
3518 if(fh > 0)
3519 items_visable = MAX(
3520 (h / fh) - 3,
3521 0
3522 );
3523 else
3524 items_visable = 0;
3525 /* Update items visable on list */
3526 list->items_visable = items_visable;
3527
3528 /* Recalculate scroll position if too great */
3529 if((list->total_items - list->scrolled_item) <
3530 items_visable
3531 )
3532 list->scrolled_item = MAX(
3533 list->total_items - items_visable,
3534 0
3535 );
3536
3537 /* Calculate len as lines visable + yc */
3538 len = yc + h;
3539
3540 /* Calculate characters per row */
3541 if(fw > 0)
3542 chars_per_row = MAX(
3543 (w - DEF_SCROLL_CURSOR_WIDTH -
3544 (3 * DEF_LIST_XMARGIN)) / fw,
3545 1
3546 );
3547 else
3548 chars_per_row = 1;
3549
3550 /* Draw heading label */
3551 yc += DEF_LIST_YMARGIN;
3552 GWSetFont(display, list->font);
3553 c = &list->color;
3554 if(list->sensitive)
3555 glColor4f(c->r, c->g, c->b, c->a);
3556 else
3557 glColor4f(
3558 c->r * 0.75f,
3559 c->g * 0.75f,
3560 c->b * 0.75f,
3561 c->a
3562 );
3563 GWDrawString(
3564 display,
3565 xc + DEF_LIST_XMARGIN, yc,
3566 list->label
3567 );
3568 yc += fh;
3569
3570 /* Draw scroll up and down arrows */
3571 glRasterPos2i(
3572 xc + w - DEF_SCROLL_CURSOR_WIDTH - DEF_LIST_XMARGIN,
3573 height - (yc + DEF_SCROLL_CURSOR_HEIGHT)
3574 );
3575 glBitmap(
3576 DEF_SCROLL_CURSOR_WIDTH,
3577 DEF_SCROLL_CURSOR_HEIGHT,
3578 0.0, 0.0,
3579 DEF_SCROLL_CURSOR_WIDTH, 0.0,
3580 scroll_cursor_up_bm
3581 );
3582 glRasterPos2i(
3583 xc + w - DEF_SCROLL_CURSOR_WIDTH - DEF_LIST_XMARGIN,
3584 height - (y + (h / 2) - DEF_LIST_YMARGIN)
3585 );
3586 glBitmap(
3587 DEF_SCROLL_CURSOR_WIDTH,
3588 DEF_SCROLL_CURSOR_HEIGHT,
3589 0.0, 0.0,
3590 DEF_SCROLL_CURSOR_WIDTH, 0.0,
3591 scroll_cursor_down_bm
3592 );
3593
3594 /* Sanitize scrolled item position */
3595 if(list->scrolled_item < 0)
3596 list->scrolled_item = 0;
3597
3598 /* Draw each item */
3599 for(i = list->scrolled_item; i < list->total_items; i++)
3600 {
3601 #define item_name_len 256
3602 char item_name[item_name_len];
3603 sar_menu_list_item_struct *item = list->item[i];
3604 if((item != NULL) ? (item->name == NULL) : True)
3605 continue;
3606
3607 if((yc + fh) >= len)
3608 break;
3609
3610 /* Copy item name and shorten it as needed */
3611 strncpy(item_name, item->name, item_name_len);
3612 if(chars_per_row < item_name_len)
3613 item_name[chars_per_row] = '\0';
3614 else
3615 item_name[item_name_len - 1] = '\0';
3616
3617 /* Draw item name */
3618 GWDrawString(
3619 display,
3620 xc + (1 * fw) + DEF_LIST_XMARGIN,
3621 yc,
3622 item_name
3623 );
3624 /* If this item is selected then draw selection marker
3625 * in front of the item's name.
3626 */
3627 if(i == list->selected_item)
3628 GWDrawString(
3629 display,
3630 xc + DEF_LIST_XMARGIN, yc,
3631 ">"
3632 );
3633
3634 yc += fh;
3635 #undef item_name_len
3636 }
3637 break;
3638
3639 /* ******************************************************** */
3640 case SAR_MENU_OBJECT_TYPE_MDISPLAY:
3641 mdpy = SAR_MENU_MDISPLAY(o);
3642
3643 x = (int)(mdpy->x * width);
3644 y = (int)(mdpy->y * height);
3645
3646 w = (int)(mdpy->width * width);
3647 if(w <= 0)
3648 w = width - (2 * DEF_LIST_XMARGIN);
3649 if(w <= 0)
3650 w = DEF_LIST_XMARGIN;
3651
3652 if(mdpy->height > 0)
3653 h = (int)(mdpy->height * height);
3654 else
3655 h = DEF_HEIGHT;
3656 if(h <= 0)
3657 h = DEF_LIST_YMARGIN;
3658
3659 xc = MAX(x - (w / 2), 0);
3660 yc = MAX(y - (h / 2), 0);
3661
3662 SARMenuDrawWindowBG(
3663 display, mdpy->bg_image, NULL,
3664 xc, yc,
3665 w, h,
3666 True, /* Draw base */
3667 draw_shadows, /* Draw shadow */
3668 (Boolean)((draw_selected_rect && is_selected) ? True : False)
3669 );
3670
3671 if(mdpy->draw_cb != NULL)
3672 mdpy->draw_cb(
3673 display, /* Display */
3674 m, /* Menu */
3675 o, /* This Object */
3676 mdpy->id, /* ID Code */
3677 mdpy->client_data, /* Data */
3678 xc, yc, xc + w, yc + h
3679 );
3680 #if 0
3681 /* Draw outline if selected */
3682 if(draw_selected_rect && is_selected)
3683 {
3684 int x_min = x - (w / 2),
3685 x_max = x_min + w,
3686 y_min = y - (h / 2),
3687 y_max = y_min + h;
3688 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
3689 glBegin(GL_LINE_LOOP);
3690 {
3691 glVertex2i(x_min, height - y_min);
3692 glVertex2i(x_min, height - y_max);
3693 glVertex2i(x_max, height - y_max);
3694 glVertex2i(x_max, height - y_min);
3695 }
3696 glEnd();
3697 }
3698 #endif
3699 break;
3700
3701 /* ******************************************************** */
3702 case SAR_MENU_OBJECT_TYPE_SWITCH:
3703 sw = SAR_MENU_SWITCH(o);
3704 w = sw->width;
3705 h = sw->height;
3706
3707 GWGetFontSize(
3708 sw->font,
3709 NULL, NULL,
3710 &fw, &fh
3711 );
3712
3713 if(w <= 0)
3714 w = MAX(
3715 (2 * DEF_XMARGIN) + DEF_SWITCH_WIDTH,
3716 (2 * DEF_XMARGIN) + (STRLEN(sw->label) * fw)
3717 );
3718 if(h <= 0)
3719 h = (1 * DEF_YMARGIN) + DEF_SWITCH_HEIGHT +
3720 ((sw->label != NULL) ? fh : 0);
3721
3722 x = (int)(sw->x * width);
3723 y = (int)(sw->y * height);
3724
3725 image = sw->bg_image;
3726 DO_DRAW_IMAGE
3727
3728 if(sw->label != NULL)
3729 {
3730 const char *label = sw->label;
3731
3732 GWSetFont(display, sw->font);
3733 c = &sw->color;
3734 if(sw->sensitive)
3735 glColor4f(c->r, c->g, c->b, c->a);
3736 else
3737 glColor4f(
3738 c->r * 0.75f,
3739 c->g * 0.75f,
3740 c->b * 0.75f,
3741 c->a
3742 );
3743 GWDrawString(
3744 display,
3745 x - (w / 2) + DEF_XMARGIN,
3746 y - (h / 2) + DEF_SWITCH_HEIGHT,
3747 label
3748 );
3749 }
3750
3751 /* Check state of switch and choose the appropriate switch
3752 * image to draw.
3753 */
3754 if(sw->state)
3755 image = sw->switch_on_image;
3756 else
3757 image = sw->switch_off_image;
3758 SARImageDraw(
3759 display,
3760 image,
3761 x - (DEF_SWITCH_WIDTH / 2),
3762 y - (h / 2) + 2, /* Move down a little */
3763 DEF_SWITCH_WIDTH, DEF_SWITCH_HEIGHT
3764 );
3765
3766 /* Draw outline if selected */
3767 if(draw_selected_rect && is_selected)
3768 {
3769 int x_min = x - (w / 2) + 2,
3770 x_max = x_min + w - 4,
3771 y_min = y - (h / 2) + 2,
3772 y_max = y_min + h - 4;
3773 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
3774 glBegin(GL_LINE_LOOP);
3775 {
3776 glVertex2i(x_min, height - y_min);
3777 glVertex2i(x_min, height - y_max);
3778 glVertex2i(x_max, height - y_max);
3779 glVertex2i(x_max, height - y_min);
3780 }
3781 glEnd();
3782 }
3783 break;
3784
3785 /* ******************************************************** */
3786 case SAR_MENU_OBJECT_TYPE_SPIN:
3787 spin = SAR_MENU_SPIN(o);
3788
3789 GWGetFontSize(
3790 spin->font,
3791 NULL, NULL,
3792 &fw, &fh
3793 );
3794
3795 w = (int)(width * spin->width);
3796 h = (int)MAX(
3797 height * spin->height,
3798 (4 * DEF_YMARGIN) + fh
3799 );
3800
3801 x = (int)(width * spin->x);
3802 y = (int)(height * spin->y);
3803
3804 if((w > 0) && (h > 0))
3805 {
3806 int x_start = x - (w / 2),
3807 y_start = y - (h / 2),
3808 label_len = STRLEN(spin->label),
3809 label_width = (2 * DEF_XMARGIN) + (label_len * fw);
3810
3811 /* Draw label background */
3812 SARImageDraw(
3813 display,
3814 spin->label_image,
3815 x_start,
3816 y_start,
3817 label_width,
3818 h
3819 );
3820 GWSetFont(display, spin->font);
3821 c = &spin->label_color;
3822 if(spin->sensitive)
3823 glColor4f(c->r, c->g, c->b, c->a);
3824 else
3825 glColor4f(
3826 c->r * 0.75f,
3827 c->g * 0.75f,
3828 c->b * 0.75f,
3829 c->a
3830 );
3831 GWDrawString(
3832 display,
3833 x_start + DEF_XMARGIN,
3834 y - (fh / 2),
3835 spin->label
3836 );
3837
3838
3839 /* Begin drawing value just to the right of the label */
3840 GWSetFont(display, spin->value_font);
3841 GWGetFontSize(
3842 spin->value_font,
3843 NULL, NULL,
3844 &fw, &fh
3845 );
3846 /* Draw value background */
3847 SARImageDraw(
3848 display,
3849 spin->value_image,
3850 x_start + label_width - 1, /* Overlap one pixel to the left */
3851 y_start,
3852 MAX(w - label_width, 0),
3853 h
3854 );
3855
3856 /* Current spin value valid? */
3857 if((spin->cur_value >= 0) &&
3858 (spin->cur_value < spin->total_values)
3859 )
3860 {
3861 const char *value_ptr = (const char *)spin->value[
3862 spin->cur_value
3863 ];
3864 if(value_ptr != NULL)
3865 {
3866 int value_len = STRLEN(value_ptr),
3867 value_width = value_len * fw,
3868 value_twidth = w - label_width;
3869
3870 /* Draw outline around value if selected */
3871 if(draw_selected_rect && is_selected)
3872 {
3873 int x_min = x_start + label_width +
3874 (value_twidth / 2) - (value_width / 2) - 1,
3875 x_max = x_min + value_width + 2,
3876 y_min = y - (fh / 2) - 1,
3877 y_max = y_min + fh + 2;
3878 c = &spin->value_color;
3879 glColor4f(
3880 c->r * 0.5f,
3881 c->g * 0.5f,
3882 c->b * 0.5f,
3883 c->a
3884 );
3885 glBegin(GL_LINE_LOOP);
3886 {
3887 glVertex2i(x_min, height - y_min);
3888 glVertex2i(x_min, height - y_max);
3889 glVertex2i(x_max, height - y_max);
3890 glVertex2i(x_max, height - y_min);
3891 }
3892 glEnd();
3893 }
3894
3895 /* Draw value */
3896 c = &spin->value_color;
3897 if(spin->sensitive)
3898 glColor4f(c->r, c->g, c->b, c->a);
3899 else
3900 glColor4f(
3901 c->r * 0.75f,
3902 c->g * 0.75f,
3903 c->b * 0.75f,
3904 c->a
3905 );
3906 GWDrawString(
3907 display,
3908 x_start + label_width +
3909 (value_twidth / 2) - (value_width / 2),
3910 y - (fh / 2),
3911 value_ptr
3912 );
3913 }
3914 }
3915
3916 /* Draw decrement button */
3917 switch(spin->dec_state)
3918 {
3919 case SAR_MENU_BUTTON_STATE_UNARMED:
3920 case SAR_MENU_BUTTON_STATE_HIGHLIGHTED:
3921 image = spin->dec_unarmed_image;
3922 break;
3923 default:
3924 image = spin->dec_armed_image;
3925 break;
3926 }
3927 if(image != NULL)
3928 {
3929 int img_w = MIN(image->width, h),
3930 img_h = MIN(image->height, h);
3931 SARImageDraw(
3932 display, image,
3933 x_start + label_width - 1, /* Overlap one pixel to the left */
3934 y_start + (h / 2) - (img_h / 2),
3935 img_w, img_h
3936 );
3937 }
3938
3939 /* Draw increment button */
3940 switch(spin->inc_state)
3941 {
3942 case SAR_MENU_BUTTON_STATE_UNARMED:
3943 case SAR_MENU_BUTTON_STATE_HIGHLIGHTED:
3944 image = spin->inc_unarmed_image;
3945 break;
3946 default:
3947 image = spin->inc_armed_image;
3948 break;
3949 }
3950 if(image != NULL)
3951 {
3952 int img_w = MIN(image->width, h),
3953 img_h = MIN(image->height, h);
3954 SARImageDraw(
3955 display, image,
3956 x_start + w - h,
3957 y_start + (h / 2) - (img_h / 2),
3958 img_w, img_h
3959 );
3960 }
3961 #if 0
3962 /* Draw spin left arrow? */
3963 if(spin->allow_warp ? True :
3964 (spin->cur_value > 0)
3965 )
3966 {
3967 glRasterPos2i(
3968 x_start + label_width + (3 * DEF_XMARGIN),
3969 height - (y_start + (h / 2) -
3970 (DEF_SCROLL_CURSOR_HEIGHT / 2) +
3971 DEF_SCROLL_CURSOR_HEIGHT
3972 )
3973 );
3974 glBitmap(
3975 DEF_SCROLL_CURSOR_WIDTH,
3976 DEF_SCROLL_CURSOR_HEIGHT,
3977 0.0, 0.0,
3978 DEF_SCROLL_CURSOR_WIDTH, 0.0,
3979 scroll_cursor_left_bm
3980 );
3981 }
3982 /* Draw spin right arrow? */
3983 if(spin->allow_warp ? True :
3984 (spin->cur_value < (spin->total_values - 1))
3985 )
3986 {
3987 glRasterPos2i(
3988 x_start + w - (3 * DEF_XMARGIN) -
3989 DEF_SCROLL_CURSOR_WIDTH,
3990 height - (y_start + (h / 2) -
3991 (DEF_SCROLL_CURSOR_HEIGHT / 2) +
3992 DEF_SCROLL_CURSOR_HEIGHT
3993 )
3994 );
3995 glBitmap(
3996 DEF_SCROLL_CURSOR_WIDTH,
3997 DEF_SCROLL_CURSOR_HEIGHT,
3998 0.0, 0.0,
3999 DEF_SCROLL_CURSOR_WIDTH, 0.0,
4000 scroll_cursor_right_bm
4001 );
4002 }
4003 #endif
4004 #if 0
4005 /* Draw outline if selected */
4006 if(draw_selected_rect && is_selected)
4007 {
4008 int x_min = x - (w / 2),
4009 x_max = x_min + w,
4010 y_min = y - (h / 2),
4011 y_max = y_min + h;
4012 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
4013 glBegin(GL_LINE_LOOP);
4014 {
4015 glVertex2i(x_min, height - y_min);
4016 glVertex2i(x_min, height - y_max);
4017 glVertex2i(x_max, height - y_max);
4018 glVertex2i(x_max, height - y_min);
4019 }
4020 glEnd();
4021 }
4022 #endif
4023 }
4024 break;
4025
4026 /* ******************************************************** */
4027 case SAR_MENU_OBJECT_TYPE_SLIDER:
4028 slider = SAR_MENU_SLIDER(o);
4029
4030 GWGetFontSize(
4031 slider->font,
4032 NULL, NULL,
4033 &fw, &fh
4034 );
4035
4036 w = (int)(width * slider->width);
4037 h = (int)MAX(
4038 height * slider->height,
4039 (4 * DEF_YMARGIN) + fh
4040 );
4041
4042 x = (int)(width * slider->x);
4043 y = (int)(height * slider->y);
4044
4045 if((w > 0) && (h > 0))
4046 {
4047 int x_start = x - (w / 2),
4048 y_start = y - (h / 2),
4049 label_len = STRLEN(slider->label),
4050 label_width = (4 * DEF_XMARGIN) + (label_len * fw);
4051
4052 /* Draw label background */
4053 SARImageDraw(
4054 display,
4055 slider->label_image,
4056 x_start,
4057 y_start,
4058 label_width,
4059 h
4060 );
4061 GWSetFont(display, slider->font);
4062 c = &slider->label_color;
4063 if(slider->sensitive)
4064 glColor4f(c->r, c->g, c->b, c->a);
4065 else
4066 glColor4f(
4067 c->r * 0.75f,
4068 c->g * 0.75f,
4069 c->b * 0.75f,
4070 c->a
4071 );
4072 GWDrawString(
4073 display,
4074 x_start + DEF_XMARGIN,
4075 y - (fh / 2),
4076 slider->label
4077 );
4078
4079 /* Draw trough background */
4080 SARImageDraw(
4081 display,
4082 slider->trough_image,
4083 x_start + label_width - 1, /* Overlap one pixel to the left */
4084 y_start,
4085 MAX(w - label_width, 0),
4086 h
4087 );
4088
4089 /* Draw handle */
4090 image = slider->handle_image;
4091 if(image != NULL)
4092 {
4093 int trough_range = MAX(
4094 w - label_width - (2 * DEF_XMARGIN),
4095 0
4096 );
4097 int handle_x = x_start + label_width - 1 +
4098 DEF_XMARGIN - (image->width / 2);
4099 int handle_y = y_start + (h / 2) -
4100 (image->height / 2);
4101 float vrange = slider->upper - slider->lower;
4102 float vc = (vrange > 0.0f) ?
4103 (slider->value / vrange) : 0.0f;
4104
4105 handle_x += (int)(vc * trough_range);
4106 if((handle_x + image->width + 1) > (x_start - 1 + w))
4107 handle_x = (x_start - 1 + w) - (image->width + 1);
4108
4109 SARImageDraw(
4110 display,
4111 image,
4112 handle_x, handle_y,
4113 image->width, image->height
4114 );
4115 }
4116
4117 /* Draw outline if selected */
4118 if(draw_selected_rect && is_selected)
4119 {
4120 int x_min = x - (w / 2) + 2,
4121 x_max = x_min + w - 4,
4122 y_min = y - (h / 2) + 2,
4123 y_max = y_min + h - 4;
4124 glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
4125 glBegin(GL_LINE_LOOP);
4126 {
4127 glVertex2i(x_min, height - y_min);
4128 glVertex2i(x_min, height - y_max);
4129 glVertex2i(x_max, height - y_max);
4130 glVertex2i(x_max, height - y_min);
4131 }
4132 glEnd();
4133 }
4134 }
4135 break;
4136
4137 /* ******************************************************** */
4138 case SAR_MENU_OBJECT_TYPE_MAP:
4139 map = SAR_MENU_MAP(o);
4140
4141 /* Draw map object with its own drawing function first */
4142 SARMenuMapDraw(display, m, map, n);
4143
4144 /* Calculate map object geometry for window frame drawing */
4145 x = (int)(map->x * width);
4146 y = (int)(map->y * height);
4147
4148 /* Calculate size to be one pixel bigger (to ensure cover) */
4149 w = (int)(map->width * width) + 2;
4150 h = (int)(map->height * height) + 2;
4151
4152 xc = MAX(x - (w / 2) - 1, 0);
4153 yc = MAX(y - (h / 2) - 1, 0);
4154
4155 SARMenuDrawWindowBG(
4156 display, map->bg_image, NULL,
4157 xc, yc,
4158 w, h,
4159 False, /* Do not draw base */
4160 draw_shadows, /* Draw shadow */
4161 (Boolean)((draw_selected_rect && is_selected) ? True : False)
4162 );
4163 break;
4164
4165 /* ******************************************************** */
4166 case SAR_MENU_OBJECT_TYPE_OBJVIEW:
4167 objview = SAR_MENU_OBJVIEW(o);
4168
4169 /* Calculate 3d object viewer object geometry for window
4170 * frame drawing.
4171 */
4172 x = (int)(objview->x * width);
4173 y = (int)(objview->y * height);
4174
4175 /* Calculate size to be one pixel bigger (to ensure cover) */
4176 w = (int)(objview->width * width) + 2;
4177 h = (int)(objview->height * height) + 2;
4178
4179 xc = MAX(x - (w / 2) - 1, 0);
4180 yc = MAX(y - (h / 2) - 1, 0);
4181
4182 SARMenuDrawWindowBG(
4183 display, objview->bg_image, &objview->bg_color,
4184 xc, yc,
4185 w, h,
4186 True, /* Draw base */
4187 draw_shadows, /* Draw shadow */
4188 (Boolean)((draw_selected_rect && is_selected) ? True : False)
4189 );
4190
4191 /* Draw buffered 3d object image, this image has an alpha
4192 * channel so it should be drawn over the base of the
4193 * window background drawn above.
4194 */
4195 if(objview->objimg != NULL)
4196 {
4197 sar_image_struct tmp_img;
4198 float aspect = (float)((objview->objimg_width > 0) ?
4199 ((float)objview->objimg_height /
4200 (float)objview->objimg_width) : 0.75
4201 );
4202 int draw_width = w,
4203 draw_height = (int)(w * aspect);
4204
4205 if((draw_height > h) && (aspect > 0.0f))
4206 {
4207 draw_width = (int)(h / aspect);
4208 draw_height = h;
4209 }
4210
4211 tmp_img.width = objview->objimg_width;
4212 tmp_img.height = objview->objimg_height;
4213 tmp_img.data = objview->objimg;
4214
4215 StateGLEnable(&display->state_gl, GL_SCISSOR_TEST);
4216 StateGLScissor(
4217 &display->state_gl,
4218 xc + DEF_MB_XMARGIN,
4219 height - yc - h + DEF_MB_YMARGIN,
4220 MAX(w - (2 * DEF_MB_XMARGIN), DEF_MB_XMARGIN),
4221 MAX(h - (2 * DEF_MB_YMARGIN), DEF_MB_YMARGIN)
4222 );
4223 if(objview->show_message)
4224 SARImageDraw(
4225 display, &tmp_img,
4226 MAX(x + (w / 2) - draw_width, 0),
4227 MAX(y - (draw_height / 2), 0),
4228 draw_width, draw_height
4229 );
4230 else
4231 SARImageDraw(
4232 display, &tmp_img,
4233 MAX(x - (draw_width / 2), 0),
4234 MAX(y - (draw_height / 2), 0),
4235 draw_width, draw_height
4236 );
4237 StateGLDisable(&display->state_gl, GL_SCISSOR_TEST);
4238 }
4239
4240 /* Begin drawing message */
4241
4242 GWGetFontSize(
4243 objview->font,
4244 NULL, NULL,
4245 &fw, &fh
4246 );
4247 GWSetFont(display, objview->font);
4248
4249 /* Draw message? */
4250 if((objview->message != NULL) && objview->show_message)
4251 {
4252 int draw_x = xc + DEF_MB_XMARGIN,
4253 draw_y = yc + DEF_MB_YMARGIN;
4254 const char *buf_ptr = objview->message;
4255 const sar_menu_color_struct *c_b = &objview->bold_color,
4256 *c_u = &objview->underline_color;
4257
4258 c = &objview->color;
4259 if(objview->sensitive)
4260 glColor4f(c->r, c->g, c->b, c->a);
4261 else
4262 glColor4f(
4263 c->r * 0.75f,
4264 c->g * 0.75f,
4265 c->b * 0.75f,
4266 c->a
4267 );
4268
4269 #define DO_DRAW_LINE_COLORED \
4270 { \
4271 const char *s = buf_ptr; \
4272 int sx = draw_x, sy = draw_y; \
4273 while((*s != '\n') && (*s != '\0')) \
4274 { \
4275 if(IS_CHAR_ESC_START(*s)) \
4276 { \
4277 s++; \
4278 if(strcasepfx(s, "bold")) \
4279 glColor4f(c_b->r, c_b->g, c_b->b, c_b->a); \
4280 else if(strcasepfx(s, "underline")) \
4281 glColor4f(c_u->r, c_u->g, c_u->b, c_u->a); \
4282 else if(strcasepfx(s, "default")) \
4283 glColor4f(c->r, c->g, c->b, c->a); \
4284 while(!IS_CHAR_ESC_END(*s) && (*s != '\0')) \
4285 s++; \
4286 if(*s != '\0') \
4287 s++; \
4288 } \
4289 else \
4290 { \
4291 GWDrawCharacter(display, sx, sy, *s); \
4292 s++; sx += fw; \
4293 } \
4294 } \
4295 if(*s == '\n') \
4296 s++; \
4297 buf_ptr = s; \
4298 }
4299
4300 /* Begin drawing each line, draw in a style similar to
4301 * the message box.
4302 */
4303 do
4304 {
4305 if(draw_y >= (yc + h - (2 * DEF_MB_YMARGIN)))
4306 break;
4307
4308 DO_DRAW_LINE_COLORED
4309 draw_y += fh;
4310
4311 } while(buf_ptr != NULL);
4312 #undef DO_DRAW_LINE_COLORED
4313 }
4314
4315 if(objview->objimg != NULL)
4316 {
4317 const char *s =
4318 "(Button1 + DRAG = Heading & Pitch Button3 + DRAG = Bank)";
4319 int draw_x = x - (STRLEN(s) * fw / 2),
4320 draw_y = yc + h - DEF_MB_YMARGIN - fh;
4321
4322 c = &objview->color;
4323 if(objview->sensitive)
4324 glColor4f(c->r, c->g, c->b, c->a);
4325 else
4326 glColor4f(
4327 c->r * 0.75f,
4328 c->g * 0.75f,
4329 c->b * 0.75f,
4330 c->a
4331 );
4332
4333 GWDrawString(
4334 display, draw_x, draw_y, s
4335 );
4336 }
4337 break;
4338
4339 }
4340 #undef DO_DRAW_IMAGE
4341 }
4342
4343
4344 /*
4345 * Draws the specified object n (but not its shadow).
4346 */
SARMenuDrawObject(gw_display_struct * display,sar_menu_struct * m,int n)4347 void SARMenuDrawObject(
4348 gw_display_struct *display, sar_menu_struct *m,
4349 int n /* Object number on m */
4350 )
4351 {
4352 SARMenuDoDrawObject(display, m, n, False);
4353 }
4354
4355 /*
4356 * Draws the specified menu m.
4357 *
4358 * Does not swap the GW buffers.
4359 */
SARMenuDrawAll(gw_display_struct * display,sar_menu_struct * m)4360 void SARMenuDrawAll(
4361 gw_display_struct *display,
4362 sar_menu_struct *m
4363 )
4364 {
4365 int i, width, height;
4366
4367 if((display == NULL) || (m == NULL))
4368 return;
4369
4370 /* Set up gl state for 2d drawing */
4371 GWOrtho2D(display);
4372
4373 GWContextGet(
4374 display, GWContextCurrent(display),
4375 NULL, NULL,
4376 NULL, NULL,
4377 &width, &height
4378 );
4379
4380 /* Draw background image */
4381 if(m->bg_image != NULL)
4382 {
4383 /* Draw to the size of the frame buffer, thus clearing it */
4384 SARImageDraw(
4385 display,
4386 m->bg_image,
4387 0, 0,
4388 width, height
4389 );
4390 }
4391 else
4392 {
4393 glClearColor(1.0f, 1.0f, 1.0f, 0.0f);
4394 glClearDepth(1.0f);
4395 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4396 }
4397
4398 /* Draw each object (with shadows) */
4399 for(i = 0; i < m->total_objects; i++)
4400 SARMenuDoDrawObject(display, m, i, True);
4401 }
4402
4403
4404 /*
4405 * Manages a pointer event assumed for the given menu.
4406 */
SARMenuManagePointer(gw_display_struct * display,sar_menu_struct * m,int x,int y,gw_event_type type,int btn_num)4407 int SARMenuManagePointer(
4408 gw_display_struct *display, sar_menu_struct *m,
4409 int x, int y, gw_event_type type, int btn_num
4410 )
4411 {
4412 int i, events_handled = 0;
4413 int xp, yp, w, h;
4414 int x_min, x_max, y_min, y_max, width, height;
4415 void *o;
4416 sar_menu_button_struct *button;
4417 sar_menu_message_box_struct *mesgbox;
4418 sar_menu_list_struct *list;
4419 sar_menu_mdisplay_struct *mdpy;
4420 sar_menu_switch_struct *sw;
4421 sar_menu_spin_struct *spin;
4422 sar_menu_slider_struct *slider;
4423 sar_menu_map_struct *map;
4424 sar_menu_objview_struct *objview;
4425
4426
4427 if((display == NULL) || (m == NULL))
4428 return(events_handled);
4429
4430 GWContextGet(
4431 display, GWContextCurrent(display),
4432 NULL, NULL,
4433 NULL, NULL,
4434 &width, &height
4435 );
4436
4437 /* Iterate through all menu object/widgets */
4438 for(i = 0; i < m->total_objects; i++)
4439 {
4440 o = m->object[i];
4441 if(o == NULL)
4442 continue;
4443
4444 switch(SAR_MENU_OBJECT_TYPE(o))
4445 {
4446 /* ***************************************************** */
4447 case SAR_MENU_OBJECT_TYPE_BUTTON:
4448 button = SAR_MENU_BUTTON(o);
4449 if(!button->sensitive)
4450 break;
4451
4452 xp = (int)(button->x * width) + button->offset_x;
4453 yp = (int)(button->y * height) + button->offset_y;
4454 w = button->width;
4455 h = button->height;
4456
4457 /* Calculate coordinate bounds */
4458 x_min = (int)MAX(xp - (w / 2), 0);
4459 x_max = (int)MAX(x_min + w, w);
4460 y_min = (int)MAX(yp - (h / 2), 0);
4461 y_max = (int)MAX(y_min + h, h);
4462
4463 /* Event in bounds? */
4464 if((events_handled <= 0) &&
4465 (x >= x_min) && (x < x_max) &&
4466 (y >= y_min) && (y < y_max)
4467 )
4468 {
4469 /* Handle by event type */
4470 switch(type)
4471 {
4472 case GWEventTypePointerMotion:
4473 if(button->state == SAR_MENU_BUTTON_STATE_UNARMED)
4474 {
4475 button->state = SAR_MENU_BUTTON_STATE_HIGHLIGHTED;
4476 events_handled++;
4477 DO_REDRAW_OBJECT(display, m, i)
4478 }
4479 break;
4480
4481 case GWEventTypeButtonPress:
4482 events_handled++;
4483 /* Select new object as needed and redraw the
4484 * previously selected object
4485 */
4486 if(m->selected_object != i)
4487 {
4488 int po = m->selected_object;
4489 m->selected_object = i;
4490 if(m->always_full_redraw)
4491 SARMenuDrawAll(display, m);
4492 else
4493 SARMenuDrawObject(display, m, po);
4494 }
4495 /* Set button to armed state as appropriate */
4496 if((button->state != SAR_MENU_BUTTON_STATE_ARMED) &&
4497 (btn_num == 1)
4498 )
4499 {
4500 button->state = SAR_MENU_BUTTON_STATE_ARMED;
4501 DO_REDRAW_OBJECT(display, m, i)
4502 }
4503 else
4504 {
4505 GWSwapBuffer(display);
4506 }
4507 break;
4508
4509 case GWEventTypeButtonRelease:
4510 events_handled++;
4511 /* Select new object as needed and redraw the
4512 * previously selected object
4513 */
4514 if(m->selected_object != i)
4515 {
4516 int po = m->selected_object;
4517 m->selected_object = i;
4518 if(m->always_full_redraw)
4519 SARMenuDrawAll(display, m);
4520 else
4521 SARMenuDrawObject(display, m, po);
4522 }
4523 /* Set button back to highlighted state if it
4524 * was armed and call the button's click
4525 * callback
4526 */
4527 if(button->state == SAR_MENU_BUTTON_STATE_ARMED)
4528 {
4529 button->state = SAR_MENU_BUTTON_STATE_HIGHLIGHTED;
4530 if(m->always_full_redraw)
4531 SARMenuDrawAll(display, m);
4532 else
4533 SARMenuDrawObject(display, m, i);
4534
4535 if(button->func_cb != NULL)
4536 {
4537 int n;
4538 sar_menu_button_struct *button2;
4539
4540 /* Set all other buttons on this menu to
4541 * unarmed.
4542 */
4543 for(n = 0; n < m->total_objects; n++)
4544 {
4545 o = m->object[n];
4546 if(SAR_MENU_IS_BUTTON(o))
4547 button2 = SAR_MENU_BUTTON(o);
4548 else
4549 continue;
4550 if(button == button2)
4551 continue;
4552
4553 if(button2->state != SAR_MENU_BUTTON_STATE_UNARMED)
4554 {
4555 button2->state = SAR_MENU_BUTTON_STATE_UNARMED;
4556 if(m->always_full_redraw)
4557 SARMenuDrawAll(display, m);
4558 else
4559 SARMenuDrawObject(display, m, n);
4560 }
4561 }
4562
4563 GWSwapBuffer(display);
4564
4565 /* Call callback function */
4566 button->func_cb(
4567 button, /* Object */
4568 button->id, /* ID Code */
4569 button->client_data /* Data */
4570 );
4571 }
4572 else
4573 {
4574 GWSwapBuffer(display);
4575 }
4576 }
4577 break;
4578
4579 case GWEventType2ButtonPress:
4580 case GWEventType3ButtonPress:
4581 break;
4582 }
4583 }
4584 else
4585 {
4586 /* Pointer event out of bounds */
4587 switch(type)
4588 {
4589 case GWEventTypeButtonPress:
4590 break;
4591 case GWEventTypeButtonRelease:
4592 case GWEventTypePointerMotion:
4593 if(button->state != SAR_MENU_BUTTON_STATE_UNARMED)
4594 {
4595 button->state = SAR_MENU_BUTTON_STATE_UNARMED;
4596 DO_REDRAW_OBJECT(display, m, i)
4597 }
4598 break;
4599 case GWEventType2ButtonPress:
4600 case GWEventType3ButtonPress:
4601 break;
4602 }
4603 }
4604 break;
4605
4606 /* ***************************************************** */
4607 case SAR_MENU_OBJECT_TYPE_MESSAGE_BOX:
4608 mesgbox = SAR_MENU_MESSAGE_BOX(o);
4609 if(!mesgbox->sensitive)
4610 break;
4611
4612 w = (int)(mesgbox->width * width);
4613 if(w <= 0)
4614 w = (int)(width - (2 * DEF_MB_XMARGIN));
4615 if(w <= 0)
4616 w = DEF_MB_XMARGIN;
4617
4618 if(mesgbox->height > 0)
4619 h = (int)(mesgbox->height * height);
4620 else
4621 h = DEF_HEIGHT;
4622 if(h <= 0)
4623 h = DEF_MB_YMARGIN;
4624
4625 /* Get coordinate bounds */
4626 x_min = (int)((mesgbox->x * width) - (w / 2));
4627 x_max = (int)(x_min + w);
4628 y_min = (int)((mesgbox->y * height) - (h / 2));
4629 y_max = (int)(y_min + h);
4630
4631 /* Pointer event in bounds? */
4632 if((events_handled <= 0) &&
4633 (x >= x_min) && (x < x_max) &&
4634 (y >= y_min) && (y < y_max) &&
4635 (mesgbox->message != NULL) &&
4636 (type == GWEventTypeButtonPress)
4637 )
4638 {
4639 int fh, fw;
4640 int lines_visable, columns_visable,
4641 total_lines, scroll_width;
4642
4643 events_handled++;
4644
4645 /* Select new object as needed and redraw the
4646 * previously selected object.
4647 */
4648 if(m->selected_object != i)
4649 {
4650 int po = m->selected_object;
4651 m->selected_object = i;
4652 if(m->always_full_redraw)
4653 SARMenuDrawAll(display, m);
4654 else
4655 SARMenuDrawObject(display, m, po);
4656 }
4657
4658 GWGetFontSize(
4659 mesgbox->font,
4660 NULL, NULL,
4661 &fw, &fh
4662 );
4663
4664 /* Calculate colums visable */
4665 if(fw > 0)
4666 columns_visable = (w - DEF_SCROLL_CURSOR_WIDTH
4667 - (2 * DEF_MB_XMARGIN)) / fw;
4668 else
4669 columns_visable = 1;
4670 if(columns_visable < 1)
4671 columns_visable = 1;
4672
4673 /* Calculate width (height) of scroll indicator */
4674 scroll_width = fh + (2 * DEF_MB_YMARGIN);
4675
4676 /* Calculate lines visable */
4677 if(fh > 0)
4678 lines_visable = (h - (2 * DEF_MB_YMARGIN)) / fh;
4679 else
4680 lines_visable = 0;
4681 if(lines_visable < 0)
4682 lines_visable = 0;
4683
4684 /* Calculate total number of lines */
4685 total_lines = SARMenuMessageBoxTotalLines(
4686 mesgbox->message, columns_visable
4687 );
4688
4689 /* Let's make scrolling simple, check if y is above
4690 * or below the midpoint.
4691 */
4692 if(y < (mesgbox->y * height))
4693 {
4694 /* Scroll up */
4695 mesgbox->scrolled_line--;
4696 }
4697 else
4698 {
4699 /* Scroll down */
4700 mesgbox->scrolled_line++;
4701 }
4702
4703 if(mesgbox->scrolled_line >
4704 (total_lines - (lines_visable / 2))
4705 )
4706 mesgbox->scrolled_line = total_lines -
4707 (lines_visable / 2);
4708 if(mesgbox->scrolled_line < 0)
4709 mesgbox->scrolled_line = 0;
4710
4711 DO_REDRAW_OBJECT(display, m, i)
4712 }
4713 break;
4714
4715 /* ***************************************************** */
4716 case SAR_MENU_OBJECT_TYPE_LIST:
4717 list = SAR_MENU_LIST(o);
4718 if(!list->sensitive)
4719 break;
4720
4721 w = (int)(list->width * width);
4722 if(w <= 0)
4723 w = width - (2 * DEF_LIST_XMARGIN);
4724 if(w <= 0)
4725 w = DEF_LIST_XMARGIN;
4726
4727 if(list->height > 0)
4728 h = (int)(list->height * height);
4729 else
4730 h = DEF_HEIGHT;
4731 if(h <= 0)
4732 h = DEF_LIST_YMARGIN;
4733
4734 /* Calculate coordinate bounds */
4735 x_min = (int)((list->x * width) - (w / 2));
4736 x_max = (int)(x_min + w);
4737 y_min = (int)((list->y * height) - (h / 2));
4738 y_max = (int)(y_min + h);
4739
4740 /* Event in bounds? */
4741 if((events_handled <= 0) &&
4742 (x >= x_min) && (x < x_max) &&
4743 (y >= y_min) && (y < y_max)
4744 )
4745 {
4746 int fh, fw, items_visible;
4747 int scroll = 0;
4748
4749 GWGetFontSize(
4750 list->font,
4751 NULL, NULL,
4752 &fw, &fh
4753 );
4754 /* Calculate items visible, remember to subtract
4755 * three items for borders and heading
4756 */
4757 if(fh > 0)
4758 items_visible = MAX(
4759 (h / fh) - 3,
4760 0
4761 );
4762 else
4763 items_visible = 0;
4764
4765 /* Update items visable on list */
4766 list->items_visable = items_visible;
4767
4768 /* Determine if we need to scroll up or down
4769 * depending on the location of the event
4770 */
4771 if(x >= (x_max - DEF_SCROLL_CURSOR_WIDTH - DEF_LIST_XMARGIN))
4772 {
4773 if(y < (y_min + DEF_SCROLL_CURSOR_HEIGHT + fh + DEF_LIST_YMARGIN))
4774 scroll = 1;
4775 else if(y >= (y_max - DEF_SCROLL_CURSOR_HEIGHT - DEF_LIST_YMARGIN))
4776 scroll = 2;
4777 }
4778
4779 /* Handle by event type */
4780 switch(type)
4781 {
4782 case GWEventTypeButtonPress:
4783 events_handled++;
4784
4785 /* Select new object as needed and redraw the
4786 * previously selected object
4787 */
4788 if(m->selected_object != i)
4789 {
4790 int po = m->selected_object;
4791 m->selected_object = i;
4792 if(m->always_full_redraw)
4793 SARMenuDrawAll(display, m);
4794 else
4795 SARMenuDrawObject(display, m, po);
4796 }
4797
4798 /* Scroll up? */
4799 if(scroll == 1)
4800 {
4801 list->scrolled_item -= MAX(
4802 items_visible - 1,
4803 1
4804 );
4805 if(list->scrolled_item < 0)
4806 list->scrolled_item = 0;
4807
4808 DO_REDRAW_OBJECT(display, m, i)
4809 }
4810 /* Scroll down? */
4811 else if(scroll == 2)
4812 {
4813 list->scrolled_item += MAX(
4814 items_visible - 1,
4815 1
4816 );
4817 if(list->scrolled_item >=
4818 (list->total_items - (items_visible / 2))
4819 )
4820 list->scrolled_item =
4821 list->total_items -
4822 (items_visible / 2);
4823 if(list->scrolled_item < 0)
4824 list->scrolled_item = 0;
4825
4826 DO_REDRAW_OBJECT(display, m, i)
4827 }
4828 else
4829 {
4830 /* Match selection */
4831 int sel_num, prev_sel_num;
4832
4833 /* Calculate selection position, remember
4834 * to - 1 to account for the heading
4835 * which should not be selected
4836 */
4837 if(fh > 0)
4838 sel_num = list->scrolled_item +
4839 ((y - DEF_LIST_YMARGIN - fh - y_min) / fh);
4840 else
4841 sel_num = -1;
4842
4843 /* Sanitize selection */
4844 if(sel_num < -1)
4845 sel_num = -1;
4846 if(sel_num >= list->total_items)
4847 sel_num = list->total_items - 1;
4848
4849 /* Record previously selected item and set
4850 * new selected item
4851 */
4852 prev_sel_num = list->selected_item;
4853 list->selected_item = sel_num;
4854
4855 DO_REDRAW_OBJECT(display, m, i)
4856
4857 /* Call select callback */
4858 if((list->select_cb != NULL) &&
4859 (prev_sel_num != sel_num) &&
4860 (sel_num >= 0) &&
4861 (sel_num < list->total_items)
4862 )
4863 {
4864 sar_menu_list_item_struct *item = list->item[sel_num];
4865 if(item != NULL)
4866 list->select_cb(
4867 list, /* This Object */
4868 list->id, /* ID Code */
4869 list->client_data, /* Data */
4870 sel_num, /* Item Number */
4871 item, /* Item Pointer */
4872 item->client_data /* Item Data */
4873 );
4874 }
4875 }
4876 break;
4877
4878 case GWEventTypeButtonRelease:
4879 break;
4880
4881 case GWEventTypePointerMotion:
4882 break;
4883
4884 case GWEventType2ButtonPress:
4885 events_handled++;
4886
4887 /* No scroll? */
4888 if(scroll == 0)
4889 {
4890 int sel_num = list->selected_item;
4891
4892 /* Call activate callback */
4893 if((list->activate_cb != NULL) &&
4894 (sel_num >= 0) &&
4895 (sel_num < list->total_items)
4896 )
4897 {
4898 sar_menu_list_item_struct *item = list->item[sel_num];
4899 if(item != NULL)
4900 list->activate_cb(
4901 list, /* This Object */
4902 list->id, /* ID Code */
4903 list->client_data, /* Data */
4904 sel_num, /* Item Number */
4905 item, /* Item Pointer */
4906 item->client_data /* Item Data */
4907 );
4908 }
4909 }
4910 break;
4911
4912 case GWEventType3ButtonPress:
4913 break;
4914 }
4915 }
4916 break;
4917
4918 /* ***************************************************** */
4919 case SAR_MENU_OBJECT_TYPE_MDISPLAY:
4920 mdpy = SAR_MENU_MDISPLAY(o);
4921 if(!mdpy->sensitive)
4922 break;
4923
4924 w = (int)(mdpy->width * width);
4925 if(w <= 0)
4926 w = width - (2 * DEF_LIST_XMARGIN);
4927 if(w <= 0)
4928 w = DEF_LIST_XMARGIN;
4929
4930 if(mdpy->height > 0)
4931 h = (int)(mdpy->height * height);
4932 else
4933 h = DEF_HEIGHT;
4934 if(h <= 0)
4935 h = DEF_LIST_YMARGIN;
4936
4937 /* Get coordinate bounds */
4938 x_min = (int)((mdpy->x * width) - (w / 2));
4939 x_max = (int)(x_min + w);
4940 y_min = (int)((mdpy->y * height) - (h / 2));
4941 y_max = (int)(y_min + h);
4942
4943 /* Pointer event in bounds? */
4944 if((events_handled <= 0) &&
4945 (x >= x_min) && (x < x_max) &&
4946 (y >= y_min) && (y < y_max)
4947 )
4948 {
4949 switch(type)
4950 {
4951 case GWEventTypeButtonPress:
4952 events_handled++;
4953
4954 /* Select new object as needed and redraw the
4955 * previously selected object.
4956 */
4957 if(m->selected_object != i)
4958 {
4959 int po = m->selected_object;
4960 m->selected_object = i;
4961 if(m->always_full_redraw)
4962 SARMenuDrawAll(display, m);
4963 else
4964 SARMenuDrawObject(display, m, po);
4965 }
4966
4967 DO_REDRAW_OBJECT(display, m, i)
4968 break;
4969
4970 case GWEventTypeButtonRelease:
4971 case GWEventTypePointerMotion:
4972 case GWEventType2ButtonPress:
4973 case GWEventType3ButtonPress:
4974 break;
4975 }
4976 }
4977 break;
4978
4979 /* ***************************************************** */
4980 case SAR_MENU_OBJECT_TYPE_SWITCH:
4981 sw = SAR_MENU_SWITCH(o);
4982 if(sw->sensitive)
4983 {
4984 int fw, fh;
4985 const char *label = sw->label;
4986
4987 w = sw->width;
4988 h = sw->height;
4989
4990 GWGetFontSize(
4991 sw->font,
4992 NULL, NULL,
4993 &fw, &fh
4994 );
4995
4996 /* Calculate size of switch area */
4997 if(w <= 0)
4998 w = DEF_SWITCH_WIDTH;
4999 if(h <= 0)
5000 h = DEF_YMARGIN + DEF_SWITCH_HEIGHT +
5001 ((label != NULL) ? fh : 0);
5002
5003 /* Get coordinate bounds for switch area */
5004 x_min = (int)((sw->x * width) - (w / 2));
5005 x_max = (int)(x_min + DEF_SWITCH_WIDTH);
5006 y_min = (int)((sw->y * height) - (h / 2) + 2);
5007 y_max = (int)(y_min + DEF_SWITCH_HEIGHT);
5008
5009 /* Pointer event in bounds? */
5010 if((events_handled <= 0) &&
5011 (x >= x_min) && (x < x_max) &&
5012 (y >= y_min) && (y < y_max)
5013 )
5014 {
5015 switch(type)
5016 {
5017 case GWEventTypeButtonPress:
5018 break;
5019
5020 case GWEventTypeButtonRelease:
5021 switch(btn_num)
5022 {
5023 case 1:
5024 events_handled++;
5025
5026 /* Select new object as needed and
5027 * redraw the previously selected object.
5028 */
5029 if(m->selected_object != i)
5030 {
5031 int po = m->selected_object;
5032 m->selected_object = i;
5033 if(m->always_full_redraw)
5034 SARMenuDrawAll(display, m);
5035 else
5036 SARMenuDrawObject(display, m, po);
5037 }
5038
5039 sw->state = !sw->state;
5040 DO_REDRAW_OBJECT(display, m, i)
5041
5042 if(sw->switch_cb != NULL)
5043 sw->switch_cb(
5044 sw, /* This Object */
5045 sw->id, /* ID Code */
5046 sw->client_data,/* Data */
5047 sw->state /* State */
5048 );
5049 break;
5050 }
5051 break;
5052
5053 case GWEventTypePointerMotion:
5054 case GWEventType2ButtonPress:
5055 case GWEventType3ButtonPress:
5056 break;
5057 }
5058 }
5059 /* Event not handled? */
5060 if(events_handled <= 0)
5061 {
5062 /* Calculate size of object area */
5063 w = sw->width;
5064 h = sw->height;
5065 if(w <= 0)
5066 w = MAX(
5067 (2 * DEF_XMARGIN) + DEF_SWITCH_WIDTH,
5068 (2 * DEF_XMARGIN) + (STRLEN(label) * fw)
5069 );
5070 if(h <= 0)
5071 h = (1 * DEF_YMARGIN) + DEF_SWITCH_HEIGHT +
5072 ((label != NULL) ? fh : 0);
5073
5074 /* Get coordinate bounds */
5075 x_min = (int)((sw->x * width) - (w / 2));
5076 x_max = (int)(x_min + w);
5077 y_min = (int)((sw->y * height) - (h / 2));
5078 y_max = (int)(y_min + h);
5079
5080 /* Pointer event in bounds? */
5081 if((x >= x_min) && (x < x_max) &&
5082 (y >= y_min) && (y < y_max)
5083 )
5084 {
5085 switch(type)
5086 {
5087 case GWEventTypeButtonPress:
5088 events_handled++;
5089
5090 /* Select new object as needed and
5091 * redraw the previously selected
5092 * object
5093 */
5094 if(m->selected_object != i)
5095 {
5096 int po = m->selected_object;
5097 m->selected_object = i;
5098 if(m->always_full_redraw)
5099 SARMenuDrawAll(display, m);
5100 else
5101 SARMenuDrawObject(display, m, po);
5102 }
5103
5104 DO_REDRAW_OBJECT(display, m, i)
5105 break;
5106
5107 case GWEventTypeButtonRelease:
5108 case GWEventTypePointerMotion:
5109 case GWEventType2ButtonPress:
5110 case GWEventType3ButtonPress:
5111 break;
5112 }
5113 }
5114 }
5115 }
5116 break;
5117
5118 /* ***************************************************** */
5119 case SAR_MENU_OBJECT_TYPE_SPIN:
5120 spin = SAR_MENU_SPIN(o);
5121 if(spin->sensitive)
5122 {
5123 int fw, fh;
5124 int label_len = STRLEN(spin->label);
5125 int label_width;
5126
5127 GWGetFontSize(
5128 spin->font,
5129 NULL, NULL,
5130 &fw, &fh
5131 );
5132
5133 label_width = (2 * DEF_XMARGIN) + (label_len * fw);
5134
5135 w = (int)(width * spin->width);
5136 h = (int)MAX(
5137 height * spin->height,
5138 (4 * DEF_YMARGIN) + fh
5139 );
5140
5141 /* Get coordinate bounds for decrement button */
5142 x_min = (int)((spin->x * width) - (w / 2) + label_width);
5143 x_max = (int)(x_min + h);
5144 y_min = (int)((spin->y * height) - (h / 2));
5145 y_max = (int)(y_min + h);
5146 /* Pointer event in bounds? */
5147 if((x >= x_min) && (x < x_max) &&
5148 (y >= y_min) && (y < y_max) &&
5149 (events_handled <= 0)
5150 )
5151 {
5152 switch(type)
5153 {
5154 case GWEventTypeButtonPress:
5155 events_handled++;
5156 /* Select new object as needed and redraw
5157 * the previously selected object
5158 */
5159 if(m->selected_object != i)
5160 {
5161 int po = m->selected_object;
5162 m->selected_object = i;
5163 if(m->always_full_redraw)
5164 SARMenuDrawAll(display, m);
5165 else
5166 SARMenuDrawObject(display, m, po);
5167 }
5168 spin->dec_state = SAR_MENU_BUTTON_STATE_ARMED;
5169 DO_REDRAW_OBJECT(display, m, i)
5170 break;
5171 case GWEventTypeButtonRelease:
5172 events_handled++;
5173 switch(spin->dec_state)
5174 {
5175 case SAR_MENU_BUTTON_STATE_ARMED:
5176 case SAR_MENU_BUTTON_STATE_HIGHLIGHTED:
5177 spin->dec_state = SAR_MENU_BUTTON_STATE_HIGHLIGHTED;
5178 if(btn_num == 3)
5179 SARMenuSpinSelectValueIndex(
5180 display, m, i,
5181 0,
5182 False
5183 );
5184 else
5185 SARMenuSpinDoDec(display, m, i, False);
5186 DO_REDRAW_OBJECT(display, m, i)
5187 break;
5188 }
5189 break;
5190 case GWEventTypePointerMotion:
5191 events_handled++;
5192 if(spin->dec_state == SAR_MENU_BUTTON_STATE_UNARMED)
5193 {
5194 spin->dec_state = SAR_MENU_BUTTON_STATE_HIGHLIGHTED;
5195 DO_REDRAW_OBJECT(display, m, i)
5196 }
5197 break;
5198 case GWEventType2ButtonPress:
5199 case GWEventType3ButtonPress:
5200 break;
5201 }
5202 }
5203
5204 /* Get coordinate bounds for increment button */
5205 x_max = (int)((spin->x * width) + (w / 2));
5206 x_min = (int)(x_max - h);
5207 y_min = (int)((spin->y * height) - (h / 2));
5208 y_max = (int)(y_min + h);
5209 /* Pointer event in bounds? */
5210 if((x >= x_min) && (x < x_max) &&
5211 (y >= y_min) && (y < y_max) &&
5212 (events_handled <= 0)
5213 )
5214 {
5215 switch(type)
5216 {
5217 case GWEventTypeButtonPress:
5218 events_handled++;
5219 /* Select new object as needed and redraw
5220 * the previously selected object
5221 */
5222 if(m->selected_object != i)
5223 {
5224 int po = m->selected_object;
5225 m->selected_object = i;
5226 if(m->always_full_redraw)
5227 SARMenuDrawAll(display, m);
5228 else
5229 SARMenuDrawObject(display, m, po);
5230 }
5231 spin->inc_state = SAR_MENU_BUTTON_STATE_ARMED;
5232 DO_REDRAW_OBJECT(display, m, i)
5233 break;
5234 case GWEventTypeButtonRelease:
5235 events_handled++;
5236 switch(spin->inc_state)
5237 {
5238 case SAR_MENU_BUTTON_STATE_ARMED:
5239 case SAR_MENU_BUTTON_STATE_HIGHLIGHTED:
5240 spin->inc_state = SAR_MENU_BUTTON_STATE_HIGHLIGHTED;
5241 if(btn_num == 3)
5242 SARMenuSpinSelectValueIndex(
5243 display, m, i,
5244 MAX(spin->total_values - 1, 0),
5245 False
5246 );
5247 else
5248 SARMenuSpinDoInc(display, m, i, False);
5249 DO_REDRAW_OBJECT(display, m, i)
5250 break;
5251 }
5252 break;
5253 case GWEventTypePointerMotion:
5254 events_handled++;
5255 if(spin->inc_state == SAR_MENU_BUTTON_STATE_UNARMED)
5256 {
5257 spin->inc_state = SAR_MENU_BUTTON_STATE_HIGHLIGHTED;
5258 DO_REDRAW_OBJECT(display, m, i)
5259 }
5260 break;
5261 case GWEventType2ButtonPress:
5262 case GWEventType3ButtonPress:
5263 break;
5264 }
5265 }
5266
5267 /* Event not handled above? */
5268 if(events_handled <= 0)
5269 {
5270 /* Event not handled above, this implies the
5271 * event occured outside the event areas of
5272 * this object
5273 */
5274 switch(type)
5275 {
5276 case GWEventTypeButtonPress:
5277 /* Get coordinate bounds */
5278 x_min = (int)((spin->x * width) - (w / 2));
5279 x_max = (int)(x_min + w);
5280 y_min = (int)((spin->y * height) - (h / 2));
5281 y_max = (int)(y_min + h);
5282
5283 /* Pointer event in bounds? */
5284 if((x >= x_min) && (x < x_max) &&
5285 (y >= y_min) && (y < y_max)
5286 )
5287 {
5288 events_handled++;
5289 /* Select new object as needed and
5290 * redraw the previously selected object.
5291 */
5292 if(m->selected_object != i)
5293 {
5294 int po = m->selected_object;
5295 m->selected_object = i;
5296 if(m->always_full_redraw)
5297 SARMenuDrawAll(display, m);
5298 else
5299 SARMenuDrawObject(display, m, po);
5300 }
5301 DO_REDRAW_OBJECT(display, m, i)
5302 }
5303 break;
5304
5305 case GWEventTypeButtonRelease:
5306 case GWEventTypePointerMotion:
5307 if(spin->dec_state != SAR_MENU_BUTTON_STATE_UNARMED)
5308 {
5309 spin->dec_state = SAR_MENU_BUTTON_STATE_UNARMED;
5310 DO_REDRAW_OBJECT(display, m, i)
5311 }
5312 if(spin->inc_state != SAR_MENU_BUTTON_STATE_UNARMED)
5313 {
5314 spin->inc_state = SAR_MENU_BUTTON_STATE_UNARMED;
5315 DO_REDRAW_OBJECT(display, m, i)
5316 }
5317 break;
5318
5319 case GWEventType2ButtonPress:
5320 case GWEventType3ButtonPress:
5321 break;
5322 }
5323 }
5324 }
5325 break;
5326
5327 /* ***************************************************** */
5328 case SAR_MENU_OBJECT_TYPE_SLIDER:
5329 slider = SAR_MENU_SLIDER(o);
5330 if(slider->sensitive)
5331 {
5332 int fw, fh;
5333 int label_len = STRLEN(slider->label);
5334 int label_width;
5335
5336 GWGetFontSize(
5337 slider->font,
5338 NULL, NULL,
5339 &fw, &fh
5340 );
5341
5342 w = (int)(width * slider->width);
5343 h = (int)MAX(
5344 height * slider->height,
5345 (4 * DEF_YMARGIN) + fh
5346 );
5347
5348 label_width = (4 * DEF_XMARGIN) + (label_len * fw);
5349
5350 /* Get coordinate bounds of trough */
5351 x_min = (int)(
5352 (slider->x * width) - (w / 2) + label_width
5353 ) + DEF_XMARGIN;
5354 x_max = (int)((slider->x * width) + (w / 2)) - DEF_XMARGIN;
5355 y_min = (int)((slider->y * height) - (h / 2));
5356 y_max = (int)(y_min + h);
5357
5358 /* Pointer event in bounds? */
5359 if((events_handled <= 0) &&
5360 (x >= x_min) && (x < x_max) &&
5361 (y >= y_min) && (y < y_max)
5362 )
5363 {
5364 float vc, value;
5365 #define DO_CALCULATE_VALUE { \
5366 vc = ((x_max - x_min) > 0) ? \
5367 (float)(x - x_min) / (float)(x_max - x_min) : 0.0f; \
5368 value = CLIP(slider->lower + \
5369 (vc * (slider->upper - slider->lower)), \
5370 slider->lower, slider->upper \
5371 ); \
5372 }
5373
5374 switch(type)
5375 {
5376 case GWEventTypeButtonPress:
5377 events_handled++;
5378 /* Select new object as needed and redraw the
5379 * previously selected object
5380 */
5381 if(m->selected_object != i)
5382 {
5383 int po = m->selected_object;
5384 m->selected_object = i;
5385 if(m->always_full_redraw)
5386 SARMenuDrawAll(display, m);
5387 else
5388 SARMenuDrawObject(display, m, po);
5389 }
5390 /* Record drag button number */
5391 slider->drag_button = btn_num;
5392 if(slider->drag_button == 1)
5393 {
5394 DO_CALCULATE_VALUE
5395 SARMenuSliderSetValue(
5396 display, m, i, value, True
5397 );
5398 }
5399 else
5400 {
5401 DO_REDRAW_OBJECT(display, m, i)
5402 }
5403 break;
5404
5405 case GWEventTypeButtonRelease:
5406 events_handled++;
5407 slider->drag_button = 0;
5408 break;
5409
5410 case GWEventTypePointerMotion:
5411 if(slider->drag_button == 1)
5412 {
5413 DO_CALCULATE_VALUE
5414 SARMenuSliderSetValue(
5415 display, m, i, value, True
5416 );
5417 events_handled++;
5418 }
5419 break;
5420
5421 case GWEventType2ButtonPress:
5422 case GWEventType3ButtonPress:
5423 break;
5424 }
5425 #undef DO_CALCULATE_VALUE
5426 }
5427 }
5428 break;
5429
5430 /* ***************************************************** */
5431 case SAR_MENU_OBJECT_TYPE_MAP:
5432 map = SAR_MENU_MAP(o);
5433 if(!map->sensitive)
5434 break;
5435 events_handled += SARMenuMapManagePointer(
5436 display, m, map, i,
5437 x, y, type, btn_num
5438 );
5439 break;
5440
5441 /* ***************************************************** */
5442 case SAR_MENU_OBJECT_TYPE_OBJVIEW:
5443 objview = SAR_MENU_OBJVIEW(o);
5444 if(!objview->sensitive)
5445 break;
5446 events_handled += SARMenuObjViewManagePointer(
5447 display, m, objview, i,
5448 x, y, type, btn_num
5449 );
5450 break;
5451 }
5452 }
5453
5454 return(events_handled);
5455 }
5456
5457
5458 /*
5459 * Manages a key event assumed for the menu.
5460 */
SARMenuManageKey(gw_display_struct * display,sar_menu_struct * m,int key,Boolean state)5461 int SARMenuManageKey(
5462 gw_display_struct *display, sar_menu_struct *m,
5463 int key, Boolean state
5464 )
5465 {
5466 int i, prev_sel_num, events_handled = 0;
5467 int items_visable = 0;
5468 int fw, fh, w, h, width, height;
5469 void *o;
5470 sar_menu_button_struct *button;
5471 sar_menu_message_box_struct *mesgbox;
5472 sar_menu_list_struct *list;
5473 sar_menu_switch_struct *sw;
5474 sar_menu_spin_struct *spin;
5475 sar_menu_slider_struct *slider;
5476 sar_menu_objview_struct *ov;
5477
5478
5479 if((display == NULL) || (m == NULL))
5480 return(events_handled);
5481
5482 #if 0
5483 /* Always ignore key releases */
5484 if(!state)
5485 return(events_handled);
5486 #endif
5487
5488 GWContextGet(
5489 display, GWContextCurrent(display),
5490 NULL, NULL,
5491 NULL, NULL,
5492 &width, &height
5493 );
5494
5495
5496 /* Menu global key functions */
5497 switch(key)
5498 {
5499 /* Tab changes selected object */
5500 case '\t':
5501 if(!state)
5502 {
5503 events_handled++;
5504 break;
5505 }
5506
5507 prev_sel_num = m->selected_object;
5508
5509 #define TYPE_SELECTABLE(t) ( \
5510 ((t) != SAR_MENU_OBJECT_TYPE_LABEL) && \
5511 ((t) != SAR_MENU_OBJECT_TYPE_PROGRESS) \
5512 )
5513
5514 if(display->shift_key_state)
5515 {
5516 /* Seek backwards until we get a selectable object
5517 * type or the list has cycled
5518 */
5519 sar_menu_object_type type;
5520 int status = 0;
5521 m->selected_object--;
5522 while(m->selected_object >= 0)
5523 {
5524 o = SARMenuGetObject(m, m->selected_object);
5525 if((o != NULL) &&
5526 SARMenuObjectIsSensitive(m, m->selected_object)
5527 )
5528 {
5529 type = SAR_MENU_OBJECT_TYPE(o);
5530 if(TYPE_SELECTABLE(type))
5531 {
5532 status = 1;
5533 break;
5534 }
5535 }
5536 m->selected_object--;
5537 }
5538 /* Did not get a match? */
5539 if(!status)
5540 {
5541 /* From the end */
5542 m->selected_object = m->total_objects - 1;
5543 while(m->selected_object > prev_sel_num)
5544 {
5545 o = SARMenuGetObject(m, m->selected_object);
5546 if((o != NULL) &&
5547 SARMenuObjectIsSensitive(m, m->selected_object)
5548 )
5549 {
5550 type = SAR_MENU_OBJECT_TYPE(o);
5551 if(TYPE_SELECTABLE(type))
5552 {
5553 status = 1;
5554 break;
5555 }
5556 }
5557 m->selected_object--;
5558 }
5559 }
5560 /* Still no match? */
5561 if(!status)
5562 m->selected_object = prev_sel_num;
5563 }
5564 else
5565 {
5566 /* Seek forwards until we get a selectable object
5567 * type or the list has cycled
5568 */
5569 sar_menu_object_type type;
5570 int status = 0;
5571 m->selected_object++;
5572 while(m->selected_object < m->total_objects)
5573 {
5574 o = SARMenuGetObject(m, m->selected_object);
5575 if((o != NULL) &&
5576 SARMenuObjectIsSensitive(m, m->selected_object)
5577 )
5578 {
5579 type = SAR_MENU_OBJECT_TYPE(o);
5580 if(TYPE_SELECTABLE(type))
5581 {
5582 status = 1;
5583 break;
5584 }
5585 }
5586 m->selected_object++;
5587 }
5588 /* Didn't get a match? */
5589 if(!status)
5590 {
5591 /* From the beginning */
5592 m->selected_object = 0;
5593 while(m->selected_object < prev_sel_num)
5594 {
5595 o = SARMenuGetObject(m, m->selected_object);
5596 if((o != NULL) &&
5597 SARMenuObjectIsSensitive(m, m->selected_object)
5598 )
5599 {
5600 type = SAR_MENU_OBJECT_TYPE(o);
5601 if(TYPE_SELECTABLE(type))
5602 {
5603 status = 1;
5604 break;
5605 }
5606 }
5607 m->selected_object++;
5608 }
5609 }
5610 /* Still no match? */
5611 if(!status)
5612 m->selected_object = prev_sel_num;
5613 }
5614
5615 /* Sanitize */
5616 if(m->selected_object >= m->total_objects)
5617 m->selected_object = 0;
5618 else if(m->selected_object < 0)
5619 m->selected_object = m->total_objects - 1;
5620
5621 if(m->selected_object < 0)
5622 m->selected_object = 0;
5623
5624 /* If a menu's selected object is this button and this
5625 * button is unarmed, it needs to be highlighted
5626 */
5627 o = SARMenuGetObject(m, prev_sel_num);
5628 if(o != NULL)
5629 {
5630 if(SAR_MENU_IS_BUTTON(o))
5631 {
5632 button = SAR_MENU_BUTTON(o);
5633 button->state = SAR_MENU_BUTTON_STATE_UNARMED;
5634 }
5635 }
5636 o = SARMenuGetObject(m, m->selected_object);
5637 if(o != NULL)
5638 {
5639 if(SAR_MENU_IS_BUTTON(o))
5640 {
5641 button = SAR_MENU_BUTTON(o);
5642 button->state = SAR_MENU_BUTTON_STATE_HIGHLIGHTED;
5643 }
5644 }
5645
5646 DO_REDRAW_MENU(display,m)
5647 events_handled++;
5648 break;
5649 }
5650 if(events_handled > 0)
5651 return(events_handled);
5652
5653
5654 /* Key on selected widget */
5655 i = m->selected_object;
5656 o = SARMenuGetObject(m, i);
5657 if(o != NULL)
5658 {
5659 /* Handle by widget type */
5660 switch(SAR_MENU_OBJECT_TYPE(o))
5661 {
5662 /* **************************************************** */
5663 case SAR_MENU_OBJECT_TYPE_BUTTON:
5664 button = SAR_MENU_BUTTON(o);
5665 if(!button->sensitive)
5666 break;
5667
5668 switch(key)
5669 {
5670 case '\n': case ' ':
5671 if(state)
5672 {
5673 button->state = SAR_MENU_BUTTON_STATE_ARMED;
5674 DO_REDRAW_OBJECT(display, m, i)
5675 }
5676 else if(button->state == SAR_MENU_BUTTON_STATE_ARMED)
5677 {
5678 button->state = SAR_MENU_BUTTON_STATE_HIGHLIGHTED;
5679 DO_REDRAW_OBJECT(display, m, i)
5680 if(button->func_cb != NULL)
5681 button->func_cb(
5682 button, /* Object */
5683 button->id, /* ID Code */
5684 button->client_data /* Data */
5685 );
5686 }
5687 events_handled++;
5688 break;
5689 }
5690 break;
5691
5692 /* **************************************************** */
5693 case SAR_MENU_OBJECT_TYPE_MESSAGE_BOX:
5694 mesgbox = SAR_MENU_MESSAGE_BOX(o);
5695 if(!mesgbox->sensitive)
5696 break;
5697
5698 if(!state)
5699 break;
5700
5701 w = (int)(mesgbox->width * width);
5702 if(w <= 0)
5703 w = (int)(width - (2 * DEF_MB_XMARGIN));
5704 if(w <= 0)
5705 w = DEF_MB_XMARGIN;
5706
5707 if(mesgbox->height > 0)
5708 h = (int)(mesgbox->height * height);
5709 else
5710 h = DEF_HEIGHT;
5711 if(h <= 0)
5712 h = DEF_MB_YMARGIN;
5713
5714 if(mesgbox->message != NULL)
5715 {
5716 int total_lines, columns_visable,
5717 lines_visable, scroll_width;
5718
5719
5720 GWGetFontSize(
5721 mesgbox->font,
5722 NULL, NULL,
5723 &fw, &fh
5724 );
5725
5726 /* Calculate colums visible */
5727 if(fw > 0)
5728 columns_visable = (w - DEF_SCROLL_CURSOR_WIDTH
5729 - (2 * DEF_MB_XMARGIN)) / fw;
5730 else
5731 columns_visable = 1;
5732 if(columns_visable < 1)
5733 columns_visable = 1;
5734
5735 /* Calculate width (height) of scroll indicator */
5736 scroll_width = fh + (2 * DEF_MB_YMARGIN);
5737
5738 /* Calculate lines visable */
5739 if(fh > 0)
5740 lines_visable = (h - (2 * DEF_MB_YMARGIN)) / fh;
5741 else
5742 lines_visable = 0;
5743 if(lines_visable < 0)
5744 lines_visable = 0;
5745
5746 /* Calculate total number of lines */
5747 total_lines = SARMenuMessageBoxTotalLines(
5748 mesgbox->message, columns_visable
5749 );
5750
5751 switch(key)
5752 {
5753 case GWKeyHome:
5754 events_handled++;
5755 mesgbox->scrolled_line = 0;
5756 DO_REDRAW_OBJECT(display, m, i)
5757 break;
5758
5759 case GWKeyEnd:
5760 events_handled++;
5761 mesgbox->scrolled_line =
5762 total_lines - (lines_visable / 2);
5763 if(mesgbox->scrolled_line < 0)
5764 mesgbox->scrolled_line = 0;
5765 DO_REDRAW_OBJECT(display, m, i)
5766 break;
5767
5768 case GWKeyUp:
5769 events_handled++;
5770 mesgbox->scrolled_line--;
5771 if(mesgbox->scrolled_line < 0)
5772 mesgbox->scrolled_line = 0;
5773 DO_REDRAW_OBJECT(display, m, i)
5774 break;
5775
5776 case GWKeyDown:
5777 events_handled++;
5778 mesgbox->scrolled_line++;
5779 if(mesgbox->scrolled_line >=
5780 (total_lines - (lines_visable / 2))
5781 )
5782 mesgbox->scrolled_line = total_lines - (lines_visable / 2);
5783 if(mesgbox->scrolled_line < 0)
5784 mesgbox->scrolled_line = 0;
5785 DO_REDRAW_OBJECT(display, m, i)
5786 break;
5787
5788 case GWKeyPageUp:
5789 case 'b': case '-': case 'p':
5790 events_handled++;
5791 mesgbox->scrolled_line -= lines_visable;
5792 if(mesgbox->scrolled_line < 0)
5793 mesgbox->scrolled_line = 0;
5794 DO_REDRAW_OBJECT(display, m, i)
5795 break;
5796
5797 case GWKeyPageDown:
5798 case ' ': case 'n':
5799 events_handled++;
5800 mesgbox->scrolled_line += lines_visable;
5801 if(mesgbox->scrolled_line >=
5802 (total_lines - (lines_visable / 2))
5803 )
5804 mesgbox->scrolled_line = total_lines - (lines_visable / 2);
5805 if(mesgbox->scrolled_line < 0)
5806 mesgbox->scrolled_line = 0;
5807 DO_REDRAW_OBJECT(display, m, i)
5808 break;
5809 }
5810 }
5811 break;
5812
5813 /* **************************************************** */
5814 case SAR_MENU_OBJECT_TYPE_LIST:
5815 list = SAR_MENU_LIST(o);
5816 if(!list->sensitive)
5817 break;
5818
5819 if(!state)
5820 break;
5821
5822 w = (int)(list->width * width);
5823 if(w <= 0)
5824 w = width - (2 * DEF_LIST_XMARGIN);
5825 if(w <= 0)
5826 w = DEF_LIST_XMARGIN;
5827
5828 if(list->height > 0)
5829 h = (int)(list->height * height);
5830 else
5831 h = DEF_HEIGHT;
5832 if(h <= 0)
5833 h = DEF_LIST_YMARGIN;
5834
5835 GWGetFontSize(
5836 list->font,
5837 NULL, NULL,
5838 &fw, &fh
5839 );
5840 /* Calculate items visible, remember to subtract 3
5841 * items for borders and heading
5842 */
5843 if(fh > 0)
5844 items_visable = MAX(
5845 (h / fh) - 3,
5846 0
5847 );
5848 else
5849 items_visable = 0;
5850
5851 /* Update items visable on list */
5852 list->items_visable = items_visable;
5853
5854 /* Record previously selected item */
5855 prev_sel_num = list->selected_item;
5856
5857 switch(key)
5858 {
5859 case GWKeyHome:
5860 events_handled++;
5861 list->selected_item = 0;
5862 list->scrolled_item = 0;
5863 DO_REDRAW_OBJECT(display, m, i)
5864 break;
5865
5866 case GWKeyEnd:
5867 events_handled++;
5868 list->selected_item = list->total_items - 1;
5869 if(list->selected_item < 0)
5870 list->selected_item = 0;
5871 list->scrolled_item = list->total_items -
5872 (items_visable / 2);
5873 if(list->scrolled_item < 0)
5874 list->scrolled_item = 0;
5875 DO_REDRAW_OBJECT(display, m, i)
5876 break;
5877
5878 case GWKeyUp:
5879 events_handled++;
5880 list->selected_item--;
5881 if(list->selected_item < 0)
5882 list->selected_item = 0;
5883 if(list->selected_item < list->scrolled_item)
5884 {
5885 list->scrolled_item -= (items_visable + 1);
5886 if(list->scrolled_item < 0)
5887 list->scrolled_item = 0;
5888 }
5889 DO_REDRAW_OBJECT(display, m, i)
5890 break;
5891
5892 case GWKeyDown:
5893 events_handled++;
5894 list->selected_item++;
5895 if(list->selected_item >= list->total_items)
5896 list->selected_item = list->total_items - 1;
5897 if(list->selected_item < 0)
5898 list->selected_item = 0;
5899 if(list->selected_item > (list->scrolled_item +
5900 items_visable)
5901 )
5902 {
5903 list->scrolled_item = list->selected_item;
5904 }
5905 DO_REDRAW_OBJECT(display, m, i)
5906 break;
5907
5908 case GWKeyPageUp:
5909 case 'b': case '-': case 'p':
5910 events_handled++;
5911 list->scrolled_item -= items_visable;
5912 if(list->scrolled_item < 0)
5913 list->scrolled_item = 0;
5914
5915 list->selected_item = list->scrolled_item;
5916
5917 DO_REDRAW_OBJECT(display, m, i)
5918 break;
5919
5920 case GWKeyPageDown:
5921 case ' ': case 'n':
5922 events_handled++;
5923 list->scrolled_item += items_visable;
5924 if(list->scrolled_item >=
5925 (list->total_items - (items_visable / 2))
5926 )
5927 list->scrolled_item = list->total_items -
5928 (items_visable / 2);
5929 if(list->scrolled_item < 0)
5930 list->scrolled_item = 0;
5931 list->selected_item = list->scrolled_item;
5932 DO_REDRAW_OBJECT(display, m, i)
5933 break;
5934 }
5935
5936 /* Call select notify function */
5937 if((list->select_cb != NULL) &&
5938 (prev_sel_num != list->selected_item) &&
5939 (list->selected_item >= 0) &&
5940 (list->selected_item < list->total_items)
5941 )
5942 {
5943 sar_menu_list_item_struct *item = list->item[list->selected_item];
5944 if(item != NULL)
5945 list->select_cb(
5946 list, /* This Object */
5947 list->id, /* ID Code */
5948 list->client_data, /* Data */
5949 list->selected_item, /* Item Number */
5950 item, /* Item Pointer */
5951 item->client_data /* Item Data */
5952 );
5953 }
5954 break;
5955
5956 /* **************************************************** */
5957 case SAR_MENU_OBJECT_TYPE_SWITCH:
5958 sw = SAR_MENU_SWITCH(o);
5959 if(!sw->sensitive)
5960 break;
5961
5962 if(!state)
5963 break;
5964
5965 switch(key)
5966 {
5967 case GWKeyUp:
5968 case GWKeyDown:
5969 case GWKeyLeft:
5970 case GWKeyRight:
5971 case ' ': case '\n':
5972 events_handled++;
5973 sw->state = !sw->state;
5974 DO_REDRAW_OBJECT(display, m, i)
5975 if(sw->switch_cb != NULL)
5976 sw->switch_cb(
5977 sw, /* This Object */
5978 sw->id, /* ID Code */
5979 sw->client_data, /* Data */
5980 sw->state /* Value */
5981 );
5982 break;
5983 }
5984 break;
5985
5986 /* ***************************************************** */
5987 case SAR_MENU_OBJECT_TYPE_SPIN:
5988 spin = SAR_MENU_SPIN(o);
5989 if(!spin->sensitive)
5990 break;
5991
5992 switch(key)
5993 {
5994 case GWKeyRight:
5995 case GWKeyDown:
5996 case GWKeyPageDown:
5997 case ' ': case '\n':
5998 case '+': case '=': case 'n':
5999 if(state)
6000 {
6001 spin->inc_state = SAR_MENU_BUTTON_STATE_ARMED;
6002 }
6003 else if(spin->inc_state == SAR_MENU_BUTTON_STATE_ARMED)
6004 {
6005 spin->inc_state = SAR_MENU_BUTTON_STATE_UNARMED;
6006 SARMenuSpinDoInc(display, m, i, False);
6007 }
6008 DO_REDRAW_OBJECT(display, m, i)
6009 events_handled++;
6010 break;
6011 case GWKeyLeft:
6012 case GWKeyUp:
6013 case GWKeyPageUp:
6014 case GWKeyBackSpace:
6015 case '-': case '_': case 'b':
6016 if(state)
6017 {
6018 spin->dec_state = SAR_MENU_BUTTON_STATE_ARMED;
6019 }
6020 else if(spin->dec_state == SAR_MENU_BUTTON_STATE_ARMED)
6021 {
6022 spin->dec_state = SAR_MENU_BUTTON_STATE_UNARMED;
6023 SARMenuSpinDoDec(display, m, i, False);
6024 }
6025 DO_REDRAW_OBJECT(display, m, i)
6026 events_handled++;
6027 break;
6028 case GWKeyHome:
6029 if(state)
6030 {
6031 spin->dec_state = SAR_MENU_BUTTON_STATE_ARMED;
6032 }
6033 else if(spin->dec_state == SAR_MENU_BUTTON_STATE_ARMED)
6034 {
6035 spin->dec_state = SAR_MENU_BUTTON_STATE_UNARMED;
6036 SARMenuSpinSelectValueIndex(
6037 display, m, i,
6038 0,
6039 False
6040 );
6041 }
6042 DO_REDRAW_OBJECT(display, m, i)
6043 events_handled++;
6044 break;
6045 case GWKeyEnd:
6046 if(state)
6047 {
6048 spin->inc_state = SAR_MENU_BUTTON_STATE_ARMED;
6049 }
6050 else if(spin->inc_state == SAR_MENU_BUTTON_STATE_ARMED)
6051 {
6052 spin->inc_state = SAR_MENU_BUTTON_STATE_UNARMED;
6053 SARMenuSpinSelectValueIndex(
6054 display, m, i,
6055 MAX(spin->total_values - 1, 0),
6056 False
6057 );
6058 }
6059 DO_REDRAW_OBJECT(display, m, i)
6060 events_handled++;
6061 break;
6062 }
6063 break;
6064
6065 /* ***************************************************** */
6066 case SAR_MENU_OBJECT_TYPE_SLIDER:
6067 slider = SAR_MENU_SLIDER(o);
6068 if(!slider->sensitive)
6069 break;
6070
6071 if(!state)
6072 break;
6073
6074 if(slider->upper > slider->lower)
6075 {
6076 float inc = (float)(slider->upper - slider->lower) * 0.1f;
6077 float page_inc = (float)(slider->upper - slider->lower) * 0.25f;
6078 float value;
6079
6080 switch(key)
6081 {
6082 case GWKeyRight:
6083 case GWKeyUp:
6084 case '+': case '=': case ' ': case '\n':
6085 value = CLIP(
6086 slider->value + inc,
6087 slider->lower, slider->upper
6088 );
6089 SARMenuSliderSetValue(
6090 display, m, i, value, True
6091 );
6092 events_handled++;
6093 break;
6094 case GWKeyLeft:
6095 case GWKeyDown:
6096 case '_': case '-':
6097 value = CLIP(
6098 slider->value - inc,
6099 slider->lower, slider->upper
6100 );
6101 SARMenuSliderSetValue(
6102 display, m, i, value, True
6103 );
6104 events_handled++;
6105 break;
6106 case GWKeyPageUp:
6107 value = CLIP(
6108 slider->value + page_inc,
6109 slider->lower, slider->upper
6110 );
6111 SARMenuSliderSetValue(
6112 display, m, i, value, True
6113 );
6114 events_handled++;
6115 break;
6116 case GWKeyPageDown:
6117 value = CLIP(
6118 slider->value - page_inc,
6119 slider->lower, slider->upper
6120 );
6121 SARMenuSliderSetValue(
6122 display, m, i, value, True
6123 );
6124 events_handled++;
6125 break;
6126 case GWKeyHome:
6127 value = slider->lower;
6128 SARMenuSliderSetValue(
6129 display, m, i, value, True
6130 );
6131 events_handled++;
6132 break;
6133 case GWKeyEnd:
6134 value = slider->upper;
6135 SARMenuSliderSetValue(
6136 display, m, i, value, True
6137 );
6138 events_handled++;
6139 break;
6140 }
6141 }
6142 break;
6143
6144 /* **************************************************** */
6145 case SAR_MENU_OBJECT_TYPE_OBJVIEW:
6146 ov = SAR_MENU_OBJVIEW(o);
6147 if(!ov->sensitive)
6148 break;
6149 SARMenuObjViewManageKey(
6150 display, m, ov, i,
6151 key, state
6152 );
6153 break;
6154 }
6155 }
6156
6157 return(events_handled);
6158 }
6159