]> icculus.org git repositories - taylor/freespace2.git/blob - src/ui/window.cpp
const-char warning fixes
[taylor/freespace2.git] / src / ui / window.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Ui/WINDOW.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Routines to handle UI windows.
16  *
17  * $Log$
18  * Revision 1.3  2004/09/20 01:31:45  theoddone33
19  * GCC 3.4 fixes.
20  *
21  * Revision 1.2  2002/06/09 04:41:29  relnev
22  * added copyright header
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:11  root
25  * Initial import.
26  *
27  * 
28  * 30    10/14/99 2:52p Jefff
29  * localization fixes.  added support for hi-res specific xstr offsets
30  * 
31  * 29    8/16/99 4:06p Dave
32  * Big honking checkin.
33  * 
34  * 28    7/16/99 1:50p Dave
35  * 8 bit aabitmaps. yay.
36  * 
37  * 27    7/15/99 3:07p Dave
38  * 32 bit detection support. Mouse coord commandline.
39  * 
40  * 26    7/13/99 5:38p Jefff
41  * Added support for x offsets when drawing strings
42  * 
43  * 25    6/25/99 11:59a Dave
44  * Multi options screen.
45  * 
46  * 24    6/22/99 7:03p Dave
47  * New detail options screen.
48  * 
49  * 23    6/19/99 2:46p Dave
50  * New control config screen.
51  * 
52  * 22    6/18/99 5:16p Dave
53  * Added real beam weapon lighting. Fixed beam weapon sounds. Added MOTD
54  * dialog to PXO screen.
55  * 
56  * 21    6/04/99 11:32a Dave
57  * Added reset text to ship select screen. Fixed minor xstr bug in ui
58  * window
59  * 
60  * 20    6/02/99 6:18p Dave
61  * Fixed TNT lockup problems! Wheeeee!
62  * 
63  * 19    6/01/99 3:52p Dave
64  * View footage screen. Fixed xstrings to not display the & symbol. Popup,
65  * dead popup, pxo find player popup, pxo private room popup.
66  * 
67  * 18    5/22/99 5:35p Dave
68  * Debrief and chatbox screens. Fixed small hi-res HUD bug.
69  * 
70  * 17    5/21/99 6:45p Dave
71  * Sped up ui loading a bit. Sped up localization disk access stuff. Multi
72  * start game screen, multi password, and multi pxo-help screen.
73  * 
74  * 16    5/17/99 11:28a Dave
75  * 
76  * 15    5/17/99 9:25a Dave
77  * Updated PXO screen. Still needs popups.
78  * 
79  * 14    5/03/99 8:33p Dave
80  * New version of multi host options screen.
81  * 
82  * 13    4/16/99 5:22p Neilk
83  * Fixed UI_SLIDER2 bug
84  * 
85  * 12    2/21/99 6:02p Dave
86  * Fixed standalone WSS packets. 
87  * 
88  * 11    2/01/99 5:55p Dave
89  * Removed the idea of explicit bitmaps for buttons. Fixed text
90  * highlighting for disabled gadgets.
91  * 
92  * 10    1/29/99 2:08a Dave
93  * Fixed beam weapon collisions with players. Reduced size of scoring
94  * struct for multiplayer. Disabled PXO.
95  * 
96  * 9     1/29/99 12:47a Dave
97  * Put in sounds for beam weapon. A bunch of interface screens (tech
98  * database stuff).
99  * 
100  * 8     12/18/98 1:13a Dave
101  * Rough 1024x768 support for Direct3D. Proper detection and usage through
102  * the launcher.
103  * 
104  * 7     12/02/98 5:47p Dave
105  * Put in interface xstr code. Converted barracks screen to new format.
106  * 
107  * 6     11/30/98 1:07p Dave
108  * 16 bit conversion, first run.
109  * 
110  * 5     10/23/98 3:51p Dave
111  * Full support for tstrings.tbl and foreign languages. All that remains
112  * is to make it active in Fred.
113  * 
114  * 4     10/13/98 9:29a Dave
115  * Started neatening up freespace.h. Many variables renamed and
116  * reorganized. Added AlphaColors.[h,cpp]
117  * 
118  * 3     10/07/98 6:27p Dave
119  * Globalized mission and campaign file extensions. Removed Silent Threat
120  * special code. Moved \cache \players and \multidata into the \data
121  * directory.
122  * 
123  * 2     10/07/98 10:54a Dave
124  * Initial checkin.
125  * 
126  * 1     10/07/98 10:51a Dave
127  * 
128  *
129  * $NoKeywords: $
130  */
131
132 #include "osapi.h"
133 #include "uidefs.h"
134 #include "ui.h"
135 #include "freespace.h"
136 #include "bmpman.h"
137 #include "palman.h"
138 #include "parselo.h"
139 #include "timer.h"
140 #include "alphacolors.h"
141 #include "font.h"
142 #include "localize.h"
143 #include "cmdline.h"
144
145 // global xstr colors
146 color *Xstr_colors[UI_NUM_XSTR_COLORS][3] = {
147         {       // UI_XSTR_COLOR_GREEN
148                 &Color_normal,
149                 &Color_ui_light_green,
150                 &Color_ui_green,
151         },
152         {       // UI_XSTR_COLOR_PINK
153                 &Color_normal,
154                 &Color_ui_light_pink,
155                 &Color_ui_pink,
156         },
157 };
158
159 // --------------------------------------------------------------------
160 // UI_WINDOW constructor
161 //
162 //
163 UI_WINDOW::UI_WINDOW()
164 {
165         int idx;
166
167         mask_bmap_id = -1;                              // bitmap id of the mask bitmap to define hotspots
168         foreground_bmap_id = -1;                // bitmap id of the foreground bitmap to display
169         mask_bmap_ptr = NULL;                   // pointer to bitmap of the mask
170         mask_data = NULL;                                       // points to raw mask bitmap data
171         mask_w = -1;                                            // bitmap width
172         mask_h = -1;                                            // bitmap height
173         tooltip_handler = NULL;                 // pointer to function to handle custom tooltips
174
175         // NULL all the xstring structs
176         for(idx=0; idx<MAX_UI_XSTRS; idx++){
177                 xstrs[idx] = NULL;
178         }
179 }
180
181 // --------------------------------------------------------------------
182 // UI_WINDOW destructor
183 //
184 //
185 UI_WINDOW::~UI_WINDOW()
186 {
187 }
188
189 // --------------------------------------------------------------------
190 // UI_WINDOW::set_mask_bmap()
191 //
192 // Specify the filename for the mask bitmap to use.  This has the hotspots
193 // for all the different controls.
194 //
195 void UI_WINDOW::set_mask_bmap(const char *fname)
196 {
197         int bmap;
198
199         bmap = bm_load(fname);
200
201         if (bmap < 0) {
202                 Error(LOCATION, "Could not load in %s!", fname);
203
204         } else {
205                 set_mask_bmap(bmap, fname);
206         }
207 }
208
209 void UI_WINDOW::set_mask_bmap(int bmap, const char *name)
210 {
211         // int i;
212
213         // init_tooltips();
214         Assert(bmap >= 0);      
215
216         if (bmap != mask_bmap_id) {
217                 if (mask_bmap_id >= 0){
218                         bm_unlock(mask_bmap_id);
219                 }
220
221                 mask_w = -1;
222                 mask_h = -1;
223
224                 mask_bmap_id = bmap;
225                 mask_bmap_ptr = bm_lock(mask_bmap_id, 8, BMP_AABITMAP);
226                 mask_data = (ushort *) mask_bmap_ptr->data;             
227                 bm_get_info( bmap, &mask_w, &mask_h );
228                 tt_group = -1;
229                 /*
230                 for (i=0; i<Num_tooltip_groups; i++){
231                         if (!stricmp(Tooltip_groups[i].mask, name)){
232                                 tt_group = i;
233                         }
234                 }
235                 */
236         } else {
237                 nprintf(("UI", "Warning: tried to switch bitmap mask to the same bitmap\n"));
238         }
239 }
240
241 // --------------------------------------------------------------------
242 // UI_WINDOW::set_foreground_bmap()
243 //
244 // Specify the filename for the mask bitmap to display on the ui window as
245 // a background.
246 //
247 void UI_WINDOW::set_foreground_bmap(const char *fname)
248 {
249         // load in the background bitmap 
250         foreground_bmap_id = bm_load(fname);
251         if (foreground_bmap_id < 0) {
252                 Error(LOCATION,"Could not load in %s!",fname);
253         }
254 #ifndef HARDWARE_ONLY
255         palette_use_bm_palette(foreground_bmap_id);
256 #endif
257 }
258
259
260 void UI_WINDOW::create( int _x, int _y, int _w, int _h, int _flags )
261 {
262         x = _x;
263         y = _y;
264         w = _w;
265         h = _h;
266         flags = _flags;
267         first_gadget = NULL;
268         selected_gadget = NULL;
269         tooltip_handler = NULL;  // pointer to function to handle custom tooltips
270         ignore_gadgets = 0;
271         use_hack_to_get_around_stupid_problem_flag = 0;
272
273         f_id = gr_init_font("font01.vf");
274
275         if (_x < 0)
276                 _x = 0;
277         if (_x + _w - 1 >= gr_screen.max_w)
278                 _x = gr_screen.max_w - _w;
279         if (_y < 0)
280                 _y = 0;
281         if (_y + _h - 1 >= gr_screen.max_h)
282                 _y = gr_screen.max_h - _h;
283
284         game_flush();
285 }
286
287 void UI_WINDOW::release_bitmaps()
288 {
289         if (mask_bmap_ptr) {
290                 // done with the mask bitmap, so unlock it
291                 bm_unlock(mask_bmap_id);
292
293                 // unload the bitmaps
294                 if (mask_bmap_id >= 0) {
295                         bm_release(mask_bmap_id);
296                         mask_bmap_id = -1;
297                 }
298
299                 mask_bmap_ptr = NULL;
300         }
301
302         if (foreground_bmap_id >= 0) {
303                 bm_release(foreground_bmap_id);
304                 foreground_bmap_id = -1;
305         }
306 }
307
308 void UI_WINDOW::destroy()
309 {
310         UI_GADGET *cur;
311         int idx;
312
313         // free up any bitmaps
314         release_bitmaps();
315
316         // destroy all gadgets
317         if (first_gadget) {
318                 cur = first_gadget;
319                 do {
320                         cur->destroy();
321                         cur = cur->next;
322
323                 } while (cur != first_gadget);
324         }
325
326         // free up all xstrs
327         for(idx=0; idx<MAX_UI_XSTRS; idx++){
328                 // free up this struct
329                 if(xstrs[idx] != NULL){
330                         if(xstrs[idx]->xstr != NULL){
331                                 free((char *)xstrs[idx]->xstr);
332                         }
333                         free(xstrs[idx]);
334                         xstrs[idx] = NULL;
335                 }
336         }
337 }
338
339 void UI_WINDOW::draw()
340 {
341         UI_GADGET *tmp;
342
343         gr_reset_clip();
344         gr_set_font(f_id);
345
346         if (foreground_bmap_id >= 0) {
347                 gr_set_bitmap(foreground_bmap_id, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
348                 gr_bitmap(x, y);
349         }
350
351         if (flags & WIN_FILLED) {
352                 ui_draw_box_out(x, y, x+w-1, y+h-1);
353         }
354
355         if (flags & WIN_BORDER) {
356                 ui_draw_frame(x-BORDER_WIDTH, y-BORDER_WIDTH, x+w+BORDER_WIDTH-1, y+h+BORDER_WIDTH-1);
357         }
358
359         if (first_gadget) {
360                 tmp = first_gadget;
361                 do      {
362                         if (!tmp->hidden)
363                                 tmp->draw();
364
365                         tmp = tmp->next;
366
367                 } while (tmp != first_gadget);
368         }
369
370         if (first_gadget) {
371                 tmp = first_gadget;
372                 do      {
373                         if (!tmp->hidden && (tmp->kind == UI_KIND_BUTTON) && ((UI_BUTTON *) tmp)->button_down()){
374                                 tmp->draw();
375                         }
376
377                         tmp = tmp->next;
378                 } while (tmp != first_gadget);
379         }
380
381         // draw all xstrs
382         draw_xstrs();
383
384         // draw tooltips
385         draw_tooltip();
386
387         // convenient debug code for showing mouse coords
388         if(Cmdline_mouse_coords){
389                 int mx, my;
390                 mouse_get_pos(&mx, &my);
391                 // mprintf(("MOUSE (%d, %d)\n", mx, my));                                       
392                 gr_set_color_fast(&Color_normal);
393                 gr_printf(mx, my - 12, "%d %d", mx, my);
394         }       
395 }
396
397 void UI_WINDOW::draw_XSTR_forced(UI_GADGET *owner, int frame)
398 {
399         int idx;
400
401         // lookup the xstr and draw it if necessary
402         for(idx=0; idx<MAX_UI_XSTRS; idx++){
403                 if((xstrs[idx] != NULL) && (xstrs[idx]->assoc == owner)){
404                         draw_one_xstr(xstrs[idx], frame);                       
405                 }
406         }       
407 }
408
409 int UI_WINDOW::get_current_hotspot()
410 {
411         int offset, pixel_val;
412
413         if (!mask_data){
414                 return -1;
415         }
416
417         // check the pixel value under the mouse
418         offset = ui_mouse.y * gr_screen.max_w + ui_mouse.x;
419         pixel_val = *( ((ubyte*)mask_data) + offset);
420         return pixel_val;
421 }
422
423 void UI_WINDOW::draw_tooltip()
424 {
425         // int i;
426         // tooltip_group *ptr;
427         int hotspot;    
428         UI_GADGET *gadget;
429
430         if (tt_group < 0)
431                 return;
432
433         // ptr = &Tooltip_groups[tt_group];
434         hotspot = get_current_hotspot();
435
436 //      mprintf(("HOTSPOT: %d [%d]\n",hotspot, Framecount));
437
438         /*
439         if (hotspot != last_tooltip_hotspot) {
440                 last_tooltip_hotspot = hotspot;
441                 last_tooltip_time = timer_get_milliseconds();
442                 ttx = tty = -1;
443                 return;
444
445         } else if (timer_get_milliseconds() - last_tooltip_time < TOOLTIP_DELAY)
446                 return;
447         */
448
449         if (first_gadget) {
450                 gadget = first_gadget;
451                 do      {
452                         if (gadget->get_hotspot() == hotspot)
453                                 if (gadget->hidden)  // if control is hidden, don't draw tooltip for it.
454                                         return;
455                                 else
456                                         break;
457
458                         gadget = gadget->next;
459
460                 } while (gadget != first_gadget);
461         }
462
463         /*
464         for (i=ptr->start; i<ptr->end; i++) {
465                 if (Tooltips[i].hotspot == hotspot) {
466                         char *str;
467                         int w, h;
468
469                         str = Tooltips[i].text;
470                         if (str[0] == '@') {
471                                 if (!tooltip_handler)
472                                         Error(LOCATION, "No tooltip handler for screen with mask \"%s\"", ptr->mask);
473
474                                 str = (*tooltip_handler)(str);  // Let the screen handle the custom tooltips
475                                 if (!str)
476                                         return;
477                         }
478
479                         if (ttx < 0 || tty < 0) {
480                                 gr_get_string_size(&w, &h, str);
481                                 Assert(w < 320 && h < 100);
482                                 ttx = ui_mouse.x - w / 2;
483                                 tty = ui_mouse.y - h;
484                         }
485
486                         render_tooltip(str);
487                 }
488         }
489         */
490 }
491
492 void UI_WINDOW::render_tooltip(const char *str)
493 {
494         int w, h;
495
496         gr_get_string_size(&w, &h, str);
497         Assert(w < gr_screen.max_w - 4 && h < gr_screen.max_h - 4);
498
499         if (ttx < 2)
500                 ttx = 2;
501
502         if (tty < 2)
503                 tty = 2;
504
505         if (ttx + w + 2 > gr_screen.max_w)
506                 ttx = gr_screen.max_w - w;
507
508         if (tty + h + 2 > gr_screen.max_h)
509                 tty = gr_screen.max_h - h;
510
511         gr_set_color_fast(&Color_black);
512         gr_rect(ttx - 1, tty - 1, w + 2, h + 1);
513
514         gr_set_color_fast(&Color_bright_white);
515         gr_string(ttx, tty, str);
516 }
517
518 // key_in: If not -1, this means to use this key as input, and not call game_poll()
519 int UI_WINDOW::process(int key_in,int process_mouse)
520 {
521         UI_GADGET *tmp;
522
523         // only does stuff in non THREADED mode
524         os_poll();
525
526         if (process_mouse){
527                 ui_mouse_process();
528         }
529
530         if (key_in == -1){
531                 keypress = game_check_key();
532         } else {
533                 keypress = key_in;
534         }
535
536         last_keypress = keypress;
537         do_dump_check();
538         if (mouse_captured_gadget && B1_RELEASED){
539                 mouse_captured_gadget = NULL;
540         }
541
542         // The following code was commented out by NeilK on 4/15/99 to fix a problem we were having with
543         //      the UI_SLIDER2 class not receiving the process event when the mouse was dragging the scroller
544         // but outside the mask region. I checked a handful of other screens and so no adverse affects
545         // of this change at the time.
546
547 /*
548         if (mouse_captured_gadget) {
549                 mouse_captured_gadget->process();  // if a control has captured the mouse, only it gets processed
550                 use_hack_to_get_around_stupid_problem_flag = 0;
551                 return last_keypress;
552         }
553 */
554         if (!first_gadget) {
555                 use_hack_to_get_around_stupid_problem_flag = 0;
556                 return last_keypress;
557         }
558
559         check_focus_switch_keys();
560
561         // run through all top level gadgets and process them (they are responsible for processing
562         // their children, which UI_GADGET will handle if you don't override process() or if you
563         // do, you call UI_GADGET::process()).
564         if ( !ignore_gadgets ) {
565                 tmp = first_gadget;
566                 do      {
567                         if ( !tmp->check_move() )
568                                 tmp->process();
569
570                         tmp = tmp->next;
571
572                 } while (tmp != first_gadget);
573         }
574
575         use_hack_to_get_around_stupid_problem_flag = 0;
576         return last_keypress;
577 }
578
579 void UI_WINDOW::check_focus_switch_keys()
580 {
581         return;
582 }
583
584 void UI_WINDOW::capture_mouse(UI_GADGET *gadget)
585 {
586         mouse_captured_gadget = gadget;
587 }
588
589 void UI_WINDOW::set_ignore_gadgets(int state)
590 {
591         ignore_gadgets = state;
592 }
593
594 void UI_WINDOW::add_XSTR(const char *string, int _xstr_id, int _x, int _y, UI_GADGET *_assoc, int _color_type, int _font_id)
595 {
596         int idx;
597         int found = -1;
598         UI_XSTR *x;
599
600         // try and find a free xstr
601         for(idx=0; idx<MAX_UI_XSTRS; idx++){
602                 if(xstrs[idx] == NULL){
603                         found = idx;
604                         break;
605                 }
606         }
607
608         // if we don't have a free spot
609         if(found < 0){
610                 Int3();                 // aieee! we need to up the max # of xstrs allowed in a window.
611                 return;
612         }
613
614         // allocate a new struct
615         xstrs[idx] = (UI_XSTR*)malloc(sizeof(UI_XSTR));
616         if(xstrs[idx] == NULL){
617                 return;
618         }
619         x = xstrs[idx]; 
620
621         // fill in the data
622         x->xstr = strdup(string);               
623         if(x->xstr == NULL){
624                 free(x);
625                 xstrs[idx] = NULL;
626                 return;
627         }
628         x->xstr_id = _xstr_id;
629         x->x = _x;
630         x->y = _y;
631         x->assoc = _assoc;
632         x->font_id = _font_id;  
633         x->clr = _color_type;
634         Assert((x->clr >= 0) && (x->clr < UI_NUM_XSTR_COLORS));
635         if((x->clr < 0) || (x->clr >= UI_NUM_XSTR_COLORS)){
636                 x->clr = 0;
637         }       
638 }
639
640 void UI_WINDOW::add_XSTR(UI_XSTR *xstr)
641 {
642         int idx;
643         int found = -1;
644         UI_XSTR *x;
645
646         // try and find a free xstr
647         for(idx=0; idx<MAX_UI_XSTRS; idx++){
648                 if(xstrs[idx] == NULL){
649                         found = idx;
650                         break;
651                 }
652         }
653
654         // if we don't have a free spot
655         if(found < 0){
656                 Int3();                 // aieee! we need to up the max # of xstrs allowed in a window.
657                 return;
658         }
659
660         // allocate a new struct
661         xstrs[idx] = (UI_XSTR*)malloc(sizeof(UI_XSTR));
662         if(xstrs[idx] == NULL){
663                 return;
664         }
665         x = xstrs[idx]; 
666
667         // fill in the data
668         x->xstr = strdup(xstr->xstr);
669         if(x->xstr == NULL){
670                 free(x);
671                 xstrs[idx] = NULL;
672                 return;
673         }
674         x->xstr_id = xstr->xstr_id;
675         x->x = xstr->x;
676         x->y = xstr->y;
677         x->assoc = xstr->assoc;
678         x->font_id = xstr->font_id;     
679         x->clr = xstr->clr;
680         Assert((x->clr >= 0) && (x->clr < UI_NUM_XSTR_COLORS));
681         if((x->clr < 0) || (x->clr >= UI_NUM_XSTR_COLORS)){
682                 x->clr = 0;
683         }       
684 }
685
686 void UI_WINDOW::draw_one_xstr(UI_XSTR *x, int frame)
687 {
688         font *f_backup = NULL;          
689         char str[255] = "";
690
691         // sanity
692         if((x == NULL) || (x->xstr == NULL)){
693                 return;
694         }
695
696         // if it has an associated gadet that is hidden, do nothing
697         if((x->assoc != NULL) && (x->assoc->hidden)){
698                 return;
699         }
700         
701         // maybe set the font
702         if(x->font_id >= 0){
703                 // backup the current font
704                 Assert(Current_font != NULL);
705                 f_backup = Current_font;
706
707                 // set the new font
708                 gr_set_font(x->font_id);
709         }
710
711         // set the color
712         if(x->assoc == NULL){                   
713                 gr_set_color_fast(&Color_normal);
714         } else {
715                 // just buttons for now
716                 switch(x->assoc->kind){
717                 case UI_KIND_BUTTON:                                    
718                         // override case
719                         if((frame != -1) && (frame < 3)){
720                                 gr_set_color_fast(Xstr_colors[x->clr][frame]);
721                         }
722                         // normal checking
723                         else {
724                                 // if the button is pressed
725                                 if(((UI_BUTTON*)x->assoc)->button_down()){
726                                         gr_set_color_fast(Xstr_colors[x->clr][2]);
727                                 } 
728                                 // if the mouse is just over it
729                                 else if(x->assoc->is_mouse_on()){
730                                         gr_set_color_fast(Xstr_colors[x->clr][1]);
731                                 } else {
732                                         gr_set_color_fast(Xstr_colors[x->clr][0]);
733                                 }
734                                 break;
735                         }
736                         break;
737
738                 // all other controls just draw the normal frame
739                 default :
740                         if((frame != -1) && (frame < 3)){
741                                 gr_set_color_fast(Xstr_colors[x->clr][frame]);
742                         } else {
743                                 gr_set_color_fast(Xstr_colors[x->clr][0]);
744                         }
745                         break;
746                 }               
747
748                 // if the gadget disabled, just draw the normal nonhighlighted frame
749                 if(x->assoc->disabled()){
750                         gr_set_color_fast(Xstr_colors[x->clr][0]);
751                 }
752         }
753
754         // print this puppy out 
755         int xoffset = lcl_get_xstr_offset(x->xstr_id, gr_screen.res);
756         strncpy(str, XSTR(x->xstr, x->xstr_id), 254);
757         if(str[0] == '&'){
758                 if(strlen(str) > 1){                    
759                         gr_string((x->x) + xoffset, x->y, str + 1);
760                 }
761         } else {
762                 gr_string((x->x) + xoffset, x->y, str);
763         }
764
765         // maybe restore the old font
766         if(f_backup != NULL){
767                 Current_font = f_backup;
768         }                       
769 }
770
771 void UI_WINDOW::draw_xstrs()
772 {
773         int idx = 0;
774         
775         // draw the xstrs
776         do {
777                 draw_one_xstr(xstrs[idx], -1);          
778
779                 // next xstr
780                 idx++;
781         } while(idx < MAX_UI_XSTRS);
782 }
783
784 // TEST CODE 
785
786 void UI_WINDOW::do_dump_check()
787 {
788 #if 0
789         if ( keypress == KEY_SHIFTED+KEY_CTRLED+KEY_ALTED+KEY_F12 ) {
790                 FILE *fp;
791
792                 last_keypress = keypress = 0;
793
794                 mprintf(( "\n========== WINDOW GADGETS =========\n" ));
795                 mprintf(( "(Also dumped to ui.out)\n" ));
796
797                 fp = fopen( "ui.out", "wt" );
798                 tmp = first_gadget;
799                 do      {
800                         if ( tmp->parent == NULL ) {    
801                                 switch ( tmp->kind ) {
802                                 case UI_KIND_BUTTON:
803                                         mprintf(( "UI: Button at %d,%d\n", tmp->x, tmp->y ));
804                                         fprintf( fp, "UI: Button at %d,%d\n", tmp->x, tmp->y );
805                                         break;
806                                 case UI_KIND_KEYTRAP:
807                                         mprintf(( "UI: Keytrap at %d,%d\n", tmp->x, tmp->y ));
808                                         fprintf( fp, "UI: Keytrap at %d,%d\n", tmp->x, tmp->y );
809                                         break;
810                                 case UI_KIND_CHECKBOX:
811                                         mprintf(( "UI: Checkbox at %d,%d\n", tmp->x, tmp->y ));
812                                         fprintf( fp, "UI: Checkbox at %d,%d\n", tmp->x, tmp->y );
813                                         break;
814                                 case UI_KIND_RADIO:
815                                         mprintf(( "UI: Radiobutton at %d,%d\n", tmp->x, tmp->y ));
816                                         fprintf( fp, "UI: Radiobutton at %d,%d\n", tmp->x, tmp->y );
817                                         break;
818                                 case UI_KIND_SCROLLBAR:
819                                         mprintf(( "UI: Scrollbar at %d,%d\n", tmp->x, tmp->y ));
820                                         fprintf( fp, "UI: Scrollbar at %d,%d\n", tmp->x, tmp->y );
821                                         break;
822                                 case UI_KIND_LISTBOX:
823                                         mprintf(( "UI: Listbox at %d,%d\n", tmp->x, tmp->y ));
824                                         fprintf( fp, "UI: Listbox at %d,%d\n", tmp->x, tmp->y );
825                                         break;
826                                 case UI_KIND_INPUTBOX:
827                                         mprintf(( "UI: Inputbox at %d,%d\n", tmp->x, tmp->y ));
828                                         fprintf( fp, "UI: Inputbox at %d,%d\n", tmp->x, tmp->y );
829                                         break;
830                                 default:
831                                         mprintf(( "UI: Unknown type %d at %d,%d\n", tmp->kind, tmp->x, tmp->y ));
832                                         fprintf( fp, "UI: Unknown type %d at %d,%d\n", tmp->kind, tmp->x, tmp->y );
833                                 }
834                         }
835                         tmp = tmp->next;
836                 } while( tmp != first_gadget );
837                 fclose(fp);
838                 mprintf(( "===================================\n" ));
839         }
840 #endif
841 }
842
843 /*
844 void parse_tooltip(int n)
845 {
846         char buf[MESSAGE_LENGTH];
847
848         stuff_int(&Tooltips[n].hotspot);
849         stuff_string(buf, F_MESSAGE, NULL);
850         Tooltips[n].text = strdup(buf);
851 }
852
853 int parse_tooltips_group(int group, int n)
854 {
855         char buf[NAME_LENGTH];
856
857         Assert(group < MAX_TOOLTIP_GROUPS);
858         required_string("$Mask Filename:");
859         stuff_string(buf, F_NAME, NULL);
860         Tooltip_groups[group].mask = strdup(buf);
861         Tooltip_groups[group].start = n;
862
863         while (1) {
864                 if (check_for_string("#") || check_for_string("$")) {
865                         Tooltip_groups[group].end = n;
866                         return n;
867                 }
868
869                 Assert(n < MAX_TOOLTIPS);
870                 parse_tooltip(n++);
871         }
872 }
873
874 void parse_ship_tooltip(int n)
875 {
876 }
877
878 void parse_weapon_tooltip(int n)
879 {
880 }
881
882 void parse_tooltips()
883 {
884         int n;
885
886         // open localization
887         lcl_ext_open();
888
889         read_file_text("tooltips.tbl");
890
891         n = Num_tooltip_groups = 0;
892         reset_parse();
893
894         if (optional_string("#UI"))
895                 while (required_string_either("#", "$")) {
896                         n = parse_tooltips_group(Num_tooltip_groups, n);
897                         Num_tooltip_groups++;
898                 }
899
900         if (optional_string("#Ships"))
901                 while (required_string_either("#", "$")) {
902                         parse_ship_tooltip(Num_ship_tooltips);
903                         Num_ship_tooltips++;
904                 }
905
906         if (optional_string("#Weapons"))
907                 while (required_string_either("#", "$")) {
908                         parse_ship_tooltip(Num_weapon_tooltips);
909                         Num_weapon_tooltips++;
910                 }
911
912         required_string("#End");
913
914         // close localization
915         lcl_ext_close();
916 }
917
918 void init_tooltips()
919 {
920         static int inited = 0;
921
922         if (!inited) {
923                 int rval;
924
925                 if ((rval = setjmp(parse_abort)) != 0) {
926
927                 } else {                        
928 #ifndef DEMO
929                         parse_tooltips();
930 #endif
931                 }
932
933                 inited = 1;
934         }
935 }
936 */
937
938 void ok_clicked()
939 {
940         mprintf(( "OK Clicked!\n" ));
941 }
942
943 void do_help()
944 {
945         mprintf(( "Help!\n" ));
946 }
947