|
|
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: */
9: const char SDLGui_fileid[] = "Previous sdlgui.c : " __DATE__ " " __TIME__;
10:
11: #include <SDL.h>
12: #include <ctype.h>
13: #include <string.h>
14:
15: #include "main.h"
16: #include "sdlgui.h"
17: #include "screen.h"
18:
19: #include "font5x8.h"
20: #include "font10x16.h"
21:
22:
23: static SDL_Surface *pSdlGuiScrn; /* Pointer to the actual main SDL screen surface */
24: static SDL_Surface *pSmallFontGfx = NULL; /* The small font graphics */
25: static SDL_Surface *pBigFontGfx = NULL; /* The big font graphics */
26: static SDL_Surface *pFontGfx = NULL; /* The actual font graphics */
27: static int current_object = 0; /* Current selected object */
28:
29:
30: /*-----------------------------------------------------------------------*/
31: /**
32: * Load an 1 plane XBM into a 8 planes SDL_Surface.
33: */
34: static SDL_Surface *SDLGui_LoadXBM(int w, int h, const Uint8 *pXbmBits)
35: {
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: }
69:
70: return bitmap;
71: }
72:
73:
74: /*-----------------------------------------------------------------------*/
75: /**
76: * Initialize the GUI.
77: */
78: int SDLGui_Init(void)
79: {
80: SDL_Color blackWhiteColors[2] = {{255, 255, 255, 255}, {0, 0, 0, 255}};
81:
82: if (pSmallFontGfx && pBigFontGfx)
83: {
84: /* already initialized */
85: return 0;
86: }
87:
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_SetPaletteColors(pSmallFontGfx->format->palette, blackWhiteColors, 0, 2);
99: SDL_SetPaletteColors(pBigFontGfx->format->palette, blackWhiteColors, 0, 2);
100:
101: /* Set font color 0 as transparent: */
102: SDL_SetColorKey(pSmallFontGfx, (SDL_TRUE|SDL_RLEACCEL), 0);
103: SDL_SetColorKey(pBigFontGfx, (SDL_TRUE|SDL_RLEACCEL), 0);
104:
105: return 0;
106: }
107:
108:
109: /*-----------------------------------------------------------------------*/
110: /**
111: * Uninitialize the GUI.
112: */
113: int SDLGui_UnInit(void)
114: {
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: }
126:
127: return 0;
128: }
129:
130:
131: /*-----------------------------------------------------------------------*/
132: /**
133: * Inform the SDL-GUI about the actual SDL_Surface screen pointer and
134: * prepare the font to suit the actual resolution.
135: */
136: int SDLGui_SetScreen(SDL_Surface *pScrn)
137: {
138: pSdlGuiScrn = pScrn;
139:
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: sdlgui_fontwidth = pFontGfx->w/16;
158: sdlgui_fontheight = pFontGfx->h/16;
159:
160: return 0;
161: }
162:
163: /*-----------------------------------------------------------------------*/
164: /**
165: * Return character size for current font in given arguments.
166: */
167: void SDLGui_GetFontSize(int *width, int *height)
168: {
169: *width = sdlgui_fontwidth;
170: *height = sdlgui_fontheight;
171: }
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: {
181: dlg[0].x = (pSdlGuiScrn->w/sdlgui_fontwidth-dlg[0].w)/2;
182: dlg[0].y = (pSdlGuiScrn->h/sdlgui_fontheight-dlg[0].h)/2;
183: }
184:
185:
186: /*-----------------------------------------------------------------------*/
187: /**
188: * Draw a text string.
189: */
190: void SDLGui_Text(int x, int y, const char *txt)
191: {
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=sdlgui_fontwidth*(c%16);
200: sr.y=sdlgui_fontheight*(c/16);
201: sr.w=sdlgui_fontwidth;
202: sr.h=sdlgui_fontheight;
203: dr.x=x+i*sdlgui_fontwidth;
204: dr.y=y;
205: dr.w=sdlgui_fontwidth;
206: dr.h=sdlgui_fontheight;
207: SDL_BlitSurface(pFontGfx, &sr, pSdlGuiScrn, &dr);
208: }
209: }
210:
211:
212: /*-----------------------------------------------------------------------*/
213: /**
214: * Draw a dialog text object.
215: */
216: static void SDLGui_DrawText(const SGOBJ *tdlg, int objnum)
217: {
218: int x, y;
219: x = (tdlg[0].x+tdlg[objnum].x)*sdlgui_fontwidth;
220: y = (tdlg[0].y+tdlg[objnum].y)*sdlgui_fontheight;
221: SDLGui_Text(x, y, tdlg[objnum].txt);
222: }
223:
224:
225: /*-----------------------------------------------------------------------*/
226: /**
227: * Draw a edit field object.
228: */
229: static void SDLGui_DrawEditField(const SGOBJ *edlg, int objnum)
230: {
231: int x, y;
232: SDL_Rect rect;
233:
234: x = (edlg[0].x+edlg[objnum].x)*sdlgui_fontwidth;
235: y = (edlg[0].y+edlg[objnum].y)*sdlgui_fontheight;
236: SDLGui_Text(x, y, edlg[objnum].txt);
237:
238: rect.x = x;
239: rect.y = y + edlg[objnum].h * sdlgui_fontheight;
240: rect.w = edlg[objnum].w * sdlgui_fontwidth;
241: rect.h = 1;
242: SDL_FillRect(pSdlGuiScrn, &rect, SDL_MapRGB(pSdlGuiScrn->format,160,160,160));
243: }
244:
245:
246: /*-----------------------------------------------------------------------*/
247: /**
248: * Draw a dialog box object.
249: */
250: static void SDLGui_DrawBox(const SGOBJ *bdlg, int objnum)
251: {
252: SDL_Rect rect;
253: int x, y, w, h, offset;
254: Uint32 grey = SDL_MapRGB(pSdlGuiScrn->format,181,183,170);
255: Uint32 upleftc, downrightc;
256:
257: x = bdlg[objnum].x*sdlgui_fontwidth;
258: y = bdlg[objnum].y*sdlgui_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*sdlgui_fontwidth; /* add its absolute coordinates if we need to */
263: y += bdlg[0].y*sdlgui_fontheight;
264: }
265: w = bdlg[objnum].w*sdlgui_fontwidth;
266: h = bdlg[objnum].h*sdlgui_fontheight;
267:
268: if (bdlg[objnum].state & SG_SELECTED)
269: {
270: upleftc = SDL_MapRGB(pSdlGuiScrn->format,147,145,170);
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,147,145,170);
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);
319: }
320:
321:
322: /*-----------------------------------------------------------------------*/
323: /**
324: * Draw a normal button.
325: */
326: static void SDLGui_DrawButton(const SGOBJ *bdlg, int objnum)
327: {
328: int x,y;
329:
330: SDLGui_DrawBox(bdlg, objnum);
331:
332: x = (bdlg[0].x + bdlg[objnum].x + (bdlg[objnum].w-strlen(bdlg[objnum].txt))/2) * sdlgui_fontwidth;
333: y = (bdlg[0].y + bdlg[objnum].y + (bdlg[objnum].h-1)/2) * sdlgui_fontheight;
334:
335: if (bdlg[objnum].state & SG_SELECTED)
336: {
337: x+=1;
338: y+=1;
339: }
340: SDLGui_Text(x, y, bdlg[objnum].txt);
341: }
342:
343:
344: /*-----------------------------------------------------------------------*/
345: /**
346: * Draw a dialog radio button object.
347: */
348: static void SDLGui_DrawRadioButton(const SGOBJ *rdlg, int objnum)
349: {
350: char str[80];
351: int x, y;
352:
353: x = (rdlg[0].x + rdlg[objnum].x) * sdlgui_fontwidth;
354: y = (rdlg[0].y + rdlg[objnum].y) * sdlgui_fontheight;
355:
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);
362:
363: SDLGui_Text(x, y, str);
364: }
365:
366:
367: /*-----------------------------------------------------------------------*/
368: /**
369: * Draw a dialog check box object.
370: */
371: static void SDLGui_DrawCheckBox(const SGOBJ *cdlg, int objnum)
372: {
373: char str[80];
374: int x, y;
375:
376: x = (cdlg[0].x + cdlg[objnum].x) * sdlgui_fontwidth;
377: y = (cdlg[0].y + cdlg[objnum].y) * sdlgui_fontheight;
378:
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);
385:
386: SDLGui_Text(x, y, str);
387: }
388:
389:
390: /*-----------------------------------------------------------------------*/
391: /**
392: * Draw a scrollbar button.
393: */
394: static void SDLGui_DrawScrollbar(const SGOBJ *bdlg, int objnum)
395: {
396: SDL_Rect rect;
397: int x, y, w, h;
398: Uint32 grey0 = SDL_MapRGB(pSdlGuiScrn->format,147,145,170);
399: Uint32 grey1 = SDL_MapRGB(pSdlGuiScrn->format,181,183,170);
400: Uint32 grey2 = SDL_MapRGB(pSdlGuiScrn->format, 73, 72, 85);
401:
402: x = bdlg[objnum].x * sdlgui_fontwidth;
403: y = bdlg[objnum].y * sdlgui_fontheight + bdlg[objnum].h;
404:
405: x += bdlg[0].x*sdlgui_fontwidth; /* add mainbox absolute coordinates */
406: y += bdlg[0].y*sdlgui_fontheight; /* add mainbox absolute coordinates */
407:
408: w = 1 * sdlgui_fontwidth;
409: h = bdlg[objnum].w;
410:
411: /* Draw background: */
412: rect.x = x;
413: rect.y = y;
414: rect.w = w;
415: rect.h = h;
416: SDL_FillRect(pSdlGuiScrn, &rect, grey0);
417:
418: /* Draw upper border: */
419: rect.x = x;
420: rect.y = y;
421: rect.w = w;
422: rect.h = 1;
423: SDL_FillRect(pSdlGuiScrn, &rect, grey1);
424:
425: /* Draw bottom border: */
426: rect.x = x;
427: rect.y = y + h - 1;
428: rect.w = w;
429: rect.h = 1;
430: SDL_FillRect(pSdlGuiScrn, &rect, grey2);
431:
432: }
433:
434: /*-----------------------------------------------------------------------*/
435: /**
436: * Draw a dialog popup button object.
437: */
438: static void SDLGui_DrawPopupButton(const SGOBJ *pdlg, int objnum)
439: {
440: int x, y, w;
441: const char *downstr = "\x02";
442:
443: SDLGui_DrawBox(pdlg, objnum);
444:
445: x = (pdlg[0].x + pdlg[objnum].x) * sdlgui_fontwidth;
446: y = (pdlg[0].y + pdlg[objnum].y) * sdlgui_fontheight;
447: w = pdlg[objnum].w * sdlgui_fontwidth;
448:
449: SDLGui_Text(x, y, pdlg[objnum].txt);
450: SDLGui_Text(x+w-sdlgui_fontwidth, y, downstr);
451: }
452:
453:
454: /*-----------------------------------------------------------------------*/
455: /**
456: * Let the user insert text into an edit field object.
457: * NOTE: The dlg[objnum].txt must point to an an array that is big enough
458: * for dlg[objnum].w characters!
459: */
460: static void SDLGui_EditField(SGOBJ *dlg, int objnum)
461: {
462: size_t cursorPos; /* Position of the cursor in the edit field */
463: int blinkState = 0; /* Used for cursor blinking */
464: int bStopEditing = false; /* true if user wants to exit the edit field */
465: char *txt; /* Shortcut for dlg[objnum].txt */
466: SDL_Rect rect;
467: Uint32 grey, cursorCol;
468: SDL_Event event;
469:
470: /* Enable text input to get unicode characters with SDL_TEXTINPUT event */
471: SDL_SetTextInputRect(&rect);
472: SDL_StartTextInput();
473:
474: grey = SDL_MapRGB(pSdlGuiScrn->format, 181, 183, 170);
475: cursorCol = SDL_MapRGB(pSdlGuiScrn->format, 147, 145, 170);
476:
477: rect.x = (dlg[0].x + dlg[objnum].x) * sdlgui_fontwidth;
478: rect.y = (dlg[0].y + dlg[objnum].y) * sdlgui_fontheight;
479: rect.w = (dlg[objnum].w + 1) * sdlgui_fontwidth - 1;
480: rect.h = dlg[objnum].h * sdlgui_fontheight;
481:
482: txt = dlg[objnum].txt;
483: cursorPos = strlen(txt);
484:
485: do
486: {
487: /* Look for events */
488: if (SDL_PollEvent(&event) == 0)
489: {
490: /* No event: Wait some time for cursor blinking */
491: SDL_Delay(250);
492: blinkState ^= 1;
493: }
494: else
495: {
496: /* Handle events */
497: do
498: {
499: switch (event.type)
500: {
501: case SDL_WINDOWEVENT:
502: if(event.window.event == SDL_WINDOWEVENT_CLOSE) {
503: bQuitProgram = true;
504: bStopEditing = true;
505: }
506: break;
507: case SDL_QUIT: /* User wants to quit */
508: bQuitProgram = true;
509: bStopEditing = true;
510: break;
511: case SDL_MOUSEBUTTONDOWN: /* Mouse pressed -> stop editing */
512: bStopEditing = true;
513: break;
514: case SDL_KEYDOWN: /* Key pressed */
515: switch (event.key.keysym.sym)
516: {
517: case SDLK_RETURN:
518: case SDLK_KP_ENTER:
519: bStopEditing = true;
520: break;
521: case SDLK_LEFT:
522: if (cursorPos > 0)
523: cursorPos -= 1;
524: break;
525: case SDLK_RIGHT:
526: if (cursorPos < strlen(txt))
527: cursorPos += 1;
528: break;
529: case SDLK_BACKSPACE:
530: if (cursorPos > 0)
531: {
532: memmove(&txt[cursorPos-1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
533: cursorPos -= 1;
534: }
535: break;
536: case SDLK_DELETE:
537: if (cursorPos < strlen(txt))
538: memmove(&txt[cursorPos], &txt[cursorPos+1], strlen(&txt[cursorPos+1])+1);
539: break;
540: default:
541: /* Get other keys from SDL_TEXTINPUT event */
542: break;
543: }
544: break;
545: case SDL_TEXTINPUT:
546: if (strlen(txt) < (size_t)dlg[objnum].w)
547: {
548: memmove(&txt[cursorPos+1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
549: txt[cursorPos] = event.text.text[0];
550: cursorPos += 1;
551: }
552: break;
553: }
554: break;
555: }
556: while (SDL_PollEvent(&event));
557:
558: blinkState = 1;
559: }
560:
561: /* Redraw the text field: */
562: SDL_FillRect(pSdlGuiScrn, &rect, grey); /* Draw background */
563: /* Draw the cursor: */
564: if (blinkState && !bStopEditing)
565: {
566: SDL_Rect cursorrect;
567: cursorrect.x = rect.x + cursorPos * sdlgui_fontwidth;
568: cursorrect.y = rect.y;
569: cursorrect.w = sdlgui_fontwidth;
570: cursorrect.h = rect.h;
571: SDL_FillRect(pSdlGuiScrn, &cursorrect, cursorCol);
572: }
573: SDLGui_Text(rect.x, rect.y, dlg[objnum].txt); /* Draw text */
574: SDL_UpdateRects(pSdlGuiScrn, 1, &rect);
575: }
576: while (!bStopEditing);
577:
578: SDL_StopTextInput();
579: }
580:
581:
582: /*-----------------------------------------------------------------------*/
583: /**
584: * Draw a whole dialog.
585: */
586: void SDLGui_DrawDialog(const SGOBJ *dlg)
587: {
588: int i;
589: for (i = 0; dlg[i].type != -1; i++)
590: {
591: switch (dlg[i].type)
592: {
593: case SGBOX:
594: SDLGui_DrawBox(dlg, i);
595: break;
596: case SGTEXT:
597: SDLGui_DrawText(dlg, i);
598: break;
599: case SGEDITFIELD:
600: SDLGui_DrawEditField(dlg, i);
601: break;
602: case SGBUTTON:
603: SDLGui_DrawButton(dlg, i);
604: break;
605: case SGRADIOBUT:
606: SDLGui_DrawRadioButton(dlg, i);
607: break;
608: case SGCHECKBOX:
609: SDLGui_DrawCheckBox(dlg, i);
610: break;
611: case SGPOPUP:
612: SDLGui_DrawPopupButton(dlg, i);
613: break;
614: case SGSCROLLBAR:
615: SDLGui_DrawScrollbar(dlg, i);
616: break;
617: }
618: }
619: SDL_UpdateRect(pSdlGuiScrn, 0,0,0,0);
620: }
621:
622:
623: /*-----------------------------------------------------------------------*/
624: /**
625: * Search an object at a certain position.
626: */
627: static int SDLGui_FindObj(const SGOBJ *dlg, int fx, int fy)
628: {
629: int len, i;
630: int ob = -1;
631: int xpos, ypos;
632:
633: len = 0;
634: while (dlg[len].type != -1) len++;
635:
636: xpos = fx / sdlgui_fontwidth;
637: ypos = fy / sdlgui_fontheight;
638: /* Now search for the object: */
639: for (i = len; i >= 0; i--)
640: {
641: /* clicked on a scrollbar ? */
642: if (dlg[i].type == SGSCROLLBAR) {
643: if (xpos >= dlg[0].x+dlg[i].x && xpos < dlg[0].x+dlg[i].x+1) {
644: ypos = dlg[i].y * sdlgui_fontheight + dlg[i].h + dlg[0].y * sdlgui_fontheight;
645: if (fy >= ypos && fy < ypos + dlg[i].w) {
646: ob = i;
647: break;
648: }
649: }
650: }
651: /* clicked on another object ? */
652: else if (xpos >= dlg[0].x+dlg[i].x && ypos >= dlg[0].y+dlg[i].y
653: && xpos < dlg[0].x+dlg[i].x+dlg[i].w && ypos < dlg[0].y+dlg[i].y+dlg[i].h)
654: {
655: ob = i;
656: break;
657: }
658: }
659:
660: return ob;
661: }
662:
663:
664: /*-----------------------------------------------------------------------*/
665: /**
666: * Search a button with a special flag (e.g. SG_DEFAULT or SG_CANCEL).
667: */
668: static int SDLGui_SearchFlaggedButton(const SGOBJ *dlg, int flag)
669: {
670: int i = 0;
671:
672: while (dlg[i].type != -1)
673: {
674: if (dlg[i].flags & flag)
675: return i;
676: i++;
677: }
678:
679: return 0;
680: }
681:
682:
683: /*-----------------------------------------------------------------------*/
684: /**
685: * Show and process a dialog. Returns the button number that has been
686: * pressed or SDLGUI_UNKNOWNEVENT if an unsupported event occured (will be
687: * stored in parameter pEventOut).
688: */
689: int SDLGui_DoDialog(SGOBJ *dlg, SDL_Event *pEventOut)
690: {
691: int obj=0;
692: int oldbutton=0;
693: int retbutton=0;
694: int i, j, b;
695: SDL_Event sdlEvent;
696: SDL_Rect rct;
697: Uint32 grey;
698: SDL_Surface *pBgSurface;
699: SDL_Rect dlgrect, bgrect;
700:
701: if (pSdlGuiScrn->h / sdlgui_fontheight < dlg[0].h)
702: {
703: fprintf(stderr, "Screen size too small for dialog!\n");
704: return SDLGUI_ERROR;
705: }
706:
707: grey = SDL_MapRGB(pSdlGuiScrn->format,181,183,170);
708:
709: dlgrect.x = dlg[0].x * sdlgui_fontwidth;
710: dlgrect.y = dlg[0].y * sdlgui_fontheight;
711: dlgrect.w = dlg[0].w * sdlgui_fontwidth;
712: dlgrect.h = dlg[0].h * sdlgui_fontheight;
713:
714: bgrect.x = bgrect.y = 0;
715: bgrect.w = dlgrect.w;
716: bgrect.h = dlgrect.h;
717:
718: /* Save background */
719: pBgSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, dlgrect.w, dlgrect.h, pSdlGuiScrn->format->BitsPerPixel,
720: pSdlGuiScrn->format->Rmask, pSdlGuiScrn->format->Gmask, pSdlGuiScrn->format->Bmask, pSdlGuiScrn->format->Amask);
721: if (pSdlGuiScrn->format->palette != NULL)
722: {
723: SDL_SetPaletteColors(pBgSurface->format->palette, pSdlGuiScrn->format->palette->colors, 0, pSdlGuiScrn->format->palette->ncolors-1);
724: }
725:
726: if (pBgSurface != NULL)
727: {
728: SDL_BlitSurface(pSdlGuiScrn, &dlgrect, pBgSurface, &bgrect);
729: }
730: else
731: {
732: fprintf(stderr, "SDLGUI_DoDialog: CreateRGBSurface failed: %s\n", SDL_GetError());
733: }
734:
735: /* (Re-)draw the dialog */
736: SDLGui_DrawDialog(dlg);
737:
738: /* Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */
739: SDL_PumpEvents();
740: b = SDL_GetMouseState(&i, &j);
741:
742: /* If current object is the scrollbar, and mouse is still down, we can scroll it */
743: /* also if the mouse pointer has left the scrollbar */
744: if (dlg[current_object].type == SGSCROLLBAR) {
745: if (b & SDL_BUTTON(1)) {
746: obj = current_object;
747: dlg[obj].state |= SG_MOUSEDOWN;
748: oldbutton = obj;
749: retbutton = obj;
750: }
751: else {
752: obj = current_object;
753: current_object = 0;
754: dlg[obj].state &= SG_MOUSEUP;
755: retbutton = obj;
756: oldbutton = obj;
757: }
758: }
759: else {
760: obj = SDLGui_FindObj(dlg, i, j);
761: current_object = obj;
762: if (obj > 0 && (dlg[obj].flags&SG_TOUCHEXIT) )
763: {
764: oldbutton = obj;
765: if (b & SDL_BUTTON(1))
766: {
767: dlg[obj].state |= SG_SELECTED;
768: retbutton = obj;
769: }
770: }
771: }
772:
773:
774: /* The main loop */
775: while (retbutton == 0 && !bQuitProgram)
776: {
777: if (SDL_WaitEvent(&sdlEvent) == 1) /* Wait for events */
778:
779: switch (sdlEvent.type)
780: {
781: case SDL_QUIT:
782: retbutton = SDLGUI_QUIT;
783: break;
784:
785: case SDL_MOUSEBUTTONDOWN:
786: if (sdlEvent.button.button != SDL_BUTTON_LEFT)
787: {
788: /* Not left mouse button -> unsupported event */
789: if (pEventOut)
790: retbutton = SDLGUI_UNKNOWNEVENT;
791: break;
792: }
793: /* It was the left button: Find the object under the mouse cursor */
794: obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y);
795: if (obj>0)
796: {
797: if (dlg[obj].type==SGBUTTON)
798: {
799: dlg[obj].state |= SG_SELECTED;
800: SDLGui_DrawButton(dlg, obj);
801: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[obj].y)*sdlgui_fontheight-2,
802: dlg[obj].w*sdlgui_fontwidth+4, dlg[obj].h*sdlgui_fontheight+4);
803: oldbutton=obj;
804: }
805: if (dlg[obj].type==SGSCROLLBAR)
806: {
807: dlg[obj].state |= SG_MOUSEDOWN;
808: oldbutton=obj;
809: }
810: if ( dlg[obj].flags&SG_TOUCHEXIT )
811: {
812: dlg[obj].state |= SG_SELECTED;
813: retbutton = obj;
814: }
815: }
816: break;
817:
818: case SDL_MOUSEBUTTONUP:
819: if (sdlEvent.button.button != SDL_BUTTON_LEFT)
820: {
821: /* Not left mouse button -> unsupported event */
822: if (pEventOut)
823: retbutton = SDLGUI_UNKNOWNEVENT;
824: break;
825: }
826: /* It was the left button: Find the object under the mouse cursor */
827: obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y);
828: if (obj>0)
829: {
830: switch (dlg[obj].type)
831: {
832: case SGBUTTON:
833: if (oldbutton==obj)
834: retbutton=obj;
835: break;
836: case SGSCROLLBAR:
837: dlg[obj].state &= SG_MOUSEUP;
838:
839: if (oldbutton==obj)
840: retbutton=obj;
841: break;
842: case SGEDITFIELD:
843: SDLGui_EditField(dlg, obj);
844: break;
845: case SGRADIOBUT:
846: for (i = obj-1; i > 0 && dlg[i].type == SGRADIOBUT; i--)
847: {
848: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
849: rct.x = (dlg[0].x+dlg[i].x)*sdlgui_fontwidth;
850: rct.y = (dlg[0].y+dlg[i].y)*sdlgui_fontheight;
851: rct.w = sdlgui_fontwidth;
852: rct.h = sdlgui_fontheight;
853: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
854: SDLGui_DrawRadioButton(dlg, i);
855: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
856: }
857: for (i = obj+1; dlg[i].type == SGRADIOBUT; i++)
858: {
859: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
860: rct.x = (dlg[0].x+dlg[i].x)*sdlgui_fontwidth;
861: rct.y = (dlg[0].y+dlg[i].y)*sdlgui_fontheight;
862: rct.w = sdlgui_fontwidth;
863: rct.h = sdlgui_fontheight;
864: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
865: SDLGui_DrawRadioButton(dlg, i);
866: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
867: }
868: dlg[obj].state |= SG_SELECTED; /* Select this radio button */
869: rct.x = (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth;
870: rct.y = (dlg[0].y+dlg[obj].y)*sdlgui_fontheight;
871: rct.w = sdlgui_fontwidth;
872: rct.h = sdlgui_fontheight;
873: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
874: SDLGui_DrawRadioButton(dlg, obj);
875: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
876: retbutton = obj; // added by andreas_g
877: break;
878: case SGCHECKBOX:
879: dlg[obj].state ^= SG_SELECTED;
880: rct.x = (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth;
881: rct.y = (dlg[0].y+dlg[obj].y)*sdlgui_fontheight;
882: rct.w = sdlgui_fontwidth;
883: rct.h = sdlgui_fontheight;
884: SDL_FillRect(pSdlGuiScrn, &rct, grey); /* Clear old */
885: SDLGui_DrawCheckBox(dlg, obj);
886: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
887: retbutton = obj; // added by andreas_g
888: break;
889: case SGPOPUP:
890: dlg[obj].state |= SG_SELECTED;
891: SDLGui_DrawPopupButton(dlg, obj);
892: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[obj].y)*sdlgui_fontheight-2,
893: dlg[obj].w*sdlgui_fontwidth+4, dlg[obj].h*sdlgui_fontheight+4);
894: retbutton=obj;
895: break;
896: case SGHIDDEN:
897: retbutton=obj;
898: break;
899: }
900: }
901: if (oldbutton > 0 && dlg[oldbutton].type == SGBUTTON)
902: {
903: dlg[oldbutton].state &= ~SG_SELECTED;
904: SDLGui_DrawButton(dlg, oldbutton);
905: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[oldbutton].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[oldbutton].y)*sdlgui_fontheight-2,
906: dlg[oldbutton].w*sdlgui_fontwidth+4, dlg[oldbutton].h*sdlgui_fontheight+4);
907: oldbutton = 0;
908: }
909: if (obj >= 0 && (dlg[obj].flags&SG_EXIT))
910: {
911: retbutton = obj;
912: }
913: break;
914:
915: case SDL_JOYAXISMOTION:
916: case SDL_JOYBALLMOTION:
917: case SDL_JOYHATMOTION:
918: case SDL_MOUSEMOTION:
919: break;
920:
921: case SDL_KEYDOWN: /* Key pressed */
922: if (sdlEvent.key.keysym.sym == SDLK_RETURN
923: || sdlEvent.key.keysym.sym == SDLK_KP_ENTER)
924: {
925: retbutton = SDLGui_SearchFlaggedButton(dlg, SG_DEFAULT);
926: }
927: else if (sdlEvent.key.keysym.sym == SDLK_ESCAPE)
928: {
929: retbutton = SDLGui_SearchFlaggedButton(dlg, SG_CANCEL);
930: }
931: else if (pEventOut)
932: {
933: retbutton = SDLGUI_UNKNOWNEVENT;
934: }
935: break;
936:
937: default:
938: if (pEventOut)
939: retbutton = SDLGUI_UNKNOWNEVENT;
940: break;
941: }
942: }
943:
944: /* Restore background */
945: if (pBgSurface)
946: {
947: SDL_BlitSurface(pBgSurface, &bgrect, pSdlGuiScrn, &dlgrect);
948: SDL_FreeSurface(pBgSurface);
949: }
950:
951: /* Copy event data of unsupported events if caller wants to have it */
952: if (retbutton == SDLGUI_UNKNOWNEVENT && pEventOut)
953: memcpy(pEventOut, &sdlEvent, sizeof(SDL_Event));
954:
955: if (retbutton == SDLGUI_QUIT)
956: bQuitProgram = true;
957:
958: return retbutton;
959: }
960:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.