|
|
1.1 root 1: /*
2: Hatari - sdlgui.c
3:
1.1.1.13 root 4: This file is distributed under the GNU General Public License, version 2
5: or at your option any later version. Read the file gpl.txt for details.
1.1 root 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>
1.1.1.14! root 14: #include <stdlib.h>
1.1 root 15:
16: #include "main.h"
1.1.1.14! root 17: #include "screen.h"
1.1 root 18: #include "sdlgui.h"
1.1.1.14! root 19: #include "str.h"
1.1 root 20:
21: #include "font5x8.h"
22: #include "font10x16.h"
23:
1.1.1.14! root 24: #if WITH_SDL2
! 25: #define SDL_SRCCOLORKEY SDL_TRUE
! 26: #define SDLKey SDL_Keycode
! 27:
! 28: #endif
1.1 root 29:
1.1.1.2 root 30: static SDL_Surface *pSdlGuiScrn; /* Pointer to the actual main SDL screen surface */
1.1 root 31: static SDL_Surface *pSmallFontGfx = NULL; /* The small font graphics */
32: static SDL_Surface *pBigFontGfx = NULL; /* The big font graphics */
1.1.1.2 root 33: static SDL_Surface *pFontGfx = NULL; /* The actual font graphics */
1.1.1.10 root 34: static int current_object = 0; /* Current selected object */
1.1 root 35:
1.1.1.14! root 36: static struct {
! 37: Uint32 darkbar, midbar, lightbar;
! 38: Uint32 darkgrey, midgrey, lightgrey;
! 39: Uint32 focus, cursor, underline, editfield;
! 40: } colors;
! 41:
1.1.1.11 root 42: int sdlgui_fontwidth; /* Width of the actual font */
43: int sdlgui_fontheight; /* Height of the actual font */
44:
1.1.1.14! root 45: #define UNDERLINE_INDICATOR '_'
! 46:
! 47:
1.1 root 48: /*-----------------------------------------------------------------------*/
1.1.1.9 root 49: /**
50: * Load an 1 plane XBM into a 8 planes SDL_Surface.
51: */
1.1.1.4 root 52: static SDL_Surface *SDLGui_LoadXBM(int w, int h, const Uint8 *pXbmBits)
1.1 root 53: {
1.1.1.5 root 54: SDL_Surface *bitmap;
55: Uint8 *dstbits;
56: const Uint8 *srcbits;
57: int x, y, srcpitch;
58: int mask;
59:
60: srcbits = pXbmBits;
61:
62: /* Allocate the bitmap */
63: bitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 8, 0, 0, 0, 0);
64: if (bitmap == NULL)
65: {
66: fprintf(stderr, "Failed to allocate bitmap: %s", SDL_GetError());
67: return NULL;
68: }
69:
70: srcpitch = ((w + 7) / 8);
71: dstbits = (Uint8 *)bitmap->pixels;
72: mask = 1;
73:
74: /* Copy the pixels */
75: for (y = 0 ; y < h ; y++)
76: {
77: for (x = 0 ; x < w ; x++)
78: {
79: dstbits[x] = (srcbits[x / 8] & mask) ? 1 : 0;
80: mask <<= 1;
81: mask |= (mask >> 8);
82: mask &= 0xFF;
83: }
84: dstbits += bitmap->pitch;
85: srcbits += srcpitch;
86: }
1.1 root 87:
1.1.1.5 root 88: return bitmap;
1.1 root 89: }
90:
91:
92: /*-----------------------------------------------------------------------*/
1.1.1.9 root 93: /**
94: * Initialize the GUI.
95: */
1.1 root 96: int SDLGui_Init(void)
97: {
1.1.1.14! root 98: SDL_Color blackWhiteColors[2] = {{255, 255, 255, 255}, {0, 0, 0, 255}};
1.1 root 99:
1.1.1.6 root 100: if (pSmallFontGfx && pBigFontGfx)
101: {
102: /* already initialized */
103: return 0;
104: }
105:
1.1.1.5 root 106: /* Initialize the font graphics: */
107: pSmallFontGfx = SDLGui_LoadXBM(font5x8_width, font5x8_height, font5x8_bits);
108: pBigFontGfx = SDLGui_LoadXBM(font10x16_width, font10x16_height, font10x16_bits);
109: if (pSmallFontGfx == NULL || pBigFontGfx == NULL)
110: {
111: fprintf(stderr, "Error: Can not init font graphics!\n");
112: return -1;
113: }
114:
115: /* Set color palette of the font graphics: */
116: SDL_SetColors(pSmallFontGfx, blackWhiteColors, 0, 2);
117: SDL_SetColors(pBigFontGfx, blackWhiteColors, 0, 2);
118:
119: /* Set font color 0 as transparent: */
120: SDL_SetColorKey(pSmallFontGfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), 0);
121: SDL_SetColorKey(pBigFontGfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), 0);
1.1 root 122:
1.1.1.5 root 123: return 0;
1.1 root 124: }
125:
126:
127: /*-----------------------------------------------------------------------*/
1.1.1.9 root 128: /**
129: * Uninitialize the GUI.
130: */
1.1 root 131: int SDLGui_UnInit(void)
132: {
1.1.1.5 root 133: if (pSmallFontGfx)
134: {
135: SDL_FreeSurface(pSmallFontGfx);
136: pSmallFontGfx = NULL;
137: }
138:
139: if (pBigFontGfx)
140: {
141: SDL_FreeSurface(pBigFontGfx);
142: pBigFontGfx = NULL;
143: }
1.1 root 144:
1.1.1.5 root 145: return 0;
1.1 root 146: }
147:
148:
149: /*-----------------------------------------------------------------------*/
1.1.1.9 root 150: /**
151: * Inform the SDL-GUI about the actual SDL_Surface screen pointer and
152: * prepare the font to suit the actual resolution.
153: */
1.1.1.2 root 154: int SDLGui_SetScreen(SDL_Surface *pScrn)
1.1 root 155: {
1.1.1.5 root 156: pSdlGuiScrn = pScrn;
1.1.1.2 root 157:
1.1.1.5 root 158: /* Decide which font to use - small or big one: */
159: if (pSdlGuiScrn->w >= 640 && pSdlGuiScrn->h >= 400 && pBigFontGfx != NULL)
160: {
161: pFontGfx = pBigFontGfx;
162: }
163: else
164: {
165: pFontGfx = pSmallFontGfx;
166: }
167:
168: if (pFontGfx == NULL)
169: {
1.1.1.13 root 170: fprintf(stderr, "Error: A problem with the font occurred!\n");
1.1.1.5 root 171: return -1;
172: }
173:
174: /* Get the font width and height: */
1.1.1.10 root 175: sdlgui_fontwidth = pFontGfx->w/16;
176: sdlgui_fontheight = pFontGfx->h/16;
1.1 root 177:
1.1.1.14! root 178: /* scrollbar */
! 179: colors.darkbar = SDL_MapRGB(pSdlGuiScrn->format, 64, 64, 64);
! 180: colors.midbar = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
! 181: colors.lightbar = SDL_MapRGB(pSdlGuiScrn->format,196,196,196);
! 182: /* buttons, midgray is also normal bg color */
! 183: colors.darkgrey = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
! 184: colors.midgrey = SDL_MapRGB(pSdlGuiScrn->format,192,192,192);
! 185: colors.lightgrey = SDL_MapRGB(pSdlGuiScrn->format,255,255,255);
! 186: /* others */
! 187: colors.focus = SDL_MapRGB(pSdlGuiScrn->format,212,212,212);
! 188: colors.cursor = SDL_MapRGB(pSdlGuiScrn->format,128,128,128);
! 189: if (sdlgui_fontheight < 16)
! 190: colors.underline = SDL_MapRGB(pSdlGuiScrn->format,255,0,255);
! 191: else
! 192: colors.underline = SDL_MapRGB(pSdlGuiScrn->format,0,0,0);
! 193: colors.editfield = SDL_MapRGB(pSdlGuiScrn->format,160,160,160);
! 194:
1.1.1.5 root 195: return 0;
1.1 root 196: }
197:
1.1.1.6 root 198: /*-----------------------------------------------------------------------*/
1.1.1.9 root 199: /**
200: * Return character size for current font in given arguments.
201: */
1.1.1.6 root 202: void SDLGui_GetFontSize(int *width, int *height)
203: {
1.1.1.10 root 204: *width = sdlgui_fontwidth;
205: *height = sdlgui_fontheight;
1.1.1.6 root 206: }
1.1 root 207:
208: /*-----------------------------------------------------------------------*/
1.1.1.9 root 209: /**
210: * Center a dialog so that it appears in the middle of the screen.
211: * Note: We only store the coordinates in the root box of the dialog,
212: * all other objects in the dialog are positioned relatively to this one.
213: */
1.1 root 214: void SDLGui_CenterDlg(SGOBJ *dlg)
215: {
1.1.1.10 root 216: dlg[0].x = (pSdlGuiScrn->w/sdlgui_fontwidth-dlg[0].w)/2;
217: dlg[0].y = (pSdlGuiScrn->h/sdlgui_fontheight-dlg[0].h)/2;
1.1 root 218: }
219:
1.1.1.14! root 220: /*-----------------------------------------------------------------------*/
! 221: /**
! 222: * Return text length which ignores underlining.
! 223: */
! 224: static int SDLGui_TextLen(const char *str)
! 225: {
! 226: int len;
! 227: for (len = 0; *str; str++)
! 228: {
! 229: if (*str != UNDERLINE_INDICATOR)
! 230: len++;
! 231: }
! 232: return len;
! 233: }
1.1 root 234:
235: /*-----------------------------------------------------------------------*/
1.1.1.9 root 236: /**
1.1.1.14! root 237: * Draw a text string (internal version).
1.1.1.9 root 238: */
1.1.1.14! root 239: static void SDLGui_TextInt(int x, int y, const char *txt, bool underline)
1.1 root 240: {
1.1.1.14! root 241: int i, offset;
1.1.1.13 root 242: unsigned char c;
1.1.1.5 root 243: SDL_Rect sr, dr;
244:
1.1.1.14! root 245: /* underline offset needs to go outside the box for smaller font */
! 246: if (sdlgui_fontheight < 16)
! 247: offset = sdlgui_fontheight - 1;
! 248: else
! 249: offset = sdlgui_fontheight - 2;
! 250:
! 251: i = 0;
! 252: while (txt[i])
1.1.1.5 root 253: {
1.1.1.14! root 254: dr.x=x;
! 255: dr.y=y;
! 256: dr.w=sdlgui_fontwidth;
! 257: dr.h=sdlgui_fontheight;
! 258:
! 259: c = txt[i++];
! 260: if (c == UNDERLINE_INDICATOR && underline)
! 261: {
! 262: dr.h = 1;
! 263: dr.y += offset;
! 264: SDL_FillRect(pSdlGuiScrn, &dr, colors.underline);
! 265: continue;
! 266: }
! 267: /* for now, assume (only) Linux file paths are UTF-8 */
! 268: #if !(defined(WIN32) || defined(USE_LOCALE_CHARSET))
! 269: /* Quick and dirty convertion for latin1 characters only... */
! 270: if ((c & 0xc0) == 0xc0)
! 271: {
! 272: c = c << 6;
! 273: c |= (txt[i++]) & 0x7f;
! 274: }
! 275: else if (c >= 0x80)
! 276: {
! 277: printf("Unsupported character '%c' (0x%x)\n", c, c);
! 278: }
! 279: #endif
! 280: x += sdlgui_fontwidth;
! 281:
1.1.1.10 root 282: sr.x=sdlgui_fontwidth*(c%16);
283: sr.y=sdlgui_fontheight*(c/16);
284: sr.w=sdlgui_fontwidth;
285: sr.h=sdlgui_fontheight;
1.1.1.5 root 286: SDL_BlitSurface(pFontGfx, &sr, pSdlGuiScrn, &dr);
287: }
1.1 root 288: }
289:
1.1.1.14! root 290: /*-----------------------------------------------------------------------*/
! 291: /**
! 292: * Draw a text string (generic).
! 293: */
! 294: void SDLGui_Text(int x, int y, const char *txt)
! 295: {
! 296: SDLGui_TextInt(x, y, txt, false);
! 297: }
1.1 root 298:
299: /*-----------------------------------------------------------------------*/
1.1.1.9 root 300: /**
301: * Draw a dialog text object.
302: */
1.1.1.2 root 303: static void SDLGui_DrawText(const SGOBJ *tdlg, int objnum)
1.1 root 304: {
1.1.1.5 root 305: int x, y;
1.1.1.10 root 306: x = (tdlg[0].x+tdlg[objnum].x)*sdlgui_fontwidth;
307: y = (tdlg[0].y+tdlg[objnum].y)*sdlgui_fontheight;
1.1.1.14! root 308:
! 309: if (tdlg[objnum].flags & SG_EXIT)
! 310: {
! 311: SDL_Rect rect;
! 312: /* Draw background: */
! 313: rect.x = x;
! 314: rect.y = y;
! 315: rect.w = tdlg[objnum].w * sdlgui_fontwidth;
! 316: rect.h = tdlg[objnum].h * sdlgui_fontheight;
! 317: if (tdlg[objnum].state & SG_FOCUSED)
! 318: SDL_FillRect(pSdlGuiScrn, &rect, colors.focus);
! 319: else
! 320: SDL_FillRect(pSdlGuiScrn, &rect, colors.midgrey);
! 321: }
! 322:
1.1.1.5 root 323: SDLGui_Text(x, y, tdlg[objnum].txt);
1.1 root 324: }
325:
326:
327: /*-----------------------------------------------------------------------*/
1.1.1.9 root 328: /**
329: * Draw a edit field object.
330: */
1.1.1.2 root 331: static void SDLGui_DrawEditField(const SGOBJ *edlg, int objnum)
1.1 root 332: {
1.1.1.5 root 333: int x, y;
334: SDL_Rect rect;
1.1 root 335:
1.1.1.10 root 336: x = (edlg[0].x+edlg[objnum].x)*sdlgui_fontwidth;
337: y = (edlg[0].y+edlg[objnum].y)*sdlgui_fontheight;
1.1.1.5 root 338: SDLGui_Text(x, y, edlg[objnum].txt);
339:
340: rect.x = x;
1.1.1.10 root 341: rect.y = y + edlg[objnum].h * sdlgui_fontheight;
342: rect.w = edlg[objnum].w * sdlgui_fontwidth;
1.1.1.5 root 343: rect.h = 1;
1.1.1.14! root 344: SDL_FillRect(pSdlGuiScrn, &rect, colors.editfield);
1.1 root 345: }
346:
347:
348: /*-----------------------------------------------------------------------*/
1.1.1.9 root 349: /**
350: * Draw a dialog box object.
351: */
1.1.1.2 root 352: static void SDLGui_DrawBox(const SGOBJ *bdlg, int objnum)
1.1 root 353: {
1.1.1.5 root 354: SDL_Rect rect;
355: int x, y, w, h, offset;
1.1.1.14! root 356: Uint32 color, upleftc, downrightc;
! 357:
! 358: if (bdlg[objnum].state & SG_FOCUSED)
! 359: color = colors.focus;
! 360: else
! 361: color = colors.midgrey;
1.1.1.5 root 362:
1.1.1.10 root 363: x = bdlg[objnum].x*sdlgui_fontwidth;
364: y = bdlg[objnum].y*sdlgui_fontheight;
1.1.1.5 root 365: if (objnum > 0) /* Since the root object is a box, too, */
366: {
367: /* we have to look for it now here and only */
1.1.1.10 root 368: x += bdlg[0].x*sdlgui_fontwidth; /* add its absolute coordinates if we need to */
369: y += bdlg[0].y*sdlgui_fontheight;
1.1.1.5 root 370: }
1.1.1.10 root 371: w = bdlg[objnum].w*sdlgui_fontwidth;
372: h = bdlg[objnum].h*sdlgui_fontheight;
1.1.1.5 root 373:
374: if (bdlg[objnum].state & SG_SELECTED)
375: {
1.1.1.14! root 376: upleftc = colors.darkgrey;
! 377: downrightc = colors.lightgrey;
1.1.1.5 root 378: }
379: else
380: {
1.1.1.14! root 381: upleftc = colors.lightgrey;
! 382: downrightc = colors.darkgrey;
1.1.1.5 root 383: }
384:
385: /* The root box should be bigger than the screen, so we disable the offset there: */
386: if (objnum != 0)
387: offset = 1;
388: else
389: offset = 0;
390:
391: /* Draw background: */
392: rect.x = x;
393: rect.y = y;
394: rect.w = w;
395: rect.h = h;
1.1.1.14! root 396: SDL_FillRect(pSdlGuiScrn, &rect, color);
1.1.1.5 root 397:
398: /* Draw upper border: */
399: rect.x = x;
400: rect.y = y - offset;
401: rect.w = w;
402: rect.h = 1;
403: SDL_FillRect(pSdlGuiScrn, &rect, upleftc);
404:
405: /* Draw left border: */
406: rect.x = x - offset;
407: rect.y = y;
408: rect.w = 1;
409: rect.h = h;
410: SDL_FillRect(pSdlGuiScrn, &rect, upleftc);
411:
412: /* Draw bottom border: */
413: rect.x = x;
414: rect.y = y + h - 1 + offset;
415: rect.w = w;
416: rect.h = 1;
417: SDL_FillRect(pSdlGuiScrn, &rect, downrightc);
418:
419: /* Draw right border: */
420: rect.x = x + w - 1 + offset;
421: rect.y = y;
422: rect.w = 1;
423: rect.h = h;
424: SDL_FillRect(pSdlGuiScrn, &rect, downrightc);
1.1 root 425: }
426:
427:
428: /*-----------------------------------------------------------------------*/
1.1.1.9 root 429: /**
430: * Draw a normal button.
431: */
1.1.1.2 root 432: static void SDLGui_DrawButton(const SGOBJ *bdlg, int objnum)
1.1 root 433: {
1.1.1.5 root 434: int x,y;
1.1 root 435:
1.1.1.5 root 436: SDLGui_DrawBox(bdlg, objnum);
1.1 root 437:
1.1.1.14! root 438: x = (bdlg[0].x + bdlg[objnum].x + (bdlg[objnum].w-SDLGui_TextLen(bdlg[objnum].txt))/2) * sdlgui_fontwidth;
1.1.1.10 root 439: y = (bdlg[0].y + bdlg[objnum].y + (bdlg[objnum].h-1)/2) * sdlgui_fontheight;
1.1 root 440:
1.1.1.5 root 441: if (bdlg[objnum].state & SG_SELECTED)
442: {
443: x+=1;
444: y+=1;
445: }
1.1.1.14! root 446: SDLGui_TextInt(x, y, bdlg[objnum].txt, true);
1.1 root 447: }
448:
1.1.1.14! root 449: /*-----------------------------------------------------------------------*/
! 450: /**
! 451: * If object is focused, draw a focused background to it
! 452: */
! 453: static void SDLGui_DrawFocusBg(const SGOBJ *obj, int x, int y)
! 454: {
! 455: SDL_Rect rect;
! 456: Uint32 color;
! 457:
! 458: if (obj->state & SG_WASFOCUSED)
! 459: color = colors.midgrey;
! 460: else if (obj->state & SG_FOCUSED)
! 461: color = colors.focus;
! 462: else
! 463: return;
! 464:
! 465: rect.x = x;
! 466: rect.y = y;
! 467: rect.w = obj->w * sdlgui_fontwidth;
! 468: rect.h = obj->h * sdlgui_fontheight;
! 469:
! 470: SDL_FillRect(pSdlGuiScrn, &rect, color);
! 471: }
1.1 root 472:
473: /*-----------------------------------------------------------------------*/
1.1.1.9 root 474: /**
475: * Draw a dialog radio button object.
476: */
1.1.1.2 root 477: static void SDLGui_DrawRadioButton(const SGOBJ *rdlg, int objnum)
1.1 root 478: {
1.1.1.5 root 479: char str[80];
480: int x, y;
1.1 root 481:
1.1.1.10 root 482: x = (rdlg[0].x + rdlg[objnum].x) * sdlgui_fontwidth;
483: y = (rdlg[0].y + rdlg[objnum].y) * sdlgui_fontheight;
1.1.1.14! root 484: SDLGui_DrawFocusBg(&(rdlg[objnum]), x, y);
1.1 root 485:
1.1.1.5 root 486: if (rdlg[objnum].state & SG_SELECTED)
487: str[0]=SGRADIOBUTTON_SELECTED;
488: else
489: str[0]=SGRADIOBUTTON_NORMAL;
490: str[1]=' ';
491: strcpy(&str[2], rdlg[objnum].txt);
1.1 root 492:
1.1.1.14! root 493: SDLGui_TextInt(x, y, str, true);
1.1 root 494: }
495:
496:
497: /*-----------------------------------------------------------------------*/
1.1.1.9 root 498: /**
499: * Draw a dialog check box object.
500: */
1.1.1.2 root 501: static void SDLGui_DrawCheckBox(const SGOBJ *cdlg, int objnum)
1.1 root 502: {
1.1.1.5 root 503: char str[80];
504: int x, y;
1.1 root 505:
1.1.1.10 root 506: x = (cdlg[0].x + cdlg[objnum].x) * sdlgui_fontwidth;
507: y = (cdlg[0].y + cdlg[objnum].y) * sdlgui_fontheight;
1.1.1.14! root 508: SDLGui_DrawFocusBg(&(cdlg[objnum]), x, y);
1.1 root 509:
1.1.1.5 root 510: if ( cdlg[objnum].state&SG_SELECTED )
511: str[0]=SGCHECKBOX_SELECTED;
512: else
513: str[0]=SGCHECKBOX_NORMAL;
514: str[1]=' ';
515: strcpy(&str[2], cdlg[objnum].txt);
1.1 root 516:
1.1.1.14! root 517: SDLGui_TextInt(x, y, str, true);
1.1 root 518: }
519:
520:
521: /*-----------------------------------------------------------------------*/
1.1.1.9 root 522: /**
1.1.1.10 root 523: * Draw a scrollbar button.
524: */
525: static void SDLGui_DrawScrollbar(const SGOBJ *bdlg, int objnum)
526: {
527: SDL_Rect rect;
528: int x, y, w, h;
529:
530: x = bdlg[objnum].x * sdlgui_fontwidth;
531: y = bdlg[objnum].y * sdlgui_fontheight + bdlg[objnum].h;
532:
533: x += bdlg[0].x*sdlgui_fontwidth; /* add mainbox absolute coordinates */
534: y += bdlg[0].y*sdlgui_fontheight; /* add mainbox absolute coordinates */
535:
536: w = 1 * sdlgui_fontwidth;
537: h = bdlg[objnum].w;
538:
539: /* Draw background: */
540: rect.x = x;
541: rect.y = y;
542: rect.w = w;
543: rect.h = h;
1.1.1.14! root 544: SDL_FillRect(pSdlGuiScrn, &rect, colors.midbar);
1.1.1.10 root 545:
546: /* Draw upper border: */
547: rect.x = x;
548: rect.y = y;
549: rect.w = w;
550: rect.h = 1;
1.1.1.14! root 551: SDL_FillRect(pSdlGuiScrn, &rect, colors.lightbar);
1.1.1.10 root 552:
553: /* Draw bottom border: */
554: rect.x = x;
555: rect.y = y + h - 1;
556: rect.w = w;
557: rect.h = 1;
1.1.1.14! root 558: SDL_FillRect(pSdlGuiScrn, &rect, colors.darkbar);
1.1.1.10 root 559: }
560:
561: /*-----------------------------------------------------------------------*/
562: /**
1.1.1.9 root 563: * Draw a dialog popup button object.
564: */
1.1.1.2 root 565: static void SDLGui_DrawPopupButton(const SGOBJ *pdlg, int objnum)
1.1 root 566: {
1.1.1.10 root 567: int x, y, w;
1.1.1.5 root 568: const char *downstr = "\x02";
1.1 root 569:
1.1.1.5 root 570: SDLGui_DrawBox(pdlg, objnum);
1.1 root 571:
1.1.1.10 root 572: x = (pdlg[0].x + pdlg[objnum].x) * sdlgui_fontwidth;
573: y = (pdlg[0].y + pdlg[objnum].y) * sdlgui_fontheight;
574: w = pdlg[objnum].w * sdlgui_fontwidth;
1.1 root 575:
1.1.1.14! root 576: SDLGui_TextInt(x, y, pdlg[objnum].txt, true);
1.1.1.10 root 577: SDLGui_Text(x+w-sdlgui_fontwidth, y, downstr);
1.1 root 578: }
579:
580:
581: /*-----------------------------------------------------------------------*/
1.1.1.9 root 582: /**
583: * Let the user insert text into an edit field object.
584: * NOTE: The dlg[objnum].txt must point to an an array that is big enough
585: * for dlg[objnum].w characters!
586: */
1.1 root 587: static void SDLGui_EditField(SGOBJ *dlg, int objnum)
588: {
1.1.1.5 root 589: size_t cursorPos; /* Position of the cursor in the edit field */
590: int blinkState = 0; /* Used for cursor blinking */
1.1.1.8 root 591: int bStopEditing = false; /* true if user wants to exit the edit field */
1.1.1.5 root 592: char *txt; /* Shortcut for dlg[objnum].txt */
593: SDL_Rect rect;
594: SDL_Event event;
1.1.1.14! root 595: #if !WITH_SDL2
1.1.1.5 root 596: int nOldUnicodeMode;
1.1.1.14! root 597: #endif
1.1.1.5 root 598:
1.1.1.10 root 599: rect.x = (dlg[0].x + dlg[objnum].x) * sdlgui_fontwidth;
600: rect.y = (dlg[0].y + dlg[objnum].y) * sdlgui_fontheight;
601: rect.w = (dlg[objnum].w + 1) * sdlgui_fontwidth - 1;
602: rect.h = dlg[objnum].h * sdlgui_fontheight;
1.1.1.5 root 603:
1.1.1.14! root 604: #if WITH_SDL2
! 605: SDL_SetTextInputRect(&rect);
! 606: SDL_StartTextInput();
! 607: #else
! 608: /* Enable unicode translation to get shifted etc chars with SDL_PollEvent */
! 609: nOldUnicodeMode = SDL_EnableUNICODE(true);
! 610: #endif
! 611:
1.1.1.5 root 612: txt = dlg[objnum].txt;
613: cursorPos = strlen(txt);
614:
615: do
616: {
617: /* Look for events */
618: if (SDL_PollEvent(&event) == 0)
619: {
620: /* No event: Wait some time for cursor blinking */
621: SDL_Delay(250);
622: blinkState ^= 1;
623: }
624: else
625: {
626: /* Handle events */
627: do
628: {
629: switch (event.type)
630: {
631: case SDL_QUIT: /* User wants to quit */
1.1.1.8 root 632: bQuitProgram = true;
633: bStopEditing = true;
1.1.1.5 root 634: break;
635: case SDL_MOUSEBUTTONDOWN: /* Mouse pressed -> stop editing */
1.1.1.8 root 636: bStopEditing = true;
1.1.1.5 root 637: break;
1.1.1.14! root 638: #if WITH_SDL2
! 639: case SDL_TEXTINPUT:
! 640: if (strlen(txt) < (size_t)dlg[objnum].w)
! 641: {
! 642: memmove(&txt[cursorPos+1], &txt[cursorPos],
! 643: strlen(&txt[cursorPos])+1);
! 644: txt[cursorPos] = event.text.text[0];
! 645: cursorPos += 1;
! 646: }
! 647: break;
! 648: #endif
1.1.1.5 root 649: case SDL_KEYDOWN: /* Key pressed */
650: switch (event.key.keysym.sym)
651: {
652: case SDLK_RETURN:
653: case SDLK_KP_ENTER:
1.1.1.8 root 654: bStopEditing = true;
1.1.1.5 root 655: break;
656: case SDLK_LEFT:
657: if (cursorPos > 0)
658: cursorPos -= 1;
659: break;
660: case SDLK_RIGHT:
661: if (cursorPos < strlen(txt))
662: cursorPos += 1;
663: break;
664: case SDLK_BACKSPACE:
665: if (cursorPos > 0)
666: {
667: memmove(&txt[cursorPos-1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
668: cursorPos -= 1;
669: }
670: break;
671: case SDLK_DELETE:
672: if (cursorPos < strlen(txt))
673: memmove(&txt[cursorPos], &txt[cursorPos+1], strlen(&txt[cursorPos+1])+1);
674: break;
675: default:
1.1.1.14! root 676: #if !WITH_SDL2
1.1.1.5 root 677: /* If it is a "good" key then insert it into the text field */
678: if (event.key.keysym.unicode >= 32 && event.key.keysym.unicode < 128
679: && event.key.keysym.unicode != PATHSEP)
680: {
681: if (strlen(txt) < (size_t)dlg[objnum].w)
682: {
683: memmove(&txt[cursorPos+1], &txt[cursorPos], strlen(&txt[cursorPos])+1);
684: txt[cursorPos] = event.key.keysym.unicode;
685: cursorPos += 1;
686: }
687: }
1.1.1.14! root 688: #endif
1.1.1.5 root 689: break;
690: }
691: break;
692: }
693: }
694: while (SDL_PollEvent(&event));
695:
696: blinkState = 1;
697: }
698:
699: /* Redraw the text field: */
1.1.1.14! root 700: SDL_FillRect(pSdlGuiScrn, &rect, colors.midgrey); /* Draw background */
1.1.1.5 root 701: /* Draw the cursor: */
702: if (blinkState && !bStopEditing)
703: {
704: SDL_Rect cursorrect;
1.1.1.10 root 705: cursorrect.x = rect.x + cursorPos * sdlgui_fontwidth;
1.1.1.5 root 706: cursorrect.y = rect.y;
1.1.1.10 root 707: cursorrect.w = sdlgui_fontwidth;
1.1.1.5 root 708: cursorrect.h = rect.h;
1.1.1.14! root 709: SDL_FillRect(pSdlGuiScrn, &cursorrect, colors.cursor);
1.1.1.5 root 710: }
711: SDLGui_Text(rect.x, rect.y, dlg[objnum].txt); /* Draw text */
712: SDL_UpdateRects(pSdlGuiScrn, 1, &rect);
713: }
714: while (!bStopEditing);
715:
1.1.1.14! root 716: #if WITH_SDL2
! 717: SDL_StopTextInput();
! 718: #else
1.1.1.5 root 719: SDL_EnableUNICODE(nOldUnicodeMode);
1.1.1.14! root 720: #endif
1.1 root 721: }
722:
723:
724: /*-----------------------------------------------------------------------*/
1.1.1.9 root 725: /**
1.1.1.14! root 726: * Draw single object based on its type
! 727: */
! 728: static void SDLGui_DrawObj(const SGOBJ *dlg, int i)
! 729: {
! 730: switch (dlg[i].type)
! 731: {
! 732: case SGBOX:
! 733: SDLGui_DrawBox(dlg, i);
! 734: break;
! 735: case SGTEXT:
! 736: SDLGui_DrawText(dlg, i);
! 737: break;
! 738: case SGEDITFIELD:
! 739: SDLGui_DrawEditField(dlg, i);
! 740: break;
! 741: case SGBUTTON:
! 742: SDLGui_DrawButton(dlg, i);
! 743: break;
! 744: case SGRADIOBUT:
! 745: SDLGui_DrawRadioButton(dlg, i);
! 746: break;
! 747: case SGCHECKBOX:
! 748: SDLGui_DrawCheckBox(dlg, i);
! 749: break;
! 750: case SGPOPUP:
! 751: SDLGui_DrawPopupButton(dlg, i);
! 752: break;
! 753: case SGSCROLLBAR:
! 754: SDLGui_DrawScrollbar(dlg, i);
! 755: break;
! 756: }
! 757: }
! 758:
! 759: /*-----------------------------------------------------------------------*/
! 760: /**
1.1.1.9 root 761: * Draw a whole dialog.
762: */
1.1.1.3 root 763: void SDLGui_DrawDialog(const SGOBJ *dlg)
1.1 root 764: {
1.1.1.5 root 765: int i;
1.1.1.10 root 766:
1.1.1.5 root 767: for (i = 0; dlg[i].type != -1; i++)
768: {
1.1.1.14! root 769: SDLGui_DrawObj(dlg, i);
1.1.1.5 root 770: }
771: SDL_UpdateRect(pSdlGuiScrn, 0,0,0,0);
1.1 root 772: }
773:
774:
775: /*-----------------------------------------------------------------------*/
1.1.1.9 root 776: /**
777: * Search an object at a certain position.
1.1.1.12 root 778: * Return object index or -1 if it wasn't found.
1.1.1.9 root 779: */
1.1.1.2 root 780: static int SDLGui_FindObj(const SGOBJ *dlg, int fx, int fy)
1.1 root 781: {
1.1.1.5 root 782: int len, i;
783: int ob = -1;
784: int xpos, ypos;
785:
786: len = 0;
787: while (dlg[len].type != -1) len++;
1.1.1.10 root 788: xpos = fx / sdlgui_fontwidth;
789: ypos = fy / sdlgui_fontheight;
1.1.1.5 root 790: /* Now search for the object: */
791: for (i = len; i >= 0; i--)
792: {
1.1.1.10 root 793: /* clicked on a scrollbar ? */
794: if (dlg[i].type == SGSCROLLBAR) {
795: if (xpos >= dlg[0].x+dlg[i].x && xpos < dlg[0].x+dlg[i].x+1) {
796: ypos = dlg[i].y * sdlgui_fontheight + dlg[i].h + dlg[0].y * sdlgui_fontheight;
797: if (fy >= ypos && fy < ypos + dlg[i].w) {
798: ob = i;
799: break;
800: }
801: }
802: }
803: /* clicked on another object ? */
804: else if (xpos >= dlg[0].x+dlg[i].x && ypos >= dlg[0].y+dlg[i].y
1.1.1.5 root 805: && xpos < dlg[0].x+dlg[i].x+dlg[i].w && ypos < dlg[0].y+dlg[i].y+dlg[i].h)
806: {
807: ob = i;
808: break;
809: }
810: }
811:
812: return ob;
813: }
814:
815:
816: /*-----------------------------------------------------------------------*/
1.1.1.9 root 817: /**
1.1.1.14! root 818: * Search an object with a special flag (e.g. SG_DEFAULT or SG_CANCEL).
1.1.1.9 root 819: */
1.1.1.14! root 820: static int SDLGui_SearchFlags(const SGOBJ *dlg, int flag)
1.1.1.5 root 821: {
822: int i = 0;
823:
824: while (dlg[i].type != -1)
825: {
826: if (dlg[i].flags & flag)
827: return i;
828: i++;
829: }
1.1.1.14! root 830: return 0;
! 831: }
1.1 root 832:
1.1.1.14! root 833: /*-----------------------------------------------------------------------*/
! 834: /**
! 835: * Search an object with a special state (e.g. SG_FOCUSED).
! 836: */
! 837: static int SDLGui_SearchState(const SGOBJ *dlg, int state)
! 838: {
! 839: int i = 0;
! 840:
! 841: while (dlg[i].type != -1)
! 842: {
! 843: if (dlg[i].state & state)
! 844: return i;
! 845: i++;
! 846: }
1.1.1.5 root 847: return 0;
1.1 root 848: }
849:
1.1.1.14! root 850: /*-----------------------------------------------------------------------*/
! 851: /**
! 852: * For given dialog object type, returns whether it could have shortcut key
! 853: */
! 854: static bool SDLGui_CanHaveShortcut(int kind)
! 855: {
! 856: if (kind == SGBUTTON || kind == SGRADIOBUT || kind == SGCHECKBOX)
! 857: return true;
! 858: return false;
! 859: }
! 860:
! 861: /*-----------------------------------------------------------------------*/
! 862: /**
! 863: * Check & set dialog item shortcut values based on their text strings.
! 864: * Asserts if dialog has same shortcut defined multiple times.
! 865: */
! 866: static void SDLGui_SetShortcuts(SGOBJ *dlg)
! 867: {
! 868: unsigned chr, used[256];
! 869: const char *str;
! 870: unsigned int i;
! 871:
! 872: memset(used, 0, sizeof(used));
! 873: for (i = 0; dlg[i].type != -1; i++)
! 874: {
! 875: if (!SDLGui_CanHaveShortcut(dlg[i].type))
! 876: continue;
! 877: if (!(str = dlg[i].txt))
! 878: continue;
! 879: while(*str)
! 880: {
! 881: if (*str++ == UNDERLINE_INDICATOR)
! 882: {
! 883: /* TODO: conversion */
! 884: chr = toupper(*str);
! 885: dlg[i].shortcut = chr;
! 886: if (used[chr])
! 887: {
! 888: fprintf(stderr, "ERROR: Duplicate Hatari SDL GUI shortcut in '%s'!\n", dlg[i].txt);
! 889: exit(1);
! 890: }
! 891: used[chr] = 1;
! 892: }
! 893: }
! 894: }
! 895: }
! 896:
! 897: /*-----------------------------------------------------------------------*/
! 898: /**
! 899: * Unfocus given button
! 900: */
! 901: static void SDLGui_RemoveFocus(SGOBJ *dlg, int old)
! 902: {
! 903: if (!old)
! 904: return;
! 905: dlg[old].state &= ~SG_FOCUSED;
! 906: dlg[old].state |= SG_WASFOCUSED;
! 907: SDLGui_DrawObj(dlg, old);
! 908: dlg[old].state ^= SG_WASFOCUSED;
! 909: }
! 910:
! 911: /*-----------------------------------------------------------------------*/
! 912: /**
! 913: * Search a next button to focus and focus it
! 914: */
! 915: static int SDLGui_FocusNext(SGOBJ *dlg, int i, int inc)
! 916: {
! 917: int old = i;
! 918: if (!i)
! 919: return i;
! 920:
! 921: for (;;)
! 922: {
! 923: i += inc;
! 924:
! 925: /* wrap */
! 926: if (dlg[i].type == -1)
! 927: {
! 928: i = 0;
! 929: }
! 930: else if (i == 0)
! 931: {
! 932: while (dlg[i].type != -1)
! 933: i++;
! 934: i--;
! 935: }
! 936: /* change focus for items that can have shortcuts
! 937: * and for items in Fsel lists
! 938: */
! 939: if (SDLGui_CanHaveShortcut(dlg[i].type) || (dlg[i].flags & SG_EXIT) != 0)
! 940: {
! 941: dlg[i].state |= SG_FOCUSED;
! 942: SDLGui_DrawObj(dlg, i);
! 943: SDL_UpdateRect(pSdlGuiScrn, 0,0,0,0);
! 944: return i;
! 945: }
! 946: /* wrapped around without even initial one matching */
! 947: if (i == old)
! 948: return 0;
! 949: }
! 950: return old;
! 951: }
! 952:
! 953:
! 954: /*-----------------------------------------------------------------------*/
! 955: /**
! 956: * Handle button selection, either with mouse or keyboard
! 957: */
! 958: static int SDLGui_HandleSelection(SGOBJ *dlg, int obj, int oldbutton)
! 959: {
! 960: SDL_Rect rct;
! 961: int i, retbutton = 0;
! 962:
! 963: switch (dlg[obj].type)
! 964: {
! 965: case SGBUTTON:
! 966: if (oldbutton==obj)
! 967: retbutton=obj;
! 968: break;
! 969: case SGSCROLLBAR:
! 970: dlg[obj].state &= ~SG_MOUSEDOWN;
! 971:
! 972: if (oldbutton==obj)
! 973: retbutton=obj;
! 974: break;
! 975: case SGEDITFIELD:
! 976: SDLGui_EditField(dlg, obj);
! 977: break;
! 978: case SGRADIOBUT:
! 979: for (i = obj-1; i > 0 && dlg[i].type == SGRADIOBUT; i--)
! 980: {
! 981: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
! 982: rct.x = (dlg[0].x+dlg[i].x)*sdlgui_fontwidth;
! 983: rct.y = (dlg[0].y+dlg[i].y)*sdlgui_fontheight;
! 984: rct.w = sdlgui_fontwidth;
! 985: rct.h = sdlgui_fontheight;
! 986: SDL_FillRect(pSdlGuiScrn, &rct, colors.midgrey); /* Clear old */
! 987: SDLGui_DrawRadioButton(dlg, i);
! 988: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
! 989: }
! 990: for (i = obj+1; dlg[i].type == SGRADIOBUT; i++)
! 991: {
! 992: dlg[i].state &= ~SG_SELECTED; /* Deselect all radio buttons in this group */
! 993: rct.x = (dlg[0].x+dlg[i].x)*sdlgui_fontwidth;
! 994: rct.y = (dlg[0].y+dlg[i].y)*sdlgui_fontheight;
! 995: rct.w = sdlgui_fontwidth;
! 996: rct.h = sdlgui_fontheight;
! 997: SDL_FillRect(pSdlGuiScrn, &rct, colors.midgrey); /* Clear old */
! 998: SDLGui_DrawRadioButton(dlg, i);
! 999: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
! 1000: }
! 1001: dlg[obj].state |= SG_SELECTED; /* Select this radio button */
! 1002: rct.x = (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth;
! 1003: rct.y = (dlg[0].y+dlg[obj].y)*sdlgui_fontheight;
! 1004: rct.w = sdlgui_fontwidth;
! 1005: rct.h = sdlgui_fontheight;
! 1006: SDL_FillRect(pSdlGuiScrn, &rct, colors.midgrey); /* Clear old */
! 1007: SDLGui_DrawRadioButton(dlg, obj);
! 1008: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
! 1009: break;
! 1010: case SGCHECKBOX:
! 1011: dlg[obj].state ^= SG_SELECTED;
! 1012: rct.x = (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth;
! 1013: rct.y = (dlg[0].y+dlg[obj].y)*sdlgui_fontheight;
! 1014: rct.w = sdlgui_fontwidth;
! 1015: rct.h = sdlgui_fontheight;
! 1016: SDL_FillRect(pSdlGuiScrn, &rct, colors.midgrey); /* Clear old */
! 1017: SDLGui_DrawCheckBox(dlg, obj);
! 1018: SDL_UpdateRects(pSdlGuiScrn, 1, &rct);
! 1019: break;
! 1020: case SGPOPUP:
! 1021: dlg[obj].state |= SG_SELECTED;
! 1022: SDLGui_DrawPopupButton(dlg, obj);
! 1023: SDL_UpdateRect(pSdlGuiScrn,
! 1024: (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth-2,
! 1025: (dlg[0].y+dlg[obj].y)*sdlgui_fontheight-2,
! 1026: dlg[obj].w*sdlgui_fontwidth+4,
! 1027: dlg[obj].h*sdlgui_fontheight+4);
! 1028: retbutton=obj;
! 1029: break;
! 1030: }
! 1031:
! 1032: if (!retbutton && (dlg[obj].flags & SG_EXIT) != 0)
! 1033: {
! 1034: retbutton = obj;
! 1035: }
! 1036:
! 1037: return retbutton;
! 1038: }
! 1039:
! 1040:
! 1041: /*-----------------------------------------------------------------------*/
! 1042: /**
! 1043: * If given shortcut matches item, handle that & return it's code,
! 1044: * otherwise return zero.
! 1045: */
! 1046: static int SDLGui_HandleShortcut(SGOBJ *dlg, int key)
! 1047: {
! 1048: int i = 0;
! 1049: while (dlg[i].type != -1)
! 1050: {
! 1051: if (dlg[i].shortcut == key)
! 1052: return SDLGui_HandleSelection(dlg, i, i);
! 1053: i++;
! 1054: }
! 1055: return 0;
! 1056: }
1.1 root 1057:
1058: /*-----------------------------------------------------------------------*/
1.1.1.9 root 1059: /**
1060: * Show and process a dialog. Returns the button number that has been
1.1.1.13 root 1061: * pressed or SDLGUI_UNKNOWNEVENT if an unsupported event occurred (will be
1.1.1.9 root 1062: * stored in parameter pEventOut).
1063: */
1.1.1.14! root 1064: int SDLGui_DoDialog(SGOBJ *dlg, SDL_Event *pEventOut, bool KeepCurrentObject)
1.1 root 1065: {
1.1.1.5 root 1066: int obj=0;
1067: int oldbutton=0;
1068: int retbutton=0;
1.1.1.14! root 1069: int i, j, b, value;
! 1070: SDLKey key;
! 1071: int focused;
1.1.1.5 root 1072: SDL_Event sdlEvent;
1073: SDL_Surface *pBgSurface;
1074: SDL_Rect dlgrect, bgrect;
1.1.1.14! root 1075: SDL_Joystick *joy = NULL;
! 1076: #if !WITH_SDL2
! 1077: int nOldUnicodeMode;
! 1078: #endif
! 1079:
! 1080: /* In the case of dialog using a scrollbar, we must keep the previous */
! 1081: /* value of current_object, as the same dialog is displayed in a loop */
! 1082: /* to handle scrolling. For other dialogs, we need to reset current_object */
! 1083: /* (ie no object selected at start when displaying the dialog) */
! 1084: if ( !KeepCurrentObject )
! 1085: current_object = 0;
1.1.1.5 root 1086:
1.1.1.10 root 1087: if (pSdlGuiScrn->h / sdlgui_fontheight < dlg[0].h)
1.1.1.5 root 1088: {
1089: fprintf(stderr, "Screen size too small for dialog!\n");
1090: return SDLGUI_ERROR;
1091: }
1092:
1.1.1.10 root 1093: dlgrect.x = dlg[0].x * sdlgui_fontwidth;
1094: dlgrect.y = dlg[0].y * sdlgui_fontheight;
1095: dlgrect.w = dlg[0].w * sdlgui_fontwidth;
1096: dlgrect.h = dlg[0].h * sdlgui_fontheight;
1.1.1.5 root 1097:
1098: bgrect.x = bgrect.y = 0;
1099: bgrect.w = dlgrect.w;
1100: bgrect.h = dlgrect.h;
1101:
1102: /* Save background */
1103: pBgSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, dlgrect.w, dlgrect.h, pSdlGuiScrn->format->BitsPerPixel,
1104: pSdlGuiScrn->format->Rmask, pSdlGuiScrn->format->Gmask, pSdlGuiScrn->format->Bmask, pSdlGuiScrn->format->Amask);
1105: if (pSdlGuiScrn->format->palette != NULL)
1106: {
1107: SDL_SetColors(pBgSurface, pSdlGuiScrn->format->palette->colors, 0, pSdlGuiScrn->format->palette->ncolors-1);
1108: }
1109:
1110: if (pBgSurface != NULL)
1111: {
1112: SDL_BlitSurface(pSdlGuiScrn, &dlgrect, pBgSurface, &bgrect);
1113: }
1114: else
1115: {
1116: fprintf(stderr, "SDLGUI_DoDialog: CreateRGBSurface failed: %s\n", SDL_GetError());
1117: }
1118:
1.1.1.14! root 1119: /* focus default button if nothing else is focused */
! 1120: focused = SDLGui_SearchState(dlg, SG_FOCUSED);
! 1121: if (!focused)
! 1122: {
! 1123: int defocus = SDLGui_SearchFlags(dlg, SG_DEFAULT);
! 1124: if (defocus)
! 1125: {
! 1126: dlg[focused].state &= ~SG_FOCUSED;
! 1127: dlg[defocus].state |= SG_FOCUSED;
! 1128: focused = defocus;
! 1129: }
! 1130: }
! 1131: SDLGui_SetShortcuts(dlg);
! 1132:
1.1.1.5 root 1133: /* (Re-)draw the dialog */
1134: SDLGui_DrawDialog(dlg);
1135:
1136: /* Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */
1137: SDL_PumpEvents();
1138: b = SDL_GetMouseState(&i, &j);
1.1.1.10 root 1139:
1140: /* If current object is the scrollbar, and mouse is still down, we can scroll it */
1141: /* also if the mouse pointer has left the scrollbar */
1.1.1.12 root 1142: if (current_object >= 0 && dlg[current_object].type == SGSCROLLBAR) {
1.1.1.10 root 1143: if (b & SDL_BUTTON(1)) {
1144: obj = current_object;
1145: dlg[obj].state |= SG_MOUSEDOWN;
1146: oldbutton = obj;
1147: retbutton = obj;
1148: }
1149: else {
1150: obj = current_object;
1151: current_object = 0;
1.1.1.14! root 1152: dlg[obj].state &= ~SG_MOUSEDOWN;
1.1.1.5 root 1153: retbutton = obj;
1.1.1.10 root 1154: oldbutton = obj;
1.1.1.5 root 1155: }
1156: }
1.1.1.10 root 1157: else {
1158: obj = SDLGui_FindObj(dlg, i, j);
1159: current_object = obj;
1160: if (obj > 0 && (dlg[obj].flags&SG_TOUCHEXIT) )
1161: {
1162: oldbutton = obj;
1163: if (b & SDL_BUTTON(1))
1164: {
1165: dlg[obj].state |= SG_SELECTED;
1166: retbutton = obj;
1167: }
1168: }
1169: }
1170:
1.1.1.14! root 1171: if (SDL_NumJoysticks() > 0)
! 1172: joy = SDL_JoystickOpen(0);
! 1173:
! 1174: #if !WITH_SDL2
! 1175: /* Enable unicode translation to get shifted etc chars with SDL_PollEvent */
! 1176: nOldUnicodeMode = SDL_EnableUNICODE(true);
! 1177: #endif
1.1.1.5 root 1178:
1179: /* The main loop */
1180: while (retbutton == 0 && !bQuitProgram)
1181: {
1182: if (SDL_WaitEvent(&sdlEvent) == 1) /* Wait for events */
1.1.1.10 root 1183:
1.1.1.5 root 1184: switch (sdlEvent.type)
1185: {
1186: case SDL_QUIT:
1187: retbutton = SDLGUI_QUIT;
1188: break;
1189:
1190: case SDL_MOUSEBUTTONDOWN:
1191: if (sdlEvent.button.button != SDL_BUTTON_LEFT)
1192: {
1193: /* Not left mouse button -> unsupported event */
1194: if (pEventOut)
1195: retbutton = SDLGUI_UNKNOWNEVENT;
1196: break;
1197: }
1198: /* It was the left button: Find the object under the mouse cursor */
1199: obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y);
1200: if (obj>0)
1201: {
1202: if (dlg[obj].type==SGBUTTON)
1203: {
1204: dlg[obj].state |= SG_SELECTED;
1205: SDLGui_DrawButton(dlg, obj);
1.1.1.10 root 1206: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[obj].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[obj].y)*sdlgui_fontheight-2,
1207: dlg[obj].w*sdlgui_fontwidth+4, dlg[obj].h*sdlgui_fontheight+4);
1208: oldbutton=obj;
1209: }
1210: if (dlg[obj].type==SGSCROLLBAR)
1211: {
1212: dlg[obj].state |= SG_MOUSEDOWN;
1.1.1.5 root 1213: oldbutton=obj;
1214: }
1215: if ( dlg[obj].flags&SG_TOUCHEXIT )
1216: {
1217: dlg[obj].state |= SG_SELECTED;
1218: retbutton = obj;
1219: }
1220: }
1221: break;
1222:
1223: case SDL_MOUSEBUTTONUP:
1224: if (sdlEvent.button.button != SDL_BUTTON_LEFT)
1225: {
1226: /* Not left mouse button -> unsupported event */
1227: if (pEventOut)
1228: retbutton = SDLGUI_UNKNOWNEVENT;
1229: break;
1230: }
1231: /* It was the left button: Find the object under the mouse cursor */
1232: obj = SDLGui_FindObj(dlg, sdlEvent.button.x, sdlEvent.button.y);
1233: if (obj>0)
1234: {
1.1.1.14! root 1235: retbutton = SDLGui_HandleSelection(dlg, obj, oldbutton);
1.1.1.5 root 1236: }
1.1.1.10 root 1237: if (oldbutton > 0 && dlg[oldbutton].type == SGBUTTON)
1.1.1.5 root 1238: {
1239: dlg[oldbutton].state &= ~SG_SELECTED;
1240: SDLGui_DrawButton(dlg, oldbutton);
1.1.1.10 root 1241: SDL_UpdateRect(pSdlGuiScrn, (dlg[0].x+dlg[oldbutton].x)*sdlgui_fontwidth-2, (dlg[0].y+dlg[oldbutton].y)*sdlgui_fontheight-2,
1242: dlg[oldbutton].w*sdlgui_fontwidth+4, dlg[oldbutton].h*sdlgui_fontheight+4);
1.1.1.5 root 1243: oldbutton = 0;
1244: }
1.1.1.14! root 1245: break;
! 1246:
! 1247: case SDL_JOYAXISMOTION:
! 1248: value = sdlEvent.jaxis.value;
! 1249: if (value < -3200 || value > 3200)
1.1.1.5 root 1250: {
1.1.1.14! root 1251: if(sdlEvent.jaxis.axis == 0)
! 1252: {
! 1253: /* Left-right movement */
! 1254: if (value < 0)
! 1255: retbutton = SDLGui_HandleShortcut(dlg, SG_SHORTCUT_LEFT);
! 1256: else
! 1257: retbutton = SDLGui_HandleShortcut(dlg, SG_SHORTCUT_RIGHT);
! 1258: }
! 1259: else if(sdlEvent.jaxis.axis == 1)
! 1260: {
! 1261: /* Up-Down movement */
! 1262: if (value < 0)
! 1263: {
! 1264: SDLGui_RemoveFocus(dlg, focused);
! 1265: focused = SDLGui_FocusNext(dlg, focused, -1);
! 1266: }
! 1267: else
! 1268: {
! 1269: SDLGui_RemoveFocus(dlg, focused);
! 1270: focused = SDLGui_FocusNext(dlg, focused, +1);
! 1271: }
! 1272: }
1.1.1.5 root 1273: }
1274: break;
1275:
1.1.1.14! root 1276: case SDL_JOYBUTTONDOWN:
! 1277: retbutton = SDLGui_HandleSelection(dlg, focused, focused);
! 1278: break;
! 1279:
1.1.1.6 root 1280: case SDL_JOYBALLMOTION:
1281: case SDL_JOYHATMOTION:
1.1.1.5 root 1282: case SDL_MOUSEMOTION:
1283: break;
1284:
1285: case SDL_KEYDOWN: /* Key pressed */
1.1.1.14! root 1286: key = sdlEvent.key.keysym.sym;
! 1287: /* keyboard shortcuts are with modifiers */
! 1288: if (sdlEvent.key.keysym.mod & KMOD_LALT
! 1289: || sdlEvent.key.keysym.mod & KMOD_RALT)
1.1.1.5 root 1290: {
1.1.1.14! root 1291: if (key == SDLK_LEFT)
! 1292: retbutton = SDLGui_HandleShortcut(dlg, SG_SHORTCUT_LEFT);
! 1293: else if (key == SDLK_RIGHT)
! 1294: retbutton = SDLGui_HandleShortcut(dlg, SG_SHORTCUT_RIGHT);
! 1295: else if (key == SDLK_UP)
! 1296: retbutton = SDLGui_HandleShortcut(dlg, SG_SHORTCUT_UP);
! 1297: else if (key == SDLK_DOWN)
! 1298: retbutton = SDLGui_HandleShortcut(dlg, SG_SHORTCUT_DOWN);
! 1299: else
! 1300: {
! 1301: #if !WITH_SDL2
! 1302: /* unicode member is needed to handle shifted etc special chars */
! 1303: key = sdlEvent.key.keysym.unicode;
! 1304: #endif
! 1305: if (key >= 33 && key <= 126)
! 1306: retbutton = SDLGui_HandleShortcut(dlg, toupper(key));
! 1307: }
! 1308: if (!retbutton && pEventOut)
! 1309: retbutton = SDLGUI_UNKNOWNEVENT;
! 1310: break;
1.1.1.5 root 1311: }
1.1.1.14! root 1312: switch (key)
1.1.1.5 root 1313: {
1.1.1.14! root 1314: case SDLK_UP:
! 1315: case SDLK_LEFT:
! 1316: SDLGui_RemoveFocus(dlg, focused);
! 1317: focused = SDLGui_FocusNext(dlg, focused, -1);
! 1318: break;
! 1319: case SDLK_TAB:
! 1320: case SDLK_DOWN:
! 1321: case SDLK_RIGHT:
! 1322: SDLGui_RemoveFocus(dlg, focused);
! 1323: focused = SDLGui_FocusNext(dlg, focused, +1);
! 1324: break;
! 1325: case SDLK_HOME:
! 1326: SDLGui_RemoveFocus(dlg, focused);
! 1327: focused = SDLGui_FocusNext(dlg, 1, +1);
! 1328: break;
! 1329: case SDLK_END:
! 1330: SDLGui_RemoveFocus(dlg, focused);
! 1331: focused = SDLGui_FocusNext(dlg, 1, -1);
! 1332: break;
! 1333: case SDLK_SPACE:
! 1334: case SDLK_RETURN:
! 1335: case SDLK_KP_ENTER:
! 1336: retbutton = SDLGui_HandleSelection(dlg, focused, focused);
! 1337: break;
! 1338: case SDLK_ESCAPE:
! 1339: retbutton = SDLGui_SearchFlags(dlg, SG_CANCEL);
! 1340: break;
! 1341: default:
! 1342: if (pEventOut)
! 1343: retbutton = SDLGUI_UNKNOWNEVENT;
! 1344: break;
1.1.1.5 root 1345: }
1346: break;
1347:
1348: default:
1349: if (pEventOut)
1350: retbutton = SDLGUI_UNKNOWNEVENT;
1351: break;
1352: }
1353: }
1354:
1355: /* Restore background */
1356: if (pBgSurface)
1357: {
1358: SDL_BlitSurface(pBgSurface, &bgrect, pSdlGuiScrn, &dlgrect);
1359: SDL_FreeSurface(pBgSurface);
1360: }
1361:
1362: /* Copy event data of unsupported events if caller wants to have it */
1363: if (retbutton == SDLGUI_UNKNOWNEVENT && pEventOut)
1364: memcpy(pEventOut, &sdlEvent, sizeof(SDL_Event));
1.1.1.2 root 1365:
1.1.1.5 root 1366: if (retbutton == SDLGUI_QUIT)
1.1.1.8 root 1367: bQuitProgram = true;
1.1 root 1368:
1.1.1.14! root 1369: #if !WITH_SDL2
! 1370: SDL_EnableUNICODE(nOldUnicodeMode);
! 1371: #endif
! 1372: if (joy)
! 1373: SDL_JoystickClose(joy);
! 1374:
1.1.1.5 root 1375: return retbutton;
1.1 root 1376: }
1377:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.