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

# User Rev Content
1 berlac 1.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     }