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

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

unix.superglobalmegacorp.com

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