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