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