Annotation of hatari/src/gui-sdl/sdlgui.c, revision 1.1.1.7

1.1       root        1: /*
                      2:   Hatari - sdlgui.c
                      3: 
                      4:   This file is distributed under the GNU Public License, version 2 or at
                      5:   your option any later version. Read the file gpl.txt for details.
                      6: 
                      7:   A tiny graphical user interface for Hatari.
                      8: */
1.1.1.7 ! root        9: const char SDLGui_rcsid[] = "Hatari $Id: sdlgui.c,v 1.20 2008-11-21 18:28:24 eerot Exp $";
1.1       root       10: 
                     11: #include <SDL.h>
                     12: #include <ctype.h>
                     13: #include <string.h>
                     14: 
                     15: #include "main.h"
                     16: #include "sdlgui.h"
                     17: 
                     18: #include "font5x8.h"
                     19: #include "font10x16.h"
                     20: 
                     21: 
1.1.1.2   root       22: static SDL_Surface *pSdlGuiScrn;            /* Pointer to the actual main SDL screen surface */
1.1       root       23: static SDL_Surface *pSmallFontGfx = NULL;   /* The small font graphics */
                     24: static SDL_Surface *pBigFontGfx = NULL;     /* The big font graphics */
1.1.1.2   root       25: static SDL_Surface *pFontGfx = NULL;        /* The actual font graphics */
1.1       root       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: */
1.1.1.4   root       34: static SDL_Surface *SDLGui_LoadXBM(int w, int h, const Uint8 *pXbmBits)
1.1       root       35: {
1.1.1.5   root       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:        }
1.1       root       69: 
1.1.1.5   root       70:        return bitmap;
1.1       root       71: }
                     72: 
                     73: 
                     74: /*-----------------------------------------------------------------------*/
                     75: /*
                     76:   Initialize the GUI.
                     77: */
                     78: int SDLGui_Init(void)
                     79: {
1.1.1.5   root       80:        SDL_Color blackWhiteColors[2] = {{255, 255, 255, 0}, {0, 0, 0, 0}};
1.1       root       81: 
1.1.1.6   root       82:        if (pSmallFontGfx && pBigFontGfx)
                     83:        {
                     84:                /* already initialized */
                     85:                return 0;
                     86:        }
                     87: 
1.1.1.5   root       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);
1.1       root      104: 
1.1.1.5   root      105:        return 0;
1.1       root      106: }
                    107: 
                    108: 
                    109: /*-----------------------------------------------------------------------*/
                    110: /*
                    111:   Uninitialize the GUI.
                    112: */
                    113: int SDLGui_UnInit(void)
                    114: {
1.1.1.5   root      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:        }
1.1       root      126: 
1.1.1.5   root      127:        return 0;
1.1       root      128: }
                    129: 
                    130: 
                    131: /*-----------------------------------------------------------------------*/
                    132: /*
1.1.1.2   root      133:   Inform the SDL-GUI about the actual SDL_Surface screen pointer and
                    134:   prepare the font to suit the actual resolution.
1.1       root      135: */
1.1.1.2   root      136: int SDLGui_SetScreen(SDL_Surface *pScrn)
1.1       root      137: {
1.1.1.5   root      138:        pSdlGuiScrn = pScrn;
1.1.1.2   root      139: 
1.1.1.5   root      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;
1.1       root      159: 
1.1.1.5   root      160:        return 0;
1.1       root      161: }
                    162: 
1.1.1.6   root      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: }
1.1       root      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: {
1.1.1.5   root      181:        dlg[0].x = (pSdlGuiScrn->w/fontwidth-dlg[0].w)/2;
                    182:        dlg[0].y = (pSdlGuiScrn->h/fontheight-dlg[0].h)/2;
1.1       root      183: }
                    184: 
                    185: 
                    186: /*-----------------------------------------------------------------------*/
                    187: /*
                    188:   Draw a text string.
                    189: */
1.1.1.6   root      190: void SDLGui_Text(int x, int y, const char *txt)
1.1       root      191: {
1.1.1.5   root      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:        }
1.1       root      209: }
                    210: 
                    211: 
                    212: /*-----------------------------------------------------------------------*/
                    213: /*
                    214:   Draw a dialog text object.
                    215: */
1.1.1.2   root      216: static void SDLGui_DrawText(const SGOBJ *tdlg, int objnum)
1.1       root      217: {
1.1.1.5   root      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);
1.1       root      222: }
                    223: 
                    224: 
                    225: /*-----------------------------------------------------------------------*/
                    226: /*
                    227:   Draw a edit field object.
                    228: */
1.1.1.2   root      229: static void SDLGui_DrawEditField(const SGOBJ *edlg, int objnum)
1.1       root      230: {
1.1.1.5   root      231:        int x, y;
                    232:        SDL_Rect rect;
1.1       root      233: 
1.1.1.5   root      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));
1.1       root      243: }
                    244: 
                    245: 
                    246: /*-----------------------------------------------------------------------*/
                    247: /*
                    248:   Draw a dialog box object.
                    249: */
1.1.1.2   root      250: static void SDLGui_DrawBox(const SGOBJ *bdlg, int objnum)
1.1       root      251: {
1.1.1.5   root      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);
1.1       root      319: }
                    320: 
                    321: 
                    322: /*-----------------------------------------------------------------------*/
                    323: /*
                    324:   Draw a normal button.
                    325: */
1.1.1.2   root      326: static void SDLGui_DrawButton(const SGOBJ *bdlg, int objnum)
1.1       root      327: {
1.1.1.5   root      328:        int x,y;
1.1       root      329: 
1.1.1.5   root      330:        SDLGui_DrawBox(bdlg, objnum);
1.1       root      331: 
1.1.1.5   root      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;
1.1       root      334: 
1.1.1.5   root      335:        if (bdlg[objnum].state & SG_SELECTED)
                    336:        {
                    337:                x+=1;
                    338:                y+=1;
                    339:        }
                    340:        SDLGui_Text(x, y, bdlg[objnum].txt);
1.1       root      341: }
                    342: 
                    343: 
                    344: /*-----------------------------------------------------------------------*/
                    345: /*
                    346:   Draw a dialog radio button object.
                    347: */
1.1.1.2   root      348: static void SDLGui_DrawRadioButton(const SGOBJ *rdlg, int objnum)
1.1       root      349: {
1.1.1.5   root      350:        char str[80];
                    351:        int x, y;
1.1       root      352: 
1.1.1.5   root      353:        x = (rdlg[0].x + rdlg[objnum].x) * fontwidth;
                    354:        y = (rdlg[0].y + rdlg[objnum].y) * fontheight;
1.1       root      355: 
1.1.1.5   root      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);
1.1       root      362: 
1.1.1.5   root      363:        SDLGui_Text(x, y, str);
1.1       root      364: }
                    365: 
                    366: 
                    367: /*-----------------------------------------------------------------------*/
                    368: /*
                    369:   Draw a dialog check box object.
                    370: */
1.1.1.2   root      371: static void SDLGui_DrawCheckBox(const SGOBJ *cdlg, int objnum)
1.1       root      372: {
1.1.1.5   root      373:        char str[80];
                    374:        int x, y;
1.1       root      375: 
1.1.1.5   root      376:        x = (cdlg[0].x + cdlg[objnum].x) * fontwidth;
                    377:        y = (cdlg[0].y + cdlg[objnum].y) * fontheight;
1.1       root      378: 
1.1.1.5   root      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);
1.1       root      385: 
1.1.1.5   root      386:        SDLGui_Text(x, y, str);
1.1       root      387: }
                    388: 
                    389: 
                    390: /*-----------------------------------------------------------------------*/
                    391: /*
                    392:   Draw a dialog popup button object.
                    393: */
1.1.1.2   root      394: static void SDLGui_DrawPopupButton(const SGOBJ *pdlg, int objnum)
1.1       root      395: {
1.1.1.5   root      396:        int x, y, w, h;
                    397:        const char *downstr = "\x02";
1.1       root      398: 
1.1.1.5   root      399:        SDLGui_DrawBox(pdlg, objnum);
1.1       root      400: 
1.1.1.5   root      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;
1.1       root      405: 
1.1.1.5   root      406:        SDLGui_Text(x, y, pdlg[objnum].txt);
                    407:        SDLGui_Text(x+w-fontwidth, y, downstr);
1.1       root      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: {
1.1.1.5   root      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);
1.1       root      531: }
                    532: 
                    533: 
                    534: /*-----------------------------------------------------------------------*/
                    535: /*
                    536:   Draw a whole dialog.
                    537: */
1.1.1.3   root      538: void SDLGui_DrawDialog(const SGOBJ *dlg)
1.1       root      539: {
1.1.1.5   root      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);
1.1       root      569: }
                    570: 
                    571: 
                    572: /*-----------------------------------------------------------------------*/
                    573: /*
                    574:   Search an object at a certain position.
                    575: */
1.1.1.2   root      576: static int SDLGui_FindObj(const SGOBJ *dlg, int fx, int fy)
1.1       root      577: {
1.1.1.5   root      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:        }
1.1       root      616: 
1.1.1.5   root      617:        return 0;
1.1       root      618: }
                    619: 
                    620: 
                    621: /*-----------------------------------------------------------------------*/
                    622: /*
                    623:   Show and process a dialog. Returns the button number that has been
1.1.1.2   root      624:   pressed or SDLGUI_UNKNOWNEVENT if an unsupported event occured (will be
                    625:   stored in parameter pEventOut).
1.1       root      626: */
1.1.1.2   root      627: int SDLGui_DoDialog(SGOBJ *dlg, SDL_Event *pEventOut)
1.1       root      628: {
1.1.1.5   root      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: 
1.1.1.6   root      814:                         case SDL_JOYAXISMOTION:
                    815:                         case SDL_JOYBALLMOTION:
                    816:                         case SDL_JOYHATMOTION:
1.1.1.5   root      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));
1.1.1.2   root      853: 
1.1.1.5   root      854:        if (retbutton == SDLGUI_QUIT)
                    855:                bQuitProgram = TRUE;
1.1       root      856: 
1.1.1.5   root      857:        return retbutton;
1.1       root      858: }
                    859: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.