ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/sdlgui.cpp
Revision: 1.1
Committed: 2007-01-28T16:48:28Z (17 years, 2 months ago) by berlac
Branch: MAIN
Log Message:
Initial revision.

File Contents

# Content
1 /*
2 * sdlgui.cpp
3 *
4 * This file is taken from the ARAnyM project which builds a new and powerful
5 * TOS/FreeMiNT compatible virtual machine running on almost any hardware.
6 *
7 * Copyright (c) 2001 Thomas Huth - taken from his hatari project
8 * Copyright (c) 2002-2005 Petr Stehlik of ARAnyM dev team (see AUTHORS)
9 *
10 * It is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with Frodo; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19
20 #include "sysdeps.h"
21 #include "sdlgui.h"
22 #include "file.h"
23 #include "debug.h"
24
25 #include <cstdlib>
26
27 #include "font8.h"
28
29 static SDL_Surface *mainsurface = NULL;
30 #define sdlscrn mainsurface
31
32 static SDL_Surface *fontgfx=NULL;
33 static int fontwidth, fontheight; /* Height and width of the actual font */
34
35 // Stores current dialog coordinates
36 static SDL_Rect DialogRect = {0, 0, 0, 0};
37
38 // Used by SDLGui_Get[First|Next]BackgroundRect()
39 static SDL_Rect BackgroundRect = {0, 0, 0, 0};
40 static int BackgroundRectCounter;
41 enum
42 {
43 SG_BCKGND_RECT_BEGIN,
44 SG_BCKGND_RECT_TOP,
45 SG_BCKGND_RECT_LEFT,
46 SG_BCKGND_RECT_RIGHT,
47 SG_BCKGND_RECT_BOTTOM,
48 SG_BCKGND_RECT_END
49 };
50
51 SDL_Color blackc[] = {{0, 0, 0, 0}};
52 SDL_Color darkgreyc[] = {{128, 128, 128, 0}};
53 SDL_Color greyc[] = {{192, 192, 192, 0}};
54 SDL_Color whitec[] = {{255, 255, 255, 0}};
55
56 enum
57 {
58 SG_FIRST_EDITFIELD,
59 SG_PREVIOUS_EDITFIELD,
60 SG_NEXT_EDITFIELD,
61 SG_LAST_EDITFIELD
62 };
63
64 /*-----------------------------------------------------------------------*/
65 /*
66 Load an 1 plane XBM into a 8 planes SDL_Surface.
67 */
68 static SDL_Surface *SDLGui_LoadXBM(int w, int h, Uint8 *srcbits)
69 {
70 SDL_Surface *bitmap;
71 Uint8 *dstbits;
72 int x, y, srcpitch;
73
74 /* Allocate the bitmap */
75 bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0);
76 if ( bitmap == NULL )
77 {
78 // TODO panicbug("Couldn't allocate bitmap: %s", SDL_GetError());
79 return(NULL);
80 }
81
82 srcpitch = ((w + 7) / 8);
83 dstbits = (Uint8 *)bitmap->pixels;
84 int mask = 1;
85
86 /* Copy the pixels */
87 for (y = 0 ; y < h ; y++)
88 {
89 for (x = 0 ; x < w ; x++)
90 {
91 dstbits[x] = (srcbits[x / 8] & mask) ? 1 : 0;
92 mask <<= 1;
93 mask |= (mask >> 8);
94 mask &= 0xFF;
95 }
96 dstbits += bitmap->pitch;
97 srcbits += srcpitch;
98 }
99
100 return(bitmap);
101 }
102
103 /*-----------------------------------------------------------------------*/
104 /*
105 Initialize the GUI.
106 */
107 bool SDLGui_Init(SDL_Surface *GUISurface)
108 {
109 mainsurface = GUISurface;
110 /* Load the font graphics: */
111 fontgfx = SDLGui_LoadXBM(font8_width, font8_height, font8_bits);
112 if (fontgfx == NULL)
113 {
114 // TODO panicbug("Could not create font data");
115 // TODO panicbug("ARAnyM GUI will not be available");
116 return false;
117 }
118
119 /* Set font color 0 as transparent */
120 SDL_SetColorKey(fontgfx, SDL_SRCCOLORKEY, 0);
121
122 /* Get the font width and height: */
123 fontwidth = fontgfx->w/16;
124 fontheight = fontgfx->h/16;
125
126 return true;
127 }
128
129
130 /*-----------------------------------------------------------------------*/
131 /*
132 Uninitialize the GUI.
133 */
134 int SDLGui_UnInit()
135 {
136 if (fontgfx)
137 {
138 SDL_FreeSurface(fontgfx);
139 fontgfx = NULL;
140 }
141
142 return 0;
143 }
144
145
146 /*-----------------------------------------------------------------------*/
147 /*
148 Compute real coordinates for a given object.
149 Note: centers dialog on screen.
150 */
151 static void SDLGui_ObjCoord(SGOBJ *dlg, int objnum, SDL_Rect *rect)
152 {
153 rect->x = dlg[objnum].x * fontwidth;
154 rect->y = dlg[objnum].y * fontheight;
155 rect->w = dlg[objnum].w * fontwidth;
156 rect->h = dlg[objnum].h * fontheight;
157
158 rect->x += (sdlscrn->w - (dlg[0].w * fontwidth)) / 2;
159 rect->y += (sdlscrn->h - (dlg[0].h * fontheight)) / 2;
160 }
161
162
163 /*-----------------------------------------------------------------------*/
164 /*
165 Compute real coordinates for a given object.
166 This one takes borders into account and give coordinates as seen by user
167 */
168 void SDLGui_ObjFullCoord(SGOBJ *dlg, int objnum, SDL_Rect *coord)
169 {
170 SDLGui_ObjCoord(dlg, objnum, coord);
171
172 switch (dlg[objnum].type)
173 {
174 case SGBOX:
175 case SGBUTTON:
176 {
177 // Take border into account
178 int border_size;
179
180 if (dlg[objnum].flags & SG_SELECTABLE)
181 {
182 if (dlg[objnum].flags & SG_DEFAULT)
183 border_size = 4;
184 else
185 border_size = 3;
186 }
187 else
188 {
189 if (dlg[objnum].flags & SG_BACKGROUND)
190 border_size = 6;
191 else
192 border_size = 5;
193 }
194
195 coord->x -= border_size;
196 coord->y -= border_size;
197 coord->w += (border_size * 2);
198 coord->h += (border_size * 2);
199 }
200 break;
201 case SGEDITFIELD:
202 // Allow one more pixel to the right for cursor
203 coord->w += 1;
204 // There is a line below
205 coord->h += 1;
206 break;
207 }
208 }
209
210
211 /*-----------------------------------------------------------------------*/
212 /*
213 Refresh display at given coordinates.
214 Unlike SDL_UpdateRect() this function can eat coords that goes beyond screen
215 boundaries.
216 "rect" will be modified to represent the area actually refreshed.
217 */
218 void SDLGui_UpdateRect(SDL_Rect *rect)
219 {
220 if (rect->x < 0)
221 {
222 rect->w += rect->x;
223 rect->x = 0;
224 }
225 if ((rect->x + rect->w) > sdlscrn->w)
226 rect->w = (sdlscrn->w - rect->x);
227
228 if (rect->y < 0)
229 {
230 rect->h += rect->y;
231 rect->y = 0;
232 }
233 if ((rect->y + rect->h) > sdlscrn->h)
234 rect->h = (sdlscrn->h - rect->y);
235
236 if ((rect->w > 0) && (rect->h > 0))
237 SDL_UpdateRects(sdlscrn, 1, rect);
238 else
239 {
240 rect->x = 0;
241 rect->y = 0;
242 rect->w = 0;
243 rect->h = 0;
244 }
245 }
246
247
248 /*-----------------------------------------------------------------------*/
249 /*
250 Maps an SDL_Color to the screen format.
251 */
252 Uint32 SDLGui_MapColor(SDL_Color *color)
253 {
254 return SDL_MapRGB(sdlscrn->format, color->r, color->g, color->b);
255 }
256
257
258 /*-----------------------------------------------------------------------*/
259 /*
260 Refresh display to reflect an object change.
261 */
262 void SDLGui_RefreshObj(SGOBJ *dlg, int objnum)
263 {
264 SDL_Rect coord;
265
266 SDLGui_ObjFullCoord(dlg, objnum, &coord);
267
268 SCRLOCK;
269 SDLGui_UpdateRect(&coord);
270 SCRUNLOCK;
271 }
272
273
274 /*-----------------------------------------------------------------------*/
275 /*
276 Draw a text string.
277 */
278 void SDLGui_Text(int x, int y, const char *txt, SDL_Color *col)
279 {
280 int i;
281 char c;
282 SDL_Rect sr, dr;
283
284 SDL_SetColors(fontgfx, col, 1, 1);
285
286 SCRLOCK;
287 for (i = 0 ; txt[i] != 0 ; i++)
288 {
289 c = txt[i];
290 sr.x = fontwidth * (c % 16);
291 sr.y = fontheight * (c / 16);
292 sr.w = fontwidth;
293 sr.h = fontheight;
294
295 dr.x = x + (fontwidth * i);
296 dr.y = y;
297 dr.w = fontwidth;
298 dr.h = fontheight;
299
300 SDL_BlitSurface(fontgfx, &sr, sdlscrn, &dr);
301 }
302 SCRUNLOCK;
303 }
304
305
306 /*-----------------------------------------------------------------------*/
307 /*
308 Draw a dialog text object.
309 */
310 void SDLGui_DrawText(SGOBJ *tdlg, int objnum)
311 {
312 SDL_Rect coord;
313 SDL_Color *textc, *backgroundc;
314
315 if (tdlg[objnum].state & SG_SELECTED)
316 {
317 textc = whitec;
318 backgroundc = darkgreyc;
319 }
320 else if (tdlg[objnum].state & SG_DISABLED)
321 {
322 textc = darkgreyc;
323 backgroundc = greyc;
324 }
325 else
326 {
327 textc = blackc;
328 backgroundc = greyc;
329 }
330
331 SDLGui_ObjCoord(tdlg, objnum, &coord);
332 SDL_FillRect(sdlscrn, &coord, SDLGui_MapColor(backgroundc));
333 SDLGui_Text(coord.x, coord.y, tdlg[objnum].txt, textc);
334 }
335
336
337 /*-----------------------------------------------------------------------*/
338 /*
339 Draw an edit field object.
340 */
341 void SDLGui_DrawEditField(SGOBJ *edlg, int objnum)
342 {
343 SDL_Rect coord;
344 SDL_Color *textc;
345
346 if (edlg[objnum].state & SG_DISABLED)
347 textc = darkgreyc;
348 else
349 textc = blackc;
350
351 SDLGui_ObjCoord(edlg, objnum, &coord);
352 coord.w += 1;
353 SDL_FillRect(sdlscrn, &coord, SDLGui_MapColor(greyc));
354 SDLGui_Text(coord.x, coord.y, edlg[objnum].txt, textc);
355
356 // Draw a line below.
357 coord.y = coord.y + coord.h;
358 coord.h = 1;
359 SDL_FillRect(sdlscrn, &coord, SDLGui_MapColor(darkgreyc));
360 }
361
362
363 /*-----------------------------------------------------------------------*/
364 /*
365 Draw or erase cursor.
366 */
367 void SDLGui_DrawCursor(SGOBJ *dlg, cursor_state *cursor)
368 {
369 if (cursor->object != -1)
370 {
371 SDL_Rect coord;
372 SDL_Color *cursorc;
373
374 SDLGui_DrawEditField(dlg, cursor->object);
375
376 if (cursor->blink_state)
377 cursorc = blackc;
378 else
379 cursorc = greyc;
380
381 SDLGui_ObjCoord(dlg, cursor->object, &coord);
382 coord.x += (cursor->position * fontwidth);
383 coord.w = 1;
384 SDL_FillRect(sdlscrn, &coord, SDLGui_MapColor(cursorc));
385
386 SDLGui_RefreshObj(dlg, cursor->object);
387 }
388 }
389
390
391 /*-----------------------------------------------------------------------*/
392 /*
393 Draw a 3D effect around a given rectangle.
394 Rectangle is updated to the full size of the new object.
395 */
396 void SDLGui_Draw3DAround(SDL_Rect *coord, SDL_Color *upleftc, SDL_Color *downrightc, SDL_Color *cornerc, int width)
397 {
398 SDL_Rect rect;
399 int i;
400 Uint32 upleftcol = SDLGui_MapColor(upleftc);
401 Uint32 downrightcol = SDLGui_MapColor(downrightc);
402 Uint32 cornercol = SDLGui_MapColor(cornerc);
403
404 SCRLOCK;
405
406 for ( i = 1 ; i <= width ; i++)
407 {
408 rect.x = coord->x - i;
409 rect.y = coord->y - i;
410 rect.w = coord->w + (i * 2) - 1;
411 rect.h = 1;
412 SDL_FillRect(sdlscrn, &rect, upleftcol);
413
414 rect.x = coord->x - i;
415 rect.y = coord->y - i;
416 rect.w = 1;
417 rect.h = coord->h + (i * 2) - 1;
418 SDL_FillRect(sdlscrn, &rect, upleftcol);
419
420 rect.x = coord->x - i + 1;
421 rect.y = coord->y + coord->h - 1 + i;
422 rect.w = coord->w + (i * 2) - 1;
423 rect.h = 1;
424 SDL_FillRect(sdlscrn, &rect, downrightcol);
425
426 rect.x = coord->x + coord->w - 1 + i;
427 rect.y = coord->y - i + 1;
428 rect.w = 1;
429 rect.h = coord->h + (i * 2) - 1;
430 SDL_FillRect(sdlscrn, &rect, downrightcol);
431
432 rect.x = coord->x + coord->w + i - 1;
433 rect.y = coord->y - i;
434 rect.w = 1;
435 rect.h = 1;
436 SDL_FillRect(sdlscrn, &rect, cornercol);
437
438 rect.x = coord->x - i;
439 rect.y = coord->y + coord->h + i - 1;
440 rect.w = 1;
441 rect.h = 1;
442 SDL_FillRect(sdlscrn, &rect, cornercol);
443 }
444
445 SCRUNLOCK;
446
447 coord->x -= width;
448 coord->y -= width;
449 coord->w += (width * 2);
450 coord->h += (width * 2);
451 }
452
453
454 /*-----------------------------------------------------------------------*/
455 /*
456 Draw a colored box around a given rectangle.
457 Rectangle is updated to the full size of the new object.
458 */
459 void SDLGui_DrawBoxAround(SDL_Rect *coord, SDL_Color *color, int width)
460 {
461 SDL_Rect rect;
462 Uint32 col = SDLGui_MapColor(color);
463
464 SCRLOCK;
465
466 rect.x = coord->x - width;
467 rect.y = coord->y - width;
468 rect.w = coord->w + (width * 2);
469 rect.h = width;
470 SDL_FillRect(sdlscrn, &rect, col);
471
472 rect.x = coord->x - width;
473 rect.y = coord->y - width;
474 rect.w = width;
475 rect.h = coord->h + (width * 2);
476 SDL_FillRect(sdlscrn, &rect, col);
477
478 rect.x = coord->x + coord->w;
479 rect.y = coord->y - width;
480 rect.w = width;
481 rect.h = coord->h + (width * 2);
482 SDL_FillRect(sdlscrn, &rect, col);
483
484 rect.x = coord->x - width;
485 rect.y = coord->y + coord->h;
486 rect.w = coord->w + (width * 2);
487 rect.h = width;
488 SDL_FillRect(sdlscrn, &rect, col);
489
490 SCRUNLOCK;
491
492 coord->x -= width;
493 coord->y -= width;
494 coord->w += (width * 2);
495 coord->h += (width * 2);
496 }
497
498
499 /*-----------------------------------------------------------------------*/
500 /*
501 Draw a 3D box with given attributes.
502 */
503 void SDLGui_Draw3DBox(SDL_Rect *coord,
504 SDL_Color *backgroundc,
505 SDL_Color *inboxc,
506 SDL_Color *upleftc,
507 SDL_Color *downrightc,
508 SDL_Color *outboxc,
509 int widthbackground,
510 int widthinbox,
511 int width3D1,
512 int width3D2,
513 int widthoutbox)
514 {
515 SDL_Rect rect;
516
517 SCRLOCK;
518
519 // Draw background
520 rect.x = coord->x - widthbackground;
521 rect.y = coord->y - widthbackground;
522 rect.w = coord->w + (widthbackground * 2);
523 rect.h = coord->h + (widthbackground * 2);
524 SDL_FillRect(sdlscrn, &rect, SDLGui_MapColor(backgroundc));
525
526 SCRUNLOCK;
527
528 // Update coords
529 coord->x -= widthbackground;
530 coord->y -= widthbackground;
531 coord->w += (widthbackground * 2);
532 coord->h += (widthbackground * 2);
533
534 if (widthinbox > 0)
535 SDLGui_DrawBoxAround(coord, inboxc, widthinbox);
536
537 if (width3D1 > 0)
538 SDLGui_Draw3DAround(coord, upleftc, downrightc, backgroundc, width3D1);
539
540 if (width3D2 > 0)
541 SDLGui_Draw3DAround(coord, downrightc, upleftc, backgroundc, width3D2);
542
543 if (widthoutbox > 0)
544 SDLGui_DrawBoxAround(coord, outboxc, widthoutbox);
545 }
546
547
548 /*-----------------------------------------------------------------------*/
549 /*
550 Draw a dialog box object.
551 */
552 void SDLGui_DrawBox(SGOBJ *bdlg, int objnum)
553 {
554 SDL_Rect coord;
555 SDL_Color *my_blackc;
556 SDL_Color *upleftc, *downrightc;
557
558 SDLGui_ObjCoord(bdlg, objnum, &coord);
559
560 // Modify box drawing according to object state
561 if (bdlg[objnum].state & SG_DISABLED)
562 my_blackc = darkgreyc;
563 else
564 my_blackc = blackc;
565
566 if (bdlg[objnum].state & SG_SELECTED)
567 {
568 upleftc = darkgreyc;
569 downrightc = whitec;
570 }
571 else
572 {
573 upleftc = whitec;
574 downrightc = darkgreyc;
575 }
576
577 // Draw box according to object flags
578 switch (bdlg[objnum].flags & (SG_SELECTABLE | SG_DEFAULT | SG_BACKGROUND))
579 {
580 case (SG_SELECTABLE | SG_DEFAULT | SG_BACKGROUND):
581 case (SG_SELECTABLE | SG_DEFAULT):
582 SDLGui_Draw3DBox(&coord,
583 greyc, NULL, upleftc, downrightc, my_blackc,
584 1, 0, 1, 0, 2);
585 break;
586 case (SG_SELECTABLE | SG_BACKGROUND):
587 case SG_SELECTABLE:
588 SDLGui_Draw3DBox(&coord,
589 greyc, NULL, upleftc, downrightc, my_blackc,
590 1, 0, 1, 0, 1);
591 break;
592 case (SG_DEFAULT | SG_BACKGROUND):
593 case SG_BACKGROUND:
594 SDLGui_Draw3DBox(&coord,
595 greyc, my_blackc, upleftc, downrightc, darkgreyc,
596 0, 2, 3, 0, 1);
597 break;
598 case SG_DEFAULT:
599 case 0:
600 SDLGui_Draw3DBox(&coord,
601 greyc, NULL, upleftc, downrightc, NULL,
602 3, 0, 1, 1, 0);
603 break;
604 }
605 }
606
607
608 /*-----------------------------------------------------------------------*/
609 /*
610 Draw a normal button.
611 */
612 void SDLGui_DrawButton(SGOBJ *bdlg, int objnum)
613 {
614 SDL_Rect coord;
615 int x, y;
616 SDL_Color *textc;
617
618 SDLGui_ObjCoord(bdlg, objnum, &coord);
619
620 x = coord.x + ((coord.w - (strlen(bdlg[objnum].txt) * fontwidth)) / 2);
621 y = coord.y + ((coord.h - fontheight) / 2);
622
623 if (bdlg[objnum].state & SG_SELECTED)
624 {
625 x += 1;
626 y += 1;
627 }
628
629 if (bdlg[objnum].state & SG_DISABLED)
630 textc = darkgreyc;
631 else
632 textc = blackc;
633
634 SDLGui_DrawBox(bdlg, objnum);
635 SDLGui_Text(x, y, bdlg[objnum].txt, textc);
636 }
637
638
639 /*-----------------------------------------------------------------------*/
640 /*
641 Draw a dialog check box object state.
642 */
643 void SDLGui_DrawCheckBoxState(SGOBJ *cdlg, int objnum)
644 {
645 Uint32 grey = SDLGui_MapColor(greyc);
646 SDL_Rect coord;
647 char str[2];
648 SDL_Color *textc;
649
650 SDLGui_ObjCoord(cdlg, objnum, &coord);
651
652 if (cdlg[objnum].flags & SG_RADIO)
653 {
654 if (cdlg[objnum].state & SG_SELECTED)
655 str[0]=SGCHECKBOX_RADIO_SELECTED;
656 else
657 str[0]=SGCHECKBOX_RADIO_NORMAL;
658 }
659 else
660 {
661 if (cdlg[objnum].state & SG_SELECTED)
662 str[0]=SGCHECKBOX_SELECTED;
663 else
664 str[0]=SGCHECKBOX_NORMAL;
665 }
666
667 if (cdlg[objnum].state & SG_DISABLED)
668 textc = darkgreyc;
669 else
670 textc = blackc;
671
672 str[1]='\0';
673
674 coord.w = fontwidth;
675 coord.h = fontheight;
676
677 if (cdlg[objnum].flags & SG_BUTTON_RIGHT)
678 coord.x += ((strlen(cdlg[objnum].txt) + 1) * fontwidth);
679
680 SDL_FillRect(sdlscrn, &coord, grey);
681 SDLGui_Text(coord.x, coord.y, str, textc);
682 }
683
684
685 /*-----------------------------------------------------------------------*/
686 /*
687 Draw a dialog check box object.
688 */
689 void SDLGui_DrawCheckBox(SGOBJ *cdlg, int objnum)
690 {
691 SDL_Rect coord;
692 SDL_Color *textc;
693
694 SDLGui_ObjCoord(cdlg, objnum, &coord);
695
696 if (!(cdlg[objnum].flags&SG_BUTTON_RIGHT))
697 coord.x += (fontwidth * 2);
698
699 if (cdlg[objnum].state & SG_DISABLED)
700 textc = darkgreyc;
701 else
702 textc = blackc;
703
704 SDLGui_Text(coord.x, coord.y, cdlg[objnum].txt, textc);
705 SDLGui_DrawCheckBoxState(cdlg, objnum);
706 }
707
708
709 /*-----------------------------------------------------------------------*/
710 /*
711 Draw a dialog popup button object.
712 */
713 void SDLGui_DrawPopupButton(SGOBJ *pdlg, int objnum)
714 {
715 SDL_Rect coord;
716 const char *downstr = "\x02";
717 SDL_Color *textc;
718
719 if (pdlg[objnum].state & SG_DISABLED)
720 textc = darkgreyc;
721 else
722 textc = blackc;
723
724 SDLGui_DrawBox(pdlg, objnum);
725
726 SDLGui_ObjCoord(pdlg, objnum, &coord);
727
728 SDLGui_Text(coord.x, coord.y, pdlg[objnum].txt, textc);
729 SDLGui_Text(coord.x+coord.w-fontwidth, coord.y, downstr, textc);
730 }
731
732
733 /*-----------------------------------------------------------------------*/
734 /*
735 Draw an object.
736 */
737 void SDLGui_DrawObject(SGOBJ *dlg, int objnum)
738 {
739 switch (dlg[objnum].type)
740 {
741 case SGBOX:
742 SDLGui_DrawBox(dlg, objnum);
743 break;
744 case SGTEXT:
745 SDLGui_DrawText(dlg, objnum);
746 break;
747 case SGEDITFIELD:
748 SDLGui_DrawEditField(dlg, objnum);
749 break;
750 case SGBUTTON:
751 SDLGui_DrawButton(dlg, objnum);
752 break;
753 case SGCHECKBOX:
754 SDLGui_DrawCheckBox(dlg, objnum);
755 break;
756 case SGPOPUP:
757 SDLGui_DrawPopupButton(dlg, objnum);
758 break;
759 }
760 }
761
762
763 /*-----------------------------------------------------------------------*/
764 /*
765 Draw a whole dialog.
766 */
767 void SDLGui_DrawDialog(SGOBJ *dlg)
768 {
769 int i;
770
771 // Store dialog coordinates
772 SDLGui_ObjFullCoord(dlg, 0, &DialogRect);
773
774 for (i = 0 ; dlg[i].type != -1 ; i++)
775 {
776 if (dlg[i].state & SG_HIDDEN) continue;
777 SDLGui_DrawObject(dlg, i);
778 }
779 SDLGui_RefreshObj(dlg, 0);
780 }
781
782
783 /*-----------------------------------------------------------------------*/
784 /*
785 Search default object in a dialog.
786 */
787 int SDLGui_FindDefaultObj(SGOBJ *dlg)
788 {
789 int i = 0;
790
791 while (dlg[i].type != -1)
792 {
793 if (dlg[i].flags & SG_DEFAULT)
794 return i;
795 i++;
796 }
797
798 return -1;
799 }
800
801
802 /*-----------------------------------------------------------------------*/
803 /*
804 Search an object at given coordinates.
805 */
806 int SDLGui_FindObj(SGOBJ *dlg, int fx, int fy)
807 {
808 SDL_Rect coord;
809 int end, i;
810 int ob = -1;
811
812 // Search end object in dialog
813 i = 0;
814 while (dlg[i++].type != -1);
815 end = i;
816
817 // Now check each object
818 for (i = end-1 ; i >= 0 ; i--)
819 {
820 SDLGui_ObjFullCoord(dlg, i, &coord);
821
822 if(fx >= coord.x &&
823 fy >= coord.y &&
824 fx < (coord.x + coord.w) &&
825 fy < (coord.y + coord.h))
826 {
827 if (dlg[i].state & (SG_HIDDEN | SG_DISABLED)) continue;
828 ob = i;
829 break;
830 }
831 }
832
833 return ob;
834 }
835
836
837 /*-----------------------------------------------------------------------*/
838 /*
839 A radio object has been selected. Let's deselect any other in his group.
840 */
841 void SDLGui_SelectRadioObject(SGOBJ *dlg, int clicked_obj)
842 {
843 int obj;
844
845 // Find first radio object in this group
846 obj = clicked_obj;
847 while (dlg[--obj].flags & SG_RADIO);
848
849 // Update state
850 while (dlg[++obj].flags & SG_RADIO)
851 {
852 // This code scan every object in the group. This allows to solve cases
853 // where multiple objects where selected in the group by clicking one.
854 if ((obj != clicked_obj) && (dlg[obj].state & SG_SELECTED))
855 {
856 // Deselect this radio button
857 dlg[obj].state &= ~SG_SELECTED;
858 SDLGui_DrawObject(dlg, obj);
859 SDLGui_RefreshObj(dlg, obj);
860 }
861 }
862 }
863
864
865 /*-----------------------------------------------------------------------*/
866 /*
867 Update clicked object state depending on given mouse coordinates.
868 Returns true if the mouse is over the object, false otherwise.
869 */
870 bool SDLGui_UpdateObjState(SGOBJ *dlg, int clicked_obj, int original_state,
871 int x, int y)
872 {
873 int obj;
874
875 obj = SDLGui_FindObj(dlg, x, y);
876
877 // Special case : user clicked on an already selected radio object
878 // do not modify its state.
879 // We handle it here because it allows to exit if the object is SG_EXIT or
880 // SG_TOUCHEXIT without any additional test.
881 if ((dlg[clicked_obj].flags & SG_RADIO) && (original_state & SG_SELECTED))
882 return (obj == clicked_obj);
883
884 if (((obj != clicked_obj) &&
885 (dlg[clicked_obj].state != original_state)) ||
886 ((obj == clicked_obj) &&
887 (dlg[clicked_obj].state == original_state)))
888 {
889 if (dlg[clicked_obj].flags & SG_SELECTABLE)
890 {
891 dlg[clicked_obj].state ^= SG_SELECTED;
892 SDLGui_DrawObject(dlg, clicked_obj);
893 SDLGui_RefreshObj(dlg, clicked_obj);
894 }
895 }
896
897 return (obj == clicked_obj);
898 }
899
900
901 /*-----------------------------------------------------------------------*/
902 /*
903 Search edit field in a dialog.
904 */
905 int SDLGui_FindEditField(SGOBJ *dlg, int objnum, int mode)
906 {
907 int i, j;
908
909 switch (mode)
910 {
911 case SG_FIRST_EDITFIELD:
912 i = 0;
913 while (dlg[i].type != -1)
914 {
915 if ((dlg[i].type == SGEDITFIELD) &&
916 ((dlg[i].state & (SG_HIDDEN | SG_DISABLED)) == 0))
917 return i;
918 i++;
919 }
920 break;
921
922 case SG_PREVIOUS_EDITFIELD:
923 i = objnum - 1;
924 while (i >= 0)
925 {
926 if ((dlg[i].type == SGEDITFIELD) &&
927 ((dlg[i].state & (SG_HIDDEN | SG_DISABLED)) == 0))
928 return i;
929 i--;
930 }
931 break;
932
933 case SG_NEXT_EDITFIELD:
934 i = objnum + 1;
935 while (dlg[i].type != -1)
936 {
937 if ((dlg[i].type == SGEDITFIELD) &&
938 ((dlg[i].state & (SG_HIDDEN | SG_DISABLED)) == 0))
939 return i;
940 i++;
941 }
942 break;
943
944 case SG_LAST_EDITFIELD:
945 i = objnum + 1;
946 j = -1;
947 while (dlg[i].type != -1)
948 {
949 if ((dlg[i].type == SGEDITFIELD) &&
950 ((dlg[i].state & (SG_HIDDEN | SG_DISABLED)) == 0))
951 j = i;
952 i++;
953 }
954 if (j != -1)
955 return j;
956 break;
957 }
958
959 return objnum;
960 }
961
962
963 /*-----------------------------------------------------------------------*/
964 /*
965 Move cursor to another edit field.
966 */
967 void SDLGui_MoveCursor(SGOBJ *dlg, cursor_state *cursor, int mode)
968 {
969 int new_object;
970
971 new_object = SDLGui_FindEditField(dlg, cursor->object, mode);
972
973 if (new_object != cursor->object)
974 {
975 /* Erase old cursor */
976 cursor->blink_state = false;
977 SDLGui_DrawCursor(dlg, cursor);
978
979 cursor->object = new_object;
980 cursor->position = strlen(dlg[new_object].txt);
981 }
982 else
983 {
984 /* We stay in the same field */
985 /* Move cursor to begin or end of text depending on mode */
986 switch (mode)
987 {
988 case SG_FIRST_EDITFIELD:
989 case SG_PREVIOUS_EDITFIELD:
990 cursor->position = 0;
991 break;
992
993 case SG_NEXT_EDITFIELD:
994 case SG_LAST_EDITFIELD:
995 cursor->position = strlen(dlg[new_object].txt);
996 break;
997 }
998 }
999 }
1000
1001
1002 /*-----------------------------------------------------------------------*/
1003 /*
1004 Handle mouse clicks on edit fields.
1005 */
1006 void SDLGui_ClickEditField(SGOBJ *dlg, cursor_state *cursor, int clicked_obj, int x)
1007 {
1008 SDL_Rect coord;
1009 int i, j;
1010
1011 /* Erase old cursor */
1012 cursor->blink_state = false;
1013 SDLGui_DrawCursor(dlg, cursor);
1014
1015 SDLGui_ObjFullCoord(dlg, clicked_obj, &coord);
1016 i = (x - coord.x + (fontwidth / 2)) / fontwidth;
1017 j = strlen(dlg[clicked_obj].txt);
1018
1019 cursor->object = clicked_obj;
1020 cursor->position = MIN(i, j);
1021 cursor->blink_state = true;
1022 cursor->blink_counter = 0;
1023 SDLGui_DrawCursor(dlg, cursor);
1024 }
1025
1026
1027 /*-----------------------------------------------------------------------*/
1028 /*
1029 Handle mouse clicks.
1030 */
1031 int SDLGui_MouseClick(SGOBJ *dlg, int fx, int fy, cursor_state *cursor)
1032 {
1033 int clicked_obj;
1034 int return_obj = -1;
1035 int original_state = 0;
1036 int x, y;
1037
1038 clicked_obj = SDLGui_FindObj(dlg, fx, fy);
1039
1040 if (clicked_obj >= 0)
1041 {
1042 original_state = dlg[clicked_obj].state;
1043 SDLGui_UpdateObjState(dlg, clicked_obj, original_state, fx, fy);
1044
1045 if (dlg[clicked_obj].flags & SG_TOUCHEXIT)
1046 {
1047 return_obj = clicked_obj;
1048 clicked_obj = -1;
1049 }
1050 }
1051
1052 while (clicked_obj >= 0)
1053 {
1054 SDL_Event evnt;
1055 // SDL_PumpEvents() - not necessary, the main check_event thread calls it
1056 if (SDL_PeepEvents(&evnt, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_USEREVENT)))
1057 {
1058 switch (evnt.user.code)
1059 {
1060 case SDL_USEREVENT:
1061 // a signal that resolution has changed
1062 // Restore clicked object original state
1063 dlg[clicked_obj].state = original_state;
1064
1065 // re-draw dialog
1066 SDLGui_DrawDialog(dlg);
1067
1068 // Exit from mouse click handling.
1069 clicked_obj = -1;
1070 break;
1071
1072 case SDL_MOUSEBUTTONUP:
1073 x = reinterpret_cast<intptr>(evnt.user.data1);
1074 y = reinterpret_cast<intptr>(evnt.user.data2);
1075 if (SDLGui_UpdateObjState(dlg, clicked_obj, original_state, x, y))
1076 {
1077 // true if mouse button is released over clicked object.
1078 // If applicable, the object has been selected by
1079 // SDLGui_UpdateObjState(). Let's do additional handling here.
1080
1081 // Exit if object is an SG_EXIT one.
1082 if (dlg[clicked_obj].flags & SG_EXIT)
1083 return_obj = clicked_obj;
1084
1085 // If it's a SG_RADIO object, deselect other objects in his group.
1086 if (dlg[clicked_obj].flags & SG_RADIO)
1087 SDLGui_SelectRadioObject(dlg, clicked_obj);
1088
1089 if (dlg[clicked_obj].type == SGEDITFIELD)
1090 SDLGui_ClickEditField(dlg, cursor, clicked_obj, x);
1091 }
1092
1093 // Exit from mouse click handling.
1094 clicked_obj = -1;
1095
1096 break;
1097 }
1098 }
1099 else
1100 {
1101 // No special event occured.
1102 // Update object state according to mouse coordinates.
1103 SDL_GetMouseState(&x, &y);
1104 SDLGui_UpdateObjState(dlg, clicked_obj, original_state, x, y);
1105
1106 // Wait a little to avoid eating CPU.
1107 SDL_Delay(100);
1108 }
1109 }
1110
1111 return return_obj;
1112 }
1113
1114
1115 /*-----------------------------------------------------------------------*/
1116 /*
1117 Handle key press.
1118 */
1119 int SDLGui_KeyPress(SGOBJ *dlg, int keysym, int mod, cursor_state *cursor)
1120 {
1121 int return_obj = -1;
1122 int obj;
1123
1124 if (cursor->object != -1)
1125 {
1126 switch(keysym)
1127 {
1128 case SDLK_RETURN:
1129 case SDLK_KP_ENTER:
1130 break;
1131
1132 case SDLK_BACKSPACE:
1133 if (cursor->position > 0)
1134 {
1135 memmove(&dlg[cursor->object].txt[cursor->position-1],
1136 &dlg[cursor->object].txt[cursor->position],
1137 strlen(&dlg[cursor->object].txt[cursor->position])+1);
1138 cursor->position--;
1139 }
1140 break;
1141
1142 case SDLK_DELETE:
1143 if(cursor->position < (int)strlen(dlg[cursor->object].txt))
1144 {
1145 memmove(&dlg[cursor->object].txt[cursor->position],
1146 &dlg[cursor->object].txt[cursor->position+1],
1147 strlen(&dlg[cursor->object].txt[cursor->position+1])+1);
1148 }
1149 break;
1150
1151 case SDLK_LEFT:
1152 if (cursor->position > 0)
1153 cursor->position--;
1154 break;
1155
1156 case SDLK_RIGHT:
1157 if (cursor->position < (int)strlen(dlg[cursor->object].txt))
1158 cursor->position++;
1159 break;
1160
1161 case SDLK_DOWN:
1162 SDLGui_MoveCursor(dlg, cursor, SG_NEXT_EDITFIELD);
1163 break;
1164
1165 case SDLK_UP:
1166 SDLGui_MoveCursor(dlg, cursor, SG_PREVIOUS_EDITFIELD);
1167 break;
1168
1169 case SDLK_TAB:
1170 if (mod & KMOD_SHIFT)
1171 SDLGui_MoveCursor(dlg, cursor, SG_PREVIOUS_EDITFIELD);
1172 else
1173 SDLGui_MoveCursor(dlg, cursor, SG_NEXT_EDITFIELD);
1174 break;
1175
1176 case SDLK_HOME:
1177 if (mod & KMOD_CTRL)
1178 SDLGui_MoveCursor(dlg, cursor, SG_FIRST_EDITFIELD);
1179 else
1180 cursor->position = 0;
1181 break;
1182
1183 case SDLK_END:
1184 if (mod & KMOD_CTRL)
1185 SDLGui_MoveCursor(dlg, cursor, SG_LAST_EDITFIELD);
1186 else
1187 cursor->position = strlen(dlg[cursor->object].txt);
1188 break;
1189
1190 default:
1191 if ((keysym >= SDLK_KP0) && (keysym <= SDLK_KP9))
1192 {
1193 // map numpad numbers to normal numbers
1194 keysym -= (SDLK_KP0 - SDLK_0);
1195 }
1196 /* If it is a "good" key then insert it into the text field */
1197 if ((keysym >= SDLK_SPACE) && (keysym < SDLK_KP0))
1198 {
1199 if (strlen(dlg[cursor->object].txt) < dlg[cursor->object].w)
1200 {
1201 memmove(&dlg[cursor->object].txt[cursor->position+1],
1202 &dlg[cursor->object].txt[cursor->position],
1203 strlen(&dlg[cursor->object].txt[cursor->position])+1);
1204 if (mod & KMOD_SHIFT)
1205 dlg[cursor->object].txt[cursor->position] = toupper(keysym);
1206 else
1207 dlg[cursor->object].txt[cursor->position] = keysym;
1208 cursor->position += 1;
1209 }
1210 }
1211 break;
1212 }
1213 }
1214
1215 switch(keysym)
1216 {
1217 case SDLK_RETURN:
1218 case SDLK_KP_ENTER:
1219 obj = SDLGui_FindDefaultObj(dlg);
1220 if (obj >= 0)
1221 {
1222 dlg[obj].state ^= SG_SELECTED;
1223 SDLGui_DrawObject(dlg, obj);
1224 SDLGui_RefreshObj(dlg, obj);
1225 if (dlg[obj].flags & (SG_EXIT | SG_TOUCHEXIT))
1226 {
1227 return_obj = obj;
1228 SDL_Delay(300);
1229 }
1230 }
1231 break;
1232 }
1233
1234 // Force cursor display. Should ease text input.
1235 cursor->blink_state = true;
1236 cursor->blink_counter = 0;
1237 // Redraw current edit field...
1238 SDLGui_DrawCursor(dlg, cursor);
1239
1240 return return_obj;
1241 }
1242
1243
1244 /*-----------------------------------------------------------------------*/
1245 /*
1246 Used to update screen while GUI is opened. Return a list of rectangles that
1247 covers the screen without overlaping the current dialog.
1248 */
1249 SDL_Rect *SDLGui_GetFirstBackgroundRect(void)
1250 {
1251 // Reset counter...
1252 BackgroundRectCounter = SG_BCKGND_RECT_BEGIN;
1253 // And returns first rectangle
1254 return SDLGui_GetNextBackgroundRect();
1255 }
1256
1257
1258 /*-----------------------------------------------------------------------*/
1259 /*
1260 Returns next rectangle to be redrawn to update screen or NULL if we reached
1261 the end of the list.
1262 This code is "flying dialog" ready :)
1263 It will need some updating if we implement popup buttons handled by sdlgui,
1264 as the popup could be higher than the root box...
1265 I used some recursivity here to simplify the code.
1266 */
1267 SDL_Rect *SDLGui_GetNextBackgroundRect(void)
1268 {
1269 SDL_Rect *return_rect = NULL;
1270
1271 switch (BackgroundRectCounter)
1272 {
1273 case SG_BCKGND_RECT_END:
1274 // Nothing to do : return_rect is already initialized to NULL.
1275 break;
1276
1277 case SG_BCKGND_RECT_BEGIN:
1278 if (DialogRect.w == 0)
1279 {
1280 // The dialog is not drawn yet...
1281 // Let's redraw the full screen.
1282 BackgroundRect.x = 0;
1283 BackgroundRect.y = 0;
1284 BackgroundRect.w = sdlscrn->w;
1285 BackgroundRect.h = sdlscrn->h;
1286 return_rect = &BackgroundRect;
1287 // We reached the end of the list.
1288 BackgroundRectCounter = SG_BCKGND_RECT_END;
1289 }
1290 else
1291 {
1292 BackgroundRectCounter = SG_BCKGND_RECT_TOP;
1293 return_rect = SDLGui_GetNextBackgroundRect();
1294 }
1295 break;
1296
1297 case SG_BCKGND_RECT_TOP:
1298 BackgroundRectCounter = SG_BCKGND_RECT_LEFT;
1299 if (DialogRect.y > 0)
1300 {
1301 BackgroundRect.x = 0;
1302 BackgroundRect.y = 0;
1303 BackgroundRect.w = sdlscrn->w;
1304 BackgroundRect.h = DialogRect.y;
1305 return_rect = &BackgroundRect;
1306 }
1307 else
1308 return_rect = SDLGui_GetNextBackgroundRect();
1309 break;
1310
1311 case SG_BCKGND_RECT_LEFT:
1312 BackgroundRectCounter = SG_BCKGND_RECT_RIGHT;
1313 if (DialogRect.x > 0)
1314 {
1315 BackgroundRect.x = 0;
1316 BackgroundRect.y = (DialogRect.y > 0) ? DialogRect.y : 0;
1317 BackgroundRect.w = DialogRect.x;
1318 BackgroundRect.h =
1319 ((DialogRect.y + DialogRect.h) < (int)sdlscrn->h) ?
1320 (DialogRect.h + DialogRect.y - BackgroundRect.y) :
1321 (sdlscrn->h - DialogRect.y);
1322 return_rect = &BackgroundRect;
1323 }
1324 else
1325 return_rect = SDLGui_GetNextBackgroundRect();
1326 break;
1327
1328 case SG_BCKGND_RECT_RIGHT:
1329 BackgroundRectCounter = SG_BCKGND_RECT_BOTTOM;
1330 if ((DialogRect.x + DialogRect.w) < (int)sdlscrn->w)
1331 {
1332 BackgroundRect.x = DialogRect.x + DialogRect.w;
1333 BackgroundRect.y = (DialogRect.y > 0) ? DialogRect.y : 0;
1334 BackgroundRect.w = sdlscrn->w - (DialogRect.x + DialogRect.w);
1335 BackgroundRect.h =
1336 ((DialogRect.y + DialogRect.h) < (int)sdlscrn->w) ?
1337 (DialogRect.h + DialogRect.y - BackgroundRect.y) :
1338 (sdlscrn->h - DialogRect.y);
1339 return_rect = &BackgroundRect;
1340 }
1341 else
1342 return_rect = SDLGui_GetNextBackgroundRect();
1343 break;
1344
1345 case SG_BCKGND_RECT_BOTTOM:
1346 BackgroundRectCounter = SG_BCKGND_RECT_END;
1347 if ((DialogRect.y + DialogRect.h) < (int)sdlscrn->h)
1348 {
1349 // Bottom
1350 BackgroundRect.x = 0;
1351 BackgroundRect.y = DialogRect.y + DialogRect.h;
1352 BackgroundRect.w = sdlscrn->w;
1353 BackgroundRect.h = sdlscrn->h - (DialogRect.y + DialogRect.h);
1354 return_rect = &BackgroundRect;
1355 }
1356 else
1357 return_rect = SDLGui_GetNextBackgroundRect();
1358 break;
1359 }
1360
1361 return return_rect;
1362 }
1363
1364 SDL_Event getEvent(SGOBJ *dlg, cursor_state *cursor)
1365 {
1366 int i = 0;
1367 while(1) {
1368 SDL_Event evnt;
1369 // fprintf(stderr, "Debug Before Peep events\n");
1370 if (SDL_PeepEvents(&evnt, 1, SDL_GETEVENT, SDL_EVENTMASK(SDL_USEREVENT)))
1371 {
1372 fprintf(stderr, "Debug Peep events %d\n",i++);
1373 SDL_Event e;
1374 switch(evnt.user.code)
1375 {
1376 case SDL_KEYDOWN:
1377 case SDL_KEYUP:
1378 e.type = evnt.user.code;
1379 e.key.keysym.sym = (SDLKey)reinterpret_cast<uintptr>(evnt.user.data1);
1380 e.key.keysym.mod = (SDLMod)reinterpret_cast<uintptr>(evnt.user.data2);
1381 return e;
1382
1383 case SDL_MOUSEBUTTONDOWN:
1384 case SDL_MOUSEBUTTONUP:
1385 e.type = evnt.user.code;
1386 if (evnt.user.code == SDL_MOUSEBUTTONDOWN)
1387 fprintf(stderr, "Debug mouse down\n");
1388 else
1389 fprintf(stderr, "Debug mouse down\n");
1390 e.button.x = reinterpret_cast<intptr>(evnt.user.data1);
1391 e.button.y = reinterpret_cast<intptr>(evnt.user.data2);
1392 return e;
1393
1394 case SDL_USEREVENT:
1395 // a signal that resolution has changed
1396 if (dlg != NULL)
1397 SDLGui_DrawDialog(dlg); // re-draw dialog
1398 break;
1399 }
1400 }
1401 else
1402 {
1403 // No special event occured.
1404 // Wait a little to avoid eating CPU.
1405 SDL_Delay(50);
1406 if (cursor != NULL) {
1407 cursor->blink_counter++;
1408 if (cursor->blink_counter >= 10) {
1409 cursor->blink_counter = 0;
1410 cursor->blink_state = !cursor->blink_state;
1411 if (dlg != NULL)
1412 SDLGui_DrawCursor(dlg, cursor);
1413 }
1414 }
1415 }
1416 }
1417 }
1418
1419 /*-----------------------------------------------------------------------*/
1420 /*
1421 Show and process a dialog. Returns the button number that has been
1422 pressed. Does NOT handle SDL_QUIT - you must handle it before you
1423 pass the input event to the SDL GUI.
1424 */
1425 int SDLGui_DoDialog(SGOBJ *dlg)
1426 {
1427 int return_obj = -1;
1428 int obj;
1429 int x, y;
1430 // int keysym, mod;
1431 cursor_state cursor;
1432
1433 // Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here
1434 bool stillPressed = (SDL_GetMouseState(&x, &y) & SDL_BUTTON(1));
1435 obj = SDLGui_FindObj(dlg, x, y);
1436 if (stillPressed && (obj >= 0) && (dlg[obj].flags & SG_TOUCHEXIT))
1437 {
1438 // Mouse button is pressed over a TOUCHEXIT Button
1439 // Toogle its state before drawing anything (it has been deselected before).
1440 dlg[obj].state ^= SG_SELECTED;
1441
1442 return_obj = obj;
1443 }
1444
1445 cursor.object = SDLGui_FindEditField(dlg, -1, SG_FIRST_EDITFIELD);
1446 cursor.position = (cursor.object != -1) ? strlen(dlg[cursor.object].txt) : 0;
1447 cursor.blink_counter = 0;
1448 cursor.blink_state = true;
1449
1450 SDLGui_DrawDialog(dlg);
1451
1452 /* The main loop */
1453 while (return_obj < 0)
1454 {
1455 fprintf(stderr, "Debug SDL main loop\n");
1456 SDL_Event evnt = getEvent(dlg, &cursor);
1457 fprintf(stderr, "Debug SDL main loop got event\n");
1458 switch(evnt.type)
1459 {
1460 case SDL_KEYDOWN:
1461 return_obj = SDLGui_KeyPress(dlg, evnt.key.keysym.sym, evnt.key.keysym.mod, &cursor);
1462 break;
1463
1464 case SDL_MOUSEBUTTONDOWN:
1465 return_obj = SDLGui_MouseClick(dlg, evnt.button.x, evnt.button.y, &cursor);
1466 break;
1467 }
1468 }
1469 fprintf(stderr, "Debug SDL main loop finished\n");
1470 if (dlg[return_obj].type == SGBUTTON)
1471 {
1472 // Deselect button...
1473 // BUG: This should be caller responsibility
1474 dlg[return_obj].state ^= SG_SELECTED;
1475 }
1476
1477 return return_obj;
1478 }