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