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