|
|
1.1 root 1: /*
2: Hatari - sdlgui.c
3:
4: This file is distributed under the GNU Public License, version 2 or at
5: your option any later version. Read the file gpl.txt for details.
6:
7: A tiny graphical user interface for Hatari.
8: */
1.1.1.7 ! root 9: const char SDLGui_rcsid[] = "Hatari $Id: sdlgui.c,v 1.20 2008-11-21 18:28:24 eerot Exp $";
1.1 root 10:
11: #include <SDL.h>
12: #include <ctype.h>
13: #include <string.h>
14:
15: #include "main.h"
16: #include "sdlgui.h"
17:
18: #include "font5x8.h"
19: #include "font10x16.h"
20:
21:
1.1.1.2 root 22: static SDL_Surface *pSdlGuiScrn; /* Pointer to the actual main SDL screen surface */
1.1 root 23: static SDL_Surface *pSmallFontGfx = NULL; /* The small font graphics */
24: static SDL_Surface *pBigFontGfx = NULL; /* The big font graphics */
1.1.1.2 root 25: static SDL_Surface *pFontGfx = NULL; /* The actual font graphics */
1.1 root 26: static int fontwidth, fontheight; /* Width & height of the actual font */
27:
28:
29:
30: /*-----------------------------------------------------------------------*/
31: /*
32: Load an 1 plane XBM into a 8 planes SDL_Surface.
33: */
1.1.1.4 root 34: static SDL_Surface *SDLGui_LoadXBM(int w, int h, const Uint8 *pXbmBits)
1.1 root 35: {
1.1.1.5 root 36: SDL_Surface *bitmap;
37: Uint8 *dstbits;
38: const Uint8 *srcbits;
39: int x, y, srcpitch;
40: int mask;
41:
42: srcbits = pXbmBits;
43:
44: /* Allocate the bitmap */
45: bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0);
46: if (bitmap == NULL)
47: {
48: fprintf(stderr, "Failed to allocate bitmap: %s", SDL_GetError());
49: return NULL;
50: }
51:
52: srcpitch = ((w + 7) / 8);
53: dstbits = (Uint8 *)bitmap->pixels;
54: mask = 1;
55:
56: /* Copy the pixels */
57: for (y = 0 ; y < h ; y++)
58: {
59: for (x = 0 ; x < w ; x++)
60: {
61: dstbits[x] = (srcbits[x / 8] & mask) ? 1 : 0;
62: mask <<= 1;
63: mask |= (mask >> 8);
64: mask &= 0xFF;
65: }
66: dstbits += bitmap->pitch;
67: srcbits += srcpitch;
68: }
1.1 root 69:
1.1.1.5 root 70: return bitmap;
1.1 root 71: }
72:
73:
74: /*-----------------------------------------------------------------------*/
75: /*
76: Initialize the GUI.
77: */
78: int SDLGui_Init(void)
79: {
1.1.1.5 root 80: SDL_Color blackWhiteColors[2] = {{255, 255, 255, 0}, {0, 0, 0, 0}};
1.1 root 81:
1.1.1.6 root 82: if (pSmallFontGfx && pBigFontGfx)
83: {
84: /* already initialized */
85: return 0;
86: }
87:
1.1.1.5 root 88: /* Initialize the font graphics: */
89: pSmallFontGfx = SDLGui_LoadXBM(font5x8_width, font5x8_height, font5x8_bits);
90: pBigFontGfx = SDLGui_LoadXBM(font10x16_width, font10x16_height, font10x16_bits);
91: if (pSmallFontGfx == NULL || pBigFontGfx == NULL)
92: {
93: fprintf(stderr, "Error: Can not init font graphics!\n");
94: return -1;
95: }
96:
97: /* Set color palette of the font graphics: */
98: SDL_SetColors(pSmallFontGfx, blackWhiteColors, 0, 2);
99: SDL_SetColors(pBigFontGfx, blackWhiteColors, 0, 2);
100:
101: /* Set font color 0 as transparent: */
102: SDL_SetColorKey(pSmallFontGfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), 0);
103: SDL_SetColorKey(pBigFontGfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), 0);
1.1 root 104:
1.1.1.5 root 105: return 0;
1.1 root 106: }
107:
108:
109: /*-----------------------------------------------------------------------*/
110: /*
111: Uninitialize the GUI.
112: */
113: int SDLGui_UnInit(void)
114: {
1.1.1.5 root 115: if (pSmallFontGfx)
116: {
117: SDL_FreeSurface(pSmallFontGfx);
118: pSmallFontGfx = NULL;
119: }
120:
121: if (pBigFontGfx)
122: {
123: SDL_FreeSurface(pBigFontGfx);
124: pBigFontGfx = NULL;
125: }
1.1 root 126:
1.1.1.5 root 127: return 0;
1.1 root 128: }
129:
130:
131: /*-----------------------------------------------------------------------*/
132: /*
1.1.1.2 root 133: Inform the SDL-GUI about the actual SDL_Surface screen pointer and
134: prepare the font to suit the actual resolution.
1.1 root 135: */
1.1.1.2 root 136: int SDLGui_SetScreen(SDL_Surface *pScrn)
1.1 root 137: {
1.1.1.5 root 138: pSdlGuiScrn = pScrn;
1.1.1.2 root 139:
1.1.1.5 root 140: /* Decide which font to use - small or big one: */
141: if (pSdlGuiScrn->w >= 640 && pSdlGuiScrn->h >= 400 && pBigFontGfx != NULL)
142: {
143: pFontGfx = pBigFontGfx;
144: }
145: else
146: {
147: pFontGfx = pSmallFontGfx;
148: }
149:
150: if (pFontGfx == NULL)
151: {
152: fprintf(stderr, "Error: A problem with the font occured!\n");
153: return -1;
154: }
155:
156: /* Get the font width and height: */
157: fontwidth = pFontGfx->w/16;
158: fontheight = pFontGfx->h/16;
1.1 root 159:
1.1.1.5 root 160: return 0;
1.1 root 161: }
162:
1.1.1.6 root 163: /*-----------------------------------------------------------------------*/
164: /*
165: Return character size for current font in given arguments.
166: */
167: void SDLGui_GetFontSize(int *width, int *height)
168: {
169: *width = fontwidth;
170: *height = fontheight;
171: }
1.1 root 172:
173: /*-----------------------------------------------------------------------*/
174: /*
175: Center a dialog so that it appears in the middle of the screen.
176: Note: We only store the coordinates in the root box of the dialog,
177: all other objects in the dialog are positioned relatively to this one.
178: */
179: void SDLGui_CenterDlg(SGOBJ *dlg)
180: {
1.1.1.5 root 181: dlg[0].x = (pSdlGuiScrn->w/fontwidth-dlg[0].w)/2;
182: dlg[0].y = (pSdlGuiScrn->h/fontheight-dlg[0].h)/2;
1.1 root 183: }
184:
185:
186: /*-----------------------------------------------------------------------*/
187: /*
188: Draw a text string.
189: */
1.1.1.6 root 190: void SDLGui_Text(int x, int y, const char *txt)
1.1 root 191: {
1.1.1.5 root 192: int i;
193: char c;
194: SDL_Rect sr, dr;
195:
196: for (i=0; txt[i]!=0; i++)
197: {
198: c = txt[i];
199: sr.x=fontwidth*(c%16);
200: sr.y=fontheight*(c/16);
201: sr.w=fontwidth;
202: sr.h=fontheight;
203: dr.x=x+i*fontwidth;
204: dr.y=y;
205: dr.w=fontwidth;
206: dr.h=fontheight;
207: SDL_BlitSurface(pFontGfx, &sr, pSdlGuiScrn, &dr);
208: }
1.1 root 209: }
210:
211:
212: /*-----------------------------------------------------------------------*/
213: /*
214: Draw a dialog text object.
215: */
1.1.1.2 root 216: static void SDLGui_DrawText(const SGOBJ *tdlg, int objnum)
1.1 root 217: {
1.1.1.5 root 218: int x, y;
219: x = (tdlg[0].x+tdlg[objnum].x)*fontwidth;
220: y = (tdlg[0].y+tdlg[objnum].y)*fontheight;
221: SDLGui_Text(x, y, tdlg[objnum].txt);
1.1 root 222: }
223:
224:
225: /*-----------------------------------------------------------------------*/
226: /*
227: Draw a edit field object.
228: */
1.1.1.2 root 229: static void SDLGui_DrawEditField(const SGOBJ *edlg, int objnum)
1.1 root 230: {
1.1.1.5 root 231: int x, y;
232: SDL_Rect rect;
1.1 root 233:
1.1.1.5 root 234: x = (edlg[0].x+edlg[objnum].x)*fontwidth;
235: y = (edlg[0].y+edlg[objnum].y)*fontheight;
236: SDLGui_Text(x, y, edlg[objnum].txt);
237:
238: rect.x = x;
239: rect.y = y + edlg[objnum].h * fontheight;
240: rect.w = edlg[objnum].w * fontwidth;
241: rect.h = 1;
242: SDL_FillRect(pSdlGuiScrn, &rect, SDL_MapRGB(pSdlGuiScrn->format,160,160,160));
1.1 root 243: }
244:
245:
246: /*-----------------------------------------------------------------------*/
247: /*
248: Draw a dialog box object.
249: */
1.1.1.2 root 250: static void SDLGui_DrawBox(const SGOBJ *bdlg, int objnum)
1.1 root 251: {
1.1.1.5 root 252: SDL_Rect rect;
253: int x, y, w, h, offset;
254: Uint32 grey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192);
255: Uint32 upleftc, downrightc;
256:
257: x = bdlg[objnum].x*fontwidth;
258: y = bdlg[objnum].y*fontheight;
259: if (objnum > 0) /* Since the root object is a box, too, */
260: {
261: /* we have to look for it now here and only */
262: x += bdlg[0].x*fontwidth; /* add its absolute coordinates if we need to */
263: y += bdlg[0].y*fontheight;
264: }
265: w = bdlg[objnum].w*fontwidth;
266: h = bdlg[objnum].h*fontheight;
267:
268: if (bdlg[objnum].state & SG_SELECTED)
269: {
270: upleftc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
271: downrightc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255);
272: }
273: else
274: {
275: upleftc = SDL_MapRGB(pSdlGuiScrn->format,255,255,255);
276: downrightc = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
277: }
278:
279: /* The root box should be bigger than the screen, so we disable the offset there: */
280: if (objnum != 0)
281: offset = 1;
282: else
283: offset = 0;
284:
285: /* Draw background: */
286: rect.x = x;
287: rect.y = y;
288: rect.w = w;
289: rect.h = h;
290: SDL_FillRect(pSdlGuiScrn, &rect, grey);
291:
292: /* Draw upper border: */
293: rect.x = x;
294: rect.y = y - offset;
295: rect.w = w;
296: rect.h = 1;
297: SDL_FillRect(pSdlGuiScrn, &rect, upleftc);
298:
299: /* Draw left border: */
300: rect.x = x - offset;
301: rect.y = y;
302: rect.w = 1;
303: rect.h = h;
304: SDL_FillRect(pSdlGuiScrn, &rect, upleftc);
305:
306: /* Draw bottom border: */
307: rect.x = x;
308: rect.y = y + h - 1 + offset;
309: rect.w = w;
310: rect.h = 1;
311: SDL_FillRect(pSdlGuiScrn, &rect, downrightc);
312:
313: /* Draw right border: */
314: rect.x = x + w - 1 + offset;
315: rect.y = y;
316: rect.w = 1;
317: rect.h = h;
318: SDL_FillRect(pSdlGuiScrn, &rect, downrightc);
1.1 root 319: }
320:
321:
322: /*-----------------------------------------------------------------------*/
323: /*
324: Draw a normal button.
325: */
1.1.1.2 root 326: static void SDLGui_DrawButton(const SGOBJ *bdlg, int objnum)
1.1 root 327: {
1.1.1.5 root 328: int x,y;
1.1 root 329:
1.1.1.5 root 330: SDLGui_DrawBox(bdlg, objnum);
1.1 root 331:
1.1.1.5 root 332: x = (bdlg[0].x + bdlg[objnum].x + (bdlg[objnum].w-strlen(bdlg[objnum].txt))/2) * fontwidth;
333: y = (bdlg[0].y + bdlg[objnum].y + (bdlg[objnum].h-1)/2) * fontheight;
1.1 root 334:
1.1.1.5 root 335: if (bdlg[objnum].state & SG_SELECTED)
336: {
337: x+=1;
338: y+=1;
339: }
340: SDLGui_Text(x, y, bdlg[objnum].txt);
1.1 root 341: }
342:
343:
344: /*-----------------------------------------------------------------------*/
345: /*
346: Draw a dialog radio button object.
347: */
1.1.1.2 root 348: static void SDLGui_DrawRadioButton(const SGOBJ *rdlg, int objnum)
1.1 root 349: {
1.1.1.5 root 350: char str[80];
351: int x, y;
1.1 root 352:
1.1.1.5 root 353: x = (rdlg[0].x + rdlg[objnum].x) * fontwidth;
354: y = (rdlg[0].y + rdlg[objnum].y) * fontheight;
1.1 root 355:
1.1.1.5 root 356: if (rdlg[objnum].state & SG_SELECTED)
357: str[0]=SGRADIOBUTTON_SELECTED;
358: else
359: str[0]=SGRADIOBUTTON_NORMAL;
360: str[1]=' ';
361: strcpy(&str[2], rdlg[objnum].txt);
1.1 root 362:
1.1.1.5 root 363: SDLGui_Text(x, y, str);
1.1 root 364: }
365:
366:
367: /*-----------------------------------------------------------------------*/
368: /*
369: Draw a dialog check box object.
370: */
1.1.1.2 root 371: static void SDLGui_DrawCheckBox(const SGOBJ *cdlg, int objnum)
1.1 root 372: {
1.1.1.5 root 373: char str[80];
374: int x, y;
1.1 root 375:
1.1.1.5 root 376: x = (cdlg[0].x + cdlg[objnum].x) * fontwidth;
377: y = (cdlg[0].y + cdlg[objnum].y) * fontheight;
1.1 root 378:
1.1.1.5 root 379: if ( cdlg[objnum].state&SG_SELECTED )
380: str[0]=SGCHECKBOX_SELECTED;
381: else
382: str[0]=SGCHECKBOX_NORMAL;
383: str[1]=' ';
384: strcpy(&str[2], cdlg[objnum].txt);
1.1 root 385:
1.1.1.5 root 386: SDLGui_Text(x, y, str);
1.1 root 387: }
388:
389:
390: /*-----------------------------------------------------------------------*/
391: /*
392: Draw a dialog popup button object.
393: */
1.1.1.2 root 394: static void SDLGui_DrawPopupButton(const SGOBJ *pdlg, int objnum)
1.1 root 395: {
1.1.1.5 root 396: int x, y, w, h;
397: const char *downstr = "\x02";
1.1 root 398:
1.1.1.5 root 399: SDLGui_DrawBox(pdlg, objnum);
1.1 root 400:
1.1.1.5 root 401: x = (pdlg[0].x + pdlg[objnum].x) * fontwidth;
402: y = (pdlg[0].y + pdlg[objnum].y) * fontheight;
403: w = pdlg[objnum].w*fontwidth;
404: h = pdlg[objnum].h*fontheight;
1.1 root 405:
1.1.1.5 root 406: SDLGui_Text(x, y, pdlg[objnum].txt);
407: SDLGui_Text(x+w-fontwidth, y, downstr);
1.1 root 408: }
409:
410:
411: /*-----------------------------------------------------------------------*/
412: /*
413: Let the user insert text into an edit field object.
414: NOTE: The dlg[objnum].txt must point to an an array that is big enough
415: for dlg[objnum].w characters!
416: */
417: static void SDLGui_EditField(SGOBJ *dlg, int objnum)
418: {
1.1.1.5 root 419: size_t cursorPos; /* Position of the cursor in the edit field */
420: int blinkState = 0; /* Used for cursor blinking */
421: int bStopEditing = FALSE; /* TRUE if user wants to exit the edit field */
422: char *txt; /* Shortcut for dlg[objnum].txt */
423: SDL_Rect rect;
424: Uint32 grey, cursorCol;
425: SDL_Event event;
426: int nOldUnicodeMode;
427:
428: /* Enable unicode translation to get proper characters with SDL_PollEvent */
429: nOldUnicodeMode = SDL_EnableUNICODE(TRUE);
430:
431: grey = SDL_MapRGB(pSdlGuiScrn->format, 192, 192, 192);
432: cursorCol = SDL_MapRGB(pSdlGuiScrn->format, 128, 128, 128);
433:
434: rect.x = (dlg[0].x + dlg[objnum].x) * fontwidth;
435: rect.y = (dlg[0].y + dlg[objnum].y) * fontheight;
436: rect.w = (dlg[objnum].w + 1) * fontwidth - 1;
437: rect.h = dlg[objnum].h * fontheight;
438:
439: txt = dlg[objnum].txt;
440: cursorPos = strlen(txt);
441:
442: do
443: {
444: /* Look for events */
445: if (SDL_PollEvent(&event) == 0)
446: {
447: /* No event: Wait some time for cursor blinking */
448: SDL_Delay(250);
449: blinkState ^= 1;
450: }
451: else
452: {
453: /* Handle events */
454: do
455: {
456: switch (event.type)
457: {
458: case SDL_QUIT: /* User wants to quit */
459: bQuitProgram = TRUE;
460: bStopEditing = TRUE;
461: break;
462: case SDL_MOUSEBUTTONDOWN: /* Mouse pressed -> stop editing */
463: bStopEditing = TRUE;
464: break;
465: case SDL_KEYDOWN: /* Key pressed */
466: switch (event.key.keysym.sym)
467: {
468: case SDLK_RETURN:
469: case SDLK_KP_ENTER:
470: bStopEditing = TRUE;
471: break;
472: case SDLK_LEFT:
473: if (cursorPos > 0)
474: cursorPos -= 1;
475: break;
476: case SDLK_RIGHT:
477: if (cursorPos < strlen(txt))
478: cursorPos += 1;
479: break;
480: case SDLK_BACKSPACE:
481: if (cursorPos > 0)
482: {
483: memmove(&txt[cursorPos-1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
484: cursorPos -= 1;
485: }
486: break;
487: case SDLK_DELETE:
488: if (cursorPos < strlen(txt))
489: memmove(&txt[cursorPos], &txt[cursorPos+1], strlen(&txt[cursorPos+1])+1);
490: break;
491: default:
492: /* If it is a "good" key then insert it into the text field */
493: if (event.key.keysym.unicode >= 32 && event.key.keysym.unicode < 128
494: && event.key.keysym.unicode != PATHSEP)
495: {
496: if (strlen(txt) < (size_t)dlg[objnum].w)
497: {
498: memmove(&txt[cursorPos+1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
499: txt[cursorPos] = event.key.keysym.unicode;
500: cursorPos += 1;
501: }
502: }
503: break;
504: }
505: break;
506: }
507: }
508: while (SDL_PollEvent(&event));
509:
510: blinkState = 1;
511: }
512:
513: /* Redraw the text field: */
514: SDL_FillRect(pSdlGuiScrn, &rect, grey); /* Draw background */
515: /* Draw the cursor: */
516: if (blinkState && !bStopEditing)
517: {
518: SDL_Rect cursorrect;
519: cursorrect.x = rect.x + cursorPos * fontwidth;
520: cursorrect.y = rect.y;
521: cursorrect.w = fontwidth;
522: cursorrect.h = rect.h;
523: SDL_FillRect(pSdlGuiScrn, &cursorrect, cursorCol);
524: }
525: SDLGui_Text(rect.x, rect.y, dlg[objnum].txt); /* Draw text */
526: SDL_UpdateRects(pSdlGuiScrn, 1, &rect);
527: }
528: while (!bStopEditing);
529:
530: SDL_EnableUNICODE(nOldUnicodeMode);
1.1 root 531: }
532:
533:
534: /*-----------------------------------------------------------------------*/
535: /*
536: Draw a whole dialog.
537: */
1.1.1.3 root 538: void SDLGui_DrawDialog(const SGOBJ *dlg)
1.1 root 539: {
1.1.1.5 root 540: int i;
541: for (i = 0; dlg[i].type != -1; i++)
542: {
543: switch (dlg[i].type)
544: {
545: case SGBOX:
546: SDLGui_DrawBox(dlg, i);
547: break;
548: case SGTEXT:
549: SDLGui_DrawText(dlg, i);
550: break;
551: case SGEDITFIELD:
552: SDLGui_DrawEditField(dlg, i);
553: break;
554: case SGBUTTON:
555: SDLGui_DrawButton(dlg, i);
556: break;
557: case SGRADIOBUT:
558: SDLGui_DrawRadioButton(dlg, i);
559: break;
560: case SGCHECKBOX:
561: SDLGui_DrawCheckBox(dlg, i);
562: break;
563: case SGPOPUP:
564: SDLGui_DrawPopupButton(dlg, i);
565: break;
566: }
567: }
568: SDL_UpdateRect(pSdlGuiScrn, 0,0,0,0);
1.1 root 569: }
570:
571:
572: /*-----------------------------------------------------------------------*/
573: /*
574: Search an object at a certain position.
575: */
1.1.1.2 root 576: static int SDLGui_FindObj(const SGOBJ *dlg, int fx, int fy)
1.1 root 577: {
1.1.1.5 root 578: int len, i;
579: int ob = -1;
580: int xpos, ypos;
581:
582: len = 0;
583: while (dlg[len].type != -1) len++;
584:
585: xpos = fx / fontwidth;
586: ypos = fy / fontheight;
587: /* Now search for the object: */
588: for (i = len; i >= 0; i--)
589: {
590: if (xpos >= dlg[0].x+dlg[i].x && ypos >= dlg[0].y+dlg[i].y
591: && xpos < dlg[0].x+dlg[i].x+dlg[i].w && ypos < dlg[0].y+dlg[i].y+dlg[i].h)
592: {
593: ob = i;
594: break;
595: }
596: }
597:
598: return ob;
599: }
600:
601:
602: /*-----------------------------------------------------------------------*/
603: /*
604: Search a button with a special flag (e.g. SG_DEFAULT or SG_CANCEL).
605: */
606: static int SDLGui_SearchFlaggedButton(const SGOBJ *dlg, int flag)
607: {
608: int i = 0;
609:
610: while (dlg[i].type != -1)
611: {
612: if (dlg[i].flags & flag)
613: return i;
614: i++;
615: }
1.1 root 616:
1.1.1.5 root 617: return 0;
1.1 root 618: }
619:
620:
621: /*-----------------------------------------------------------------------*/
622: /*
623: Show and process a dialog. Returns the button number that has been
1.1.1.2 root 624: pressed or SDLGUI_UNKNOWNEVENT if an unsupported event occured (will be
625: stored in parameter pEventOut).
1.1 root 626: */
1.1.1.2 root 627: int SDLGui_DoDialog(SGOBJ *dlg, SDL_Event *pEventOut)
1.1 root 628: {
1.1.1.5 root 629: int obj=0;
630: int oldbutton=0;
631: int retbutton=0;
632: int i, j, b;
633: SDL_Event sdlEvent;
634: SDL_Rect rct;
635: Uint32 grey;
636: SDL_Surface *pBgSurface;
637: SDL_Rect dlgrect, bgrect;
638:
639: if (pSdlGuiScrn->h / fontheight < dlg[0].h)
640: {
641: fprintf(stderr, "Screen size too small for dialog!\n");
642: return SDLGUI_ERROR;
643: }
644:
645: grey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192);
646:
647: dlgrect.x = dlg[0].x * fontwidth;
648: dlgrect.y = dlg[0].y * fontheight;
649: dlgrect.w = dlg[0].w * fontwidth;
650: dlgrect.h = dlg[0].h * fontheight;
651:
652: bgrect.x = bgrect.y = 0;
653: bgrect.w = dlgrect.w;
654: bgrect.h = dlgrect.h;
655:
656: /* Save background */
657: pBgSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, dlgrect.w, dlgrect.h, pSdlGuiScrn->format->BitsPerPixel,
658: pSdlGuiScrn->format->Rmask, pSdlGuiScrn->format->Gmask, pSdlGuiScrn->format->Bmask, pSdlGuiScrn->format->Amask);
659: if (pSdlGuiScrn->format->palette != NULL)
660: {
661: SDL_SetColors(pBgSurface, pSdlGuiScrn->format->palette->colors, 0, pSdlGuiScrn->format->palette->ncolors-1);
662: }
663:
664: if (pBgSurface != NULL)
665: {
666: SDL_BlitSurface(pSdlGuiScrn, &dlgrect, pBgSurface, &bgrect);
667: }
668: else
669: {
670: fprintf(stderr, "SDLGUI_DoDialog: CreateRGBSurface failed: %s\n", SDL_GetError());
671: }
672:
673: /* (Re-)draw the dialog */
674: SDLGui_DrawDialog(dlg);
675:
676: /* Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */
677: SDL_PumpEvents();
678: b = SDL_GetMouseState(&i, &j);
679: obj = SDLGui_FindObj(dlg, i, j);
680: if (obj > 0 && (dlg[obj].flags&SG_TOUCHEXIT) )
681: {
682: oldbutton = obj;
683: if (b & SDL_BUTTON(1))
684: {
685: dlg[obj].state |= SG_SELECTED;
686: retbutton = obj;
687: }
688: }
689:
690: /* The main loop */
691: while (retbutton == 0 && !bQuitProgram)
692: {
693: if (SDL_WaitEvent(&sdlEvent) == 1) /* Wait for events */
694: switch (sdlEvent.type)
695: {
696: case SDL_QUIT:
697: retbutton = SDLGUI_QUIT;
698: break;
699:
700: case SDL_MOUSEBUTTONDOWN:
701: if (sdlEvent.button.button != SDL_BUTTON_LEFT)
702: {
703: /* Not left mouse button -> unsupported event */
704: if (pEventOut)
705: retbutton = SDLGUI_UNKNOWNEVENT;
706: break;
707: }
708: /* It was the left button: Find the object under the mouse cursor */
709: obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y);
710: if (obj>0)
711: {
712: if (dlg[obj].type==SGBUTTON)
713: {
714: dlg[obj].state |= SG_SELECTED;
715: SDLGui_DrawButton(dlg, obj);
716: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
717: dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
718: oldbutton=obj;
719: }
720: if ( dlg[obj].flags&SG_TOUCHEXIT )
721: {
722: dlg[obj].state |= SG_SELECTED;
723: retbutton = obj;
724: }
725: }
726: break;
727:
728: case SDL_MOUSEBUTTONUP:
729: if (sdlEvent.button.button != SDL_BUTTON_LEFT)
730: {
731: /* Not left mouse button -> unsupported event */
732: if (pEventOut)
733: retbutton = SDLGUI_UNKNOWNEVENT;
734: break;
735: }
736: /* It was the left button: Find the object under the mouse cursor */
737: obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y);
738: if (obj>0)
739: {
740: switch (dlg[obj].type)
741: {
742: case SGBUTTON:
743: if (oldbutton==obj)
744: retbutton=obj;
745: break;
746: case SGEDITFIELD:
747: SDLGui_EditField(dlg, obj);
748: break;
749: case SGRADIOBUT:
750: for (i = obj-1; i > 0 && dlg[i].type == SGRADIOBUT; i--)
751: {
752: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
753: rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
754: rct.y = (dlg[0].y+dlg[i].y)*fontheight;
755: rct.w = fontwidth;
756: rct.h = fontheight;
757: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
758: SDLGui_DrawRadioButton(dlg, i);
759: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
760: }
761: for (i = obj+1; dlg[i].type == SGRADIOBUT; i++)
762: {
763: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
764: rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
765: rct.y = (dlg[0].y+dlg[i].y)*fontheight;
766: rct.w = fontwidth;
767: rct.h = fontheight;
768: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
769: SDLGui_DrawRadioButton(dlg, i);
770: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
771: }
772: dlg[obj].state |= SG_SELECTED; /* Select this radio button */
773: rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
774: rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
775: rct.w = fontwidth;
776: rct.h = fontheight;
777: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
778: SDLGui_DrawRadioButton(dlg, obj);
779: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
780: break;
781: case SGCHECKBOX:
782: dlg[obj].state ^= SG_SELECTED;
783: rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
784: rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
785: rct.w = fontwidth;
786: rct.h = fontheight;
787: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
788: SDLGui_DrawCheckBox(dlg, obj);
789: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
790: break;
791: case SGPOPUP:
792: dlg[obj].state |= SG_SELECTED;
793: SDLGui_DrawPopupButton(dlg, obj);
794: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
795: dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
796: retbutton=obj;
797: break;
798: }
799: }
800: if (oldbutton > 0)
801: {
802: dlg[oldbutton].state &= ~SG_SELECTED;
803: SDLGui_DrawButton(dlg, oldbutton);
804: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[oldbutton].x)*fontwidth-2, (dlg[0].y+dlg[oldbutton].y)*fontheight-2,
805: dlg[oldbutton].w*fontwidth+4, dlg[oldbutton].h*fontheight+4);
806: oldbutton = 0;
807: }
808: if (obj >= 0 && (dlg[obj].flags&SG_EXIT))
809: {
810: retbutton = obj;
811: }
812: break;
813:
1.1.1.6 root 814: case SDL_JOYAXISMOTION:
815: case SDL_JOYBALLMOTION:
816: case SDL_JOYHATMOTION:
1.1.1.5 root 817: case SDL_MOUSEMOTION:
818: break;
819:
820: case SDL_KEYDOWN: /* Key pressed */
821: if (sdlEvent.key.keysym.sym == SDLK_RETURN
822: || sdlEvent.key.keysym.sym == SDLK_KP_ENTER)
823: {
824: retbutton = SDLGui_SearchFlaggedButton(dlg, SG_DEFAULT);
825: }
826: else if (sdlEvent.key.keysym.sym == SDLK_ESCAPE)
827: {
828: retbutton = SDLGui_SearchFlaggedButton(dlg, SG_CANCEL);
829: }
830: else if (pEventOut)
831: {
832: retbutton = SDLGUI_UNKNOWNEVENT;
833: }
834: break;
835:
836: default:
837: if (pEventOut)
838: retbutton = SDLGUI_UNKNOWNEVENT;
839: break;
840: }
841: }
842:
843: /* Restore background */
844: if (pBgSurface)
845: {
846: SDL_BlitSurface(pBgSurface, &bgrect, pSdlGuiScrn, &dlgrect);
847: SDL_FreeSurface(pBgSurface);
848: }
849:
850: /* Copy event data of unsupported events if caller wants to have it */
851: if (retbutton == SDLGUI_UNKNOWNEVENT && pEventOut)
852: memcpy(pEventOut, &sdlEvent, sizeof(SDL_Event));
1.1.1.2 root 853:
1.1.1.5 root 854: if (retbutton == SDLGUI_QUIT)
855: bQuitProgram = TRUE;
1.1 root 856:
1.1.1.5 root 857: return retbutton;
1.1 root 858: }
859:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.