Annotation of hatari/src/sdlgui.c, revision 1.1.1.2

1.1       root        1: /*
                      2:   Hatari
                      3: 
                      4:   A tiny graphical user interface for Hatari.
                      5: */
                      6: 
                      7: #include <SDL.h>
                      8: #include <sys/stat.h>
                      9: #include <unistd.h>
                     10: #include <dirent.h>
                     11: 
                     12: #include "main.h"
                     13: #include "screen.h"
                     14: #include "sdlgui.h"
                     15: #include "file.h"
                     16: 
                     17: 
                     18: #define SGRADIOBUTTON_NORMAL    12
                     19: #define SGRADIOBUTTON_SELECTED  13
                     20: #define SGCHECKBOX_NORMAL    14
                     21: #define SGCHECKBOX_SELECTED  15
                     22: #define SGARROWUP    1
                     23: #define SGARROWDOWN  2
                     24: #define SGFOLDER     5
                     25: 
                     26: 
                     27: 
1.1.1.2 ! root       28: static SDL_Surface *stdfontgfx = NULL;  /* The 'standard' font graphics */
        !            29: static SDL_Surface *fontgfx = NULL;     /* The actual font graphics */
        !            30: static int fontwidth, fontheight;       /* Height and width of the actual font */
1.1       root       31: 
                     32: 
                     33: 
                     34: /*-----------------------------------------------------------------------*/
                     35: /*
                     36:   Initialize the GUI.
                     37: */
                     38: int SDLGui_Init()
                     39: {
                     40:   char fontname[256];
                     41:   sprintf(fontname, "%s/font8.bmp", DATADIR);
                     42: 
                     43:   /* Load the font graphics: */
                     44:   stdfontgfx = SDL_LoadBMP(fontname);
                     45:   if( stdfontgfx==NULL )
                     46:   {
1.1.1.2 ! root       47:     fprintf(stderr, "Error: Can't load image %s: %s\n", fontname, SDL_GetError() );
1.1       root       48:     return -1;
                     49:   }
                     50: 
                     51:   return 0;
                     52: }
                     53: 
                     54: 
                     55: /*-----------------------------------------------------------------------*/
                     56: /*
                     57:   Uninitialize the GUI.
                     58: */
                     59: int SDLGui_UnInit()
                     60: {
                     61:   if(stdfontgfx)
1.1.1.2 ! root       62:   {
1.1       root       63:     SDL_FreeSurface(stdfontgfx);
1.1.1.2 ! root       64:     stdfontgfx = NULL;
        !            65:   }
1.1       root       66:   if(fontgfx)
1.1.1.2 ! root       67:   {
1.1       root       68:     SDL_FreeSurface(fontgfx);
1.1.1.2 ! root       69:     fontgfx = NULL;
        !            70:   }
1.1       root       71: 
                     72:   return 0;
                     73: }
                     74: 
                     75: 
                     76: /*-----------------------------------------------------------------------*/
                     77: /*
                     78:   Prepare the font to suit the actual resolution.
                     79: */
                     80: int SDLGui_PrepareFont()
                     81: {
1.1.1.2 ! root       82: /* FIXME: Freeing the old font gfx does sometimes crash with a SEGFAULT 
1.1       root       83:   if(fontgfx)
1.1.1.2 ! root       84:   {
1.1       root       85:     SDL_FreeSurface(fontgfx);
1.1.1.2 ! root       86:     fontgfx = NULL;
        !            87:   }
1.1       root       88: */
                     89: 
1.1.1.2 ! root       90:   if( stdfontgfx==NULL )
        !            91:   {
        !            92:     fprintf(stderr, "Error: The font has not been loaded!\n");
        !            93:     return -1;
        !            94:   }
        !            95: 
1.1       root       96:   /* Convert the font graphics to the actual screen format */
                     97:   fontgfx = SDL_DisplayFormat(stdfontgfx);
                     98:   if( fontgfx==NULL )
                     99:   {
                    100:     fprintf(stderr, "Could not convert font:\n %s\n", SDL_GetError() );
                    101:     return -1;
                    102:   }
                    103:   /* Set transparent pixel */
                    104:   SDL_SetColorKey(fontgfx, (SDL_SRCCOLORKEY|SDL_RLEACCEL), SDL_MapRGB(fontgfx->format,255,255,255));
                    105:   /* Get the font width and height: */
                    106:   fontwidth = fontgfx->w/16;
                    107:   fontheight = fontgfx->h/16;
                    108: 
                    109:   return 0;
                    110: }
                    111: 
                    112: 
                    113: /*-----------------------------------------------------------------------*/
                    114: /*
                    115:   Center a dialog so that it appears in the middle of the screen.
                    116:   Note: We only store the coordinates in the root box of the dialog,
                    117:   all other objects in the dialog are positioned relatively to this one.
                    118: */
                    119: void SDLGui_CenterDlg(SGOBJ *dlg)
                    120: {
                    121:   dlg[0].x = (sdlscrn->w/fontwidth-dlg[0].w)/2;
                    122:   dlg[0].y = (sdlscrn->h/fontheight-dlg[0].h)/2;
                    123: }
                    124: 
                    125: 
                    126: /*-----------------------------------------------------------------------*/
                    127: /*
                    128:   Draw a text string.
                    129: */
                    130: void SDLGui_Text(int x, int y, const char *txt)
                    131: {
                    132:   int i;
                    133:   char c;
                    134:   SDL_Rect sr, dr;
                    135:   
                    136:   for(i=0; txt[i]!=0; i++)
                    137:   {
                    138:     c = txt[i];
                    139:     sr.x=fontwidth*(c%16);  sr.y=fontheight*(c/16);
                    140:     sr.w=fontwidth;         sr.h=fontheight;
                    141:     dr.x=x+i*fontwidth;     dr.y=y;
                    142:     dr.w=fontwidth;         dr.h=fontheight;
                    143:     SDL_BlitSurface(fontgfx, &sr, sdlscrn, &dr);
                    144:   }
                    145: }
                    146: 
                    147: 
                    148: /*-----------------------------------------------------------------------*/
                    149: /*
                    150:   Draw a dialog text object.
                    151: */
                    152: void SDLGui_DrawText(SGOBJ *tdlg, int objnum)
                    153: {
                    154:   int x, y;
                    155:   x = (tdlg[0].x+tdlg[objnum].x)*fontwidth;
                    156:   y = (tdlg[0].y+tdlg[objnum].y)*fontheight;
                    157:   SDLGui_Text(x, y, tdlg[objnum].txt);
                    158: }
                    159: 
                    160: 
                    161: /*-----------------------------------------------------------------------*/
                    162: /*
                    163:   Draw a dialog box object.
                    164: */
                    165: void SDLGui_DrawBox(SGOBJ *bdlg, int objnum)
                    166: {
                    167:   SDL_Rect rect;
                    168:   int x, y, w, h;
                    169:   Uint32 grey = SDL_MapRGB(sdlscrn->format,192,192,192);
                    170:   Uint32 upleftc, downrightc;
                    171: 
                    172:   x = bdlg[objnum].x*fontwidth;
                    173:   y = bdlg[objnum].y*fontheight;
                    174:   if(objnum>0)                    /* Since the root object is a box, too, */
                    175:   {                               /* we have to look for it now here and only */
                    176:     x += bdlg[0].x*fontwidth;     /* add its absolute coordinates if we need to */
                    177:     y += bdlg[0].y*fontheight;
                    178:   }
                    179:   w = bdlg[objnum].w*fontwidth;
                    180:   h = bdlg[objnum].h*fontheight;
                    181: 
                    182:   if( bdlg[objnum].state&SG_SELECTED )
                    183:   {
                    184:     upleftc = SDL_MapRGB(sdlscrn->format,128,128,128);
                    185:     downrightc = SDL_MapRGB(sdlscrn->format,255,255,255);
                    186:   }
                    187:   else
                    188:   {
                    189:     upleftc = SDL_MapRGB(sdlscrn->format,255,255,255);
                    190:     downrightc = SDL_MapRGB(sdlscrn->format,128,128,128);
                    191:   }
                    192: 
                    193:   rect.x = x;  rect.y = y;
                    194:   rect.w = w;  rect.h = h;
                    195:   SDL_FillRect(sdlscrn, &rect, grey);
                    196: 
                    197:   rect.x = x;  rect.y = y-1;
                    198:   rect.w = w;  rect.h = 1;
                    199:   SDL_FillRect(sdlscrn, &rect, upleftc);
                    200: 
                    201:   rect.x = x-1;  rect.y = y;
                    202:   rect.w = 1;  rect.h = h;
                    203:   SDL_FillRect(sdlscrn, &rect, upleftc);
                    204: 
                    205:   rect.x = x;  rect.y = y+h;
                    206:   rect.w = w;  rect.h = 1;
                    207:   SDL_FillRect(sdlscrn, &rect, downrightc);
                    208: 
                    209:   rect.x = x+w;  rect.y = y;
                    210:   rect.w = 1;  rect.h = h;
                    211:   SDL_FillRect(sdlscrn, &rect, downrightc);
                    212: }
                    213: 
                    214: 
                    215: /*-----------------------------------------------------------------------*/
                    216: /*
                    217:   Draw a normal button.
                    218: */
                    219: void SDLGui_DrawButton(SGOBJ *bdlg, int objnum)
                    220: {
                    221:   int x,y;
                    222: 
                    223:   SDLGui_DrawBox(bdlg, objnum);
                    224: 
                    225:   x = (bdlg[0].x+bdlg[objnum].x+(bdlg[objnum].w-strlen(bdlg[objnum].txt))/2)*fontwidth;
                    226:   y = (bdlg[0].y+bdlg[objnum].y+(bdlg[objnum].h-1)/2)*fontheight;
                    227: 
                    228:   if( bdlg[objnum].state&SG_SELECTED )
                    229:   {
                    230:     x+=1;
                    231:     y+=1;
                    232:   }
                    233:   SDLGui_Text(x, y, bdlg[objnum].txt);
                    234: }
                    235: 
                    236: 
                    237: /*-----------------------------------------------------------------------*/
                    238: /*
                    239:   Draw a dialog radio button object.
                    240: */
                    241: void SDLGui_DrawRadioButton(SGOBJ *rdlg, int objnum)
                    242: {
                    243:   char str[80];
                    244:   int x, y;
                    245: 
                    246:   x = (rdlg[0].x+rdlg[objnum].x)*fontwidth;
                    247:   y = (rdlg[0].y+rdlg[objnum].y)*fontheight;
                    248: 
                    249:   if( rdlg[objnum].state&SG_SELECTED )
                    250:     str[0]=SGRADIOBUTTON_SELECTED;
                    251:    else
                    252:     str[0]=SGRADIOBUTTON_NORMAL;
                    253:   str[1]=' ';
                    254:   strcpy(&str[2], rdlg[objnum].txt);
                    255: 
                    256:   SDLGui_Text(x, y, str);
                    257: }
                    258: 
                    259: 
                    260: /*-----------------------------------------------------------------------*/
                    261: /*
                    262:   Draw a dialog check box object.
                    263: */
                    264: void SDLGui_DrawCheckBox(SGOBJ *cdlg, int objnum)
                    265: {
                    266:   char str[80];
                    267:   int x, y;
                    268: 
                    269:   x = (cdlg[0].x+cdlg[objnum].x)*fontwidth;
                    270:   y = (cdlg[0].y+cdlg[objnum].y)*fontheight;
                    271: 
                    272:   if( cdlg[objnum].state&SG_SELECTED )
                    273:     str[0]=SGCHECKBOX_SELECTED;
                    274:    else
                    275:     str[0]=SGCHECKBOX_NORMAL;
                    276:   str[1]=' ';
                    277:   strcpy(&str[2], cdlg[objnum].txt);
                    278: 
                    279:   SDLGui_Text(x, y, str);
                    280: }
                    281: 
                    282: 
                    283: /*-----------------------------------------------------------------------*/
                    284: /*
                    285:   Draw a dialog popup button object.
                    286: */
                    287: void SDLGui_DrawPopupButton(SGOBJ *pdlg, int objnum)
                    288: {
                    289:   int x, y, w, h;
                    290:   const char *downstr = "\x02";
                    291: 
                    292:   SDLGui_DrawBox(pdlg, objnum);
                    293: 
                    294:   x = (pdlg[0].x+pdlg[objnum].x)*fontwidth;
                    295:   y = (pdlg[0].y+pdlg[objnum].y)*fontheight;
                    296:   w = pdlg[objnum].w*fontwidth;
                    297:   h = pdlg[objnum].h*fontheight;
                    298: 
                    299:   SDLGui_Text(x, y, pdlg[objnum].txt);
                    300:   SDLGui_Text(x+w-fontwidth, y, downstr);
                    301: }
                    302: 
                    303: 
                    304: /*-----------------------------------------------------------------------*/
                    305: /*
                    306:   Draw a whole dialog.
                    307: */
                    308: void SDLGui_DrawDialog(SGOBJ *dlg)
                    309: {
                    310:   int i;
                    311:   for(i=0; dlg[i].type!=-1; i++ )
                    312:   {
                    313:     switch( dlg[i].type )
                    314:     {
                    315:       case SGBOX:
                    316:         SDLGui_DrawBox(dlg, i);
                    317:         break;
                    318:       case SGTEXT:
                    319:         SDLGui_DrawText(dlg, i);
                    320:         break;
                    321:       case SGBUTTON:
                    322:         SDLGui_DrawButton(dlg, i);
                    323:         break;
                    324:       case SGRADIOBUT:
                    325:         SDLGui_DrawRadioButton(dlg, i);
                    326:         break;
                    327:       case SGCHECKBOX:
                    328:         SDLGui_DrawCheckBox(dlg, i);
                    329:         break;
                    330:       case SGPOPUP:
                    331:         SDLGui_DrawPopupButton(dlg, i);
                    332:         break;
                    333:     }
                    334:   }
                    335:   SDL_UpdateRect(sdlscrn, 0,0,0,0);
                    336: }
                    337: 
                    338: 
                    339: /*-----------------------------------------------------------------------*/
                    340: /*
                    341:   Search an object at a certain position.
                    342: */
                    343: int SDLGui_FindObj(SGOBJ *dlg, int fx, int fy)
                    344: {
                    345:   int len, i;
                    346:   int ob = -1;
                    347:   int xpos, ypos;
                    348:   
                    349:   len = 0;
                    350:   while( dlg[len].type!=-1)   len++;
                    351: 
                    352:   xpos = fx/fontwidth;
                    353:   ypos = fy/fontheight;
                    354:   /* Now search for the object: */
                    355:   for(i=len; i>0; i--)
                    356:   {
                    357:     if(xpos>=dlg[0].x+dlg[i].x && ypos>=dlg[0].y+dlg[i].y
                    358:        && xpos<dlg[0].x+dlg[i].x+dlg[i].w && ypos<dlg[0].y+dlg[i].y+dlg[i].h)
                    359:     {
                    360:       ob = i;
                    361:       break;
                    362:     }
                    363:   }
                    364: 
                    365:   return ob;
                    366: }
                    367: 
                    368: 
                    369: /*-----------------------------------------------------------------------*/
                    370: /*
                    371:   Show and process a dialog. Returns the button number that has been
                    372:   pressed or -1 if something went wrong.
                    373: */
                    374: int SDLGui_DoDialog(SGOBJ *dlg)
                    375: {
                    376:   int obj=0;
                    377:   int oldbutton=0;
                    378:   int retbutton=0;
                    379:   int i, j, b;
                    380:   SDL_Event evnt;
                    381:   SDL_Rect rct;
                    382:   Uint32 grey;
                    383: 
                    384:   grey = SDL_MapRGB(sdlscrn->format,192,192,192);
                    385: 
                    386:   SDLGui_DrawDialog(dlg);
                    387: 
                    388:   /* Is the left mouse button still pressed? Yes -> Handle TOUCHEXIT objects here */
                    389:   SDL_PumpEvents();
                    390:   b = SDL_GetMouseState(&i, &j);
                    391:   obj = SDLGui_FindObj(dlg, i, j);
                    392:   if(obj>0 && (dlg[obj].flags&SG_TOUCHEXIT) )
                    393:   {
                    394:     oldbutton = obj;
                    395:     if( b&SDL_BUTTON(1) )
                    396:     {
                    397:       dlg[obj].state |= SG_SELECTED;
                    398:       return obj;
                    399:     }
                    400:   }
                    401: 
                    402:   /* The main loop */
                    403:   do
                    404:   {
                    405:     if( SDL_WaitEvent(&evnt)==1 )  /* Wait for events */
                    406:       switch(evnt.type)
                    407:       {
                    408:         case SDL_KEYDOWN:
                    409:           break;
                    410:         case SDL_QUIT:
                    411:           bQuitProgram = TRUE;
                    412:           break;
                    413:         case SDL_MOUSEBUTTONDOWN:
                    414:           obj = SDLGui_FindObj(dlg, evnt.button.x, evnt.button.y);
                    415:           if(obj>0)
                    416:           {
                    417:             if(dlg[obj].type==SGBUTTON)
                    418:             {
                    419:               dlg[obj].state |= SG_SELECTED;
                    420:               SDLGui_DrawButton(dlg, obj);
                    421:               SDL_UpdateRect(sdlscrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
                    422:                              dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
                    423:               oldbutton=obj;
                    424:             }
                    425:             if( dlg[obj].flags&SG_TOUCHEXIT )
                    426:             {
                    427:               dlg[obj].state |= SG_SELECTED;
                    428:               retbutton = obj;
                    429:             }
                    430:           }
                    431:           break;
                    432:         case SDL_MOUSEBUTTONUP:
                    433:           obj = SDLGui_FindObj(dlg, evnt.button.x, evnt.button.y);
                    434:           if(obj>0)
                    435:           {
                    436:             switch(dlg[obj].type)
                    437:             {
                    438:               case SGBUTTON:
                    439:                 if(oldbutton==obj)
                    440:                   retbutton=obj;
                    441:                 break;
                    442:               case SGRADIOBUT:
                    443:                 for(i=obj-1; i>0 && dlg[i].type==SGRADIOBUT; i--)
                    444:                 {
                    445:                   dlg[i].state &= ~SG_SELECTED;  /* Deselect all radio buttons in this group */
                    446:                   rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
                    447:                   rct.y = (dlg[0].y+dlg[i].y)*fontheight;
                    448:                   rct.w = fontwidth;  rct.h = fontheight;
                    449:                   SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
                    450:                   SDLGui_DrawRadioButton(dlg, i);
                    451:                   SDL_UpdateRects(sdlscrn, 1, &rct);
                    452:                 }
                    453:                 for(i=obj+1; dlg[i].type==SGRADIOBUT; i++)
                    454:                 {
                    455:                   dlg[i].state &= ~SG_SELECTED;  /* Deselect all radio buttons in this group */
                    456:                   rct.x = (dlg[0].x+dlg[i].x)*fontwidth;
                    457:                   rct.y = (dlg[0].y+dlg[i].y)*fontheight;
                    458:                   rct.w = fontwidth;  rct.h = fontheight;
                    459:                   SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
                    460:                   SDLGui_DrawRadioButton(dlg, i);
                    461:                   SDL_UpdateRects(sdlscrn, 1, &rct);
                    462:                 }
                    463:                 dlg[obj].state |= SG_SELECTED;  /* Select this radio button */
                    464:                 rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
                    465:                 rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
                    466:                 rct.w = fontwidth;  rct.h = fontheight;
                    467:                 SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
                    468:                 SDLGui_DrawRadioButton(dlg, obj);
                    469:                 SDL_UpdateRects(sdlscrn, 1, &rct);
                    470:                 break;
                    471:               case SGCHECKBOX:
                    472:                 dlg[obj].state ^= SG_SELECTED;
                    473:                 rct.x = (dlg[0].x+dlg[obj].x)*fontwidth;
                    474:                 rct.y = (dlg[0].y+dlg[obj].y)*fontheight;
                    475:                 rct.w = fontwidth;  rct.h = fontheight;
                    476:                 SDL_FillRect(sdlscrn, &rct, grey); /* Clear old */
                    477:                 SDLGui_DrawCheckBox(dlg, obj);
                    478:                 SDL_UpdateRects(sdlscrn, 1, &rct);
                    479:                 break;
                    480:               case SGPOPUP:
                    481:                 dlg[obj].state |= SG_SELECTED;
                    482:                 SDLGui_DrawPopupButton(dlg, obj);
                    483:                 SDL_UpdateRect(sdlscrn, (dlg[0].x+dlg[obj].x)*fontwidth-2, (dlg[0].y+dlg[obj].y)*fontheight-2,
                    484:                            dlg[obj].w*fontwidth+4, dlg[obj].h*fontheight+4);
                    485:                 retbutton=obj;
                    486:                 break;
                    487:             }
                    488:           }
                    489:           if(oldbutton>0)
                    490:           {
                    491:             dlg[oldbutton].state &= ~SG_SELECTED;
                    492:             SDLGui_DrawButton(dlg, oldbutton);
                    493:             SDL_UpdateRect(sdlscrn, (dlg[0].x+dlg[oldbutton].x)*fontwidth-2, (dlg[0].y+dlg[oldbutton].y)*fontheight-2,
                    494:                            dlg[oldbutton].w*fontwidth+4, dlg[oldbutton].h*fontheight+4);
                    495:             oldbutton = 0;
                    496:           }
                    497:           if( dlg[obj].flags&SG_EXIT )
                    498:           {
                    499:             retbutton = obj;
                    500:           }
                    501:           break;
                    502:       }
                    503:   }
                    504:   while(retbutton==0 && !bQuitProgram);
                    505: 
                    506:   if(bQuitProgram) 
                    507:     retbutton=-1;
                    508: 
                    509:   return retbutton;
                    510: }
                    511: 
                    512: 
                    513: /*-----------------------------------------------------------------------*/
                    514: /*
                    515:   Show and process a file select dialog.
                    516:   Returns TRUE if the use selected "okay", FALSE if "cancel".
                    517: */
                    518: #define SGFSDLG_UPDIR     6
                    519: #define SGFSDLG_ROOTDIR   7
                    520: #define SGFSDLG_ENTRY1    10
                    521: #define SGFSDLG_ENTRY16   25
                    522: #define SGFSDLG_UP        26
                    523: #define SGFSDLG_DOWN      27
                    524: #define SGFSDLG_OKAY      28
                    525: #define SGFSDLG_CANCEL    29
                    526: int SDLGui_FileSelect(char *path_and_name)
                    527: {
                    528:   int i;
                    529:   int entries = 0;                             /* How many files are in the actual directory? */
                    530:   int ypos = 0;
                    531:   char dlgfilenames[16][36];
                    532:   struct dirent **files = NULL;
                    533:   char path[MAX_FILENAME_LENGTH], fname[128];  /* The actual file and path names */
                    534:   char dlgpath[39], dlgfname[33];              /* File and path name in the dialog */
                    535:   BOOL reloaddir = TRUE;                       /* Do we have to reload the directory file list? */
                    536:   BOOL refreshentries = TRUE;                  /* Do we have to update the file names in the dialog? */
                    537:   int retbut;
                    538:   int oldcursorstate;
                    539:   int selection = -1;                          /* The actual selection, -1 if none selected */
                    540: 
                    541:   SGOBJ fsdlg[] =
                    542:   {
                    543:     { SGBOX, 0, 0, 0,0, 40,25, NULL },
                    544:     { SGTEXT, 0, 0, 13,1, 13,1, "Choose a file" },
                    545:     { SGTEXT, 0, 0, 1,2, 7,1, "Folder:" },
                    546:     { SGTEXT, 0, 0, 1,3, 38,1, dlgpath },
                    547:     { SGTEXT, 0, 0, 1,4, 6,1, "File:" },
                    548:     { SGTEXT, 0, 0, 7,4, 31,1, dlgfname },
                    549:     { SGBUTTON, 0, 0, 31,1, 4,1, ".." },
                    550:     { SGBUTTON, 0, 0, 36,1, 3,1, "/" },
                    551:     { SGBOX, 0, 0, 1,6, 38,16, NULL },
                    552:     { SGBOX, 0, 0, 38,7, 1,14, NULL },
                    553:     { SGTEXT, SG_EXIT, 0, 2,6, 35,1, dlgfilenames[0] },
                    554:     { SGTEXT, SG_EXIT, 0, 2,7, 35,1, dlgfilenames[1] },
                    555:     { SGTEXT, SG_EXIT, 0, 2,8, 35,1, dlgfilenames[2] },
                    556:     { SGTEXT, SG_EXIT, 0, 2,9, 35,1, dlgfilenames[3] },
                    557:     { SGTEXT, SG_EXIT, 0, 2,10, 35,1, dlgfilenames[4] },
                    558:     { SGTEXT, SG_EXIT, 0, 2,11, 35,1, dlgfilenames[5] },
                    559:     { SGTEXT, SG_EXIT, 0, 2,12, 35,1, dlgfilenames[6] },
                    560:     { SGTEXT, SG_EXIT, 0, 2,13, 35,1, dlgfilenames[7] },
                    561:     { SGTEXT, SG_EXIT, 0, 2,14, 35,1, dlgfilenames[8] },
                    562:     { SGTEXT, SG_EXIT, 0, 2,15, 35,1, dlgfilenames[9] },
                    563:     { SGTEXT, SG_EXIT, 0, 2,16, 35,1, dlgfilenames[10] },
                    564:     { SGTEXT, SG_EXIT, 0, 2,17, 35,1, dlgfilenames[11] },
                    565:     { SGTEXT, SG_EXIT, 0, 2,18, 35,1, dlgfilenames[12] },
                    566:     { SGTEXT, SG_EXIT, 0, 2,19, 35,1, dlgfilenames[13] },
                    567:     { SGTEXT, SG_EXIT, 0, 2,20, 35,1, dlgfilenames[14] },
                    568:     { SGTEXT, SG_EXIT, 0, 2,21, 35,1, dlgfilenames[15] },
                    569:     { SGBUTTON, SG_TOUCHEXIT, 0, 38,6, 1,1, "\x01" },          /* Arrow up */
                    570:     { SGBUTTON, SG_TOUCHEXIT, 0, 38,21, 1,1, "\x02" },         /* Arrow down */
                    571:     { SGBUTTON, 0, 0, 10,23, 8,1, "Okay" },
                    572:     { SGBUTTON, 0, 0, 24,23, 8,1, "Cancel" },
                    573:     { -1, 0, 0, 0,0, 0,0, NULL }
                    574:   };
                    575: 
                    576:   SDLGui_CenterDlg(fsdlg);
                    577: 
                    578:   /* Prepare the path and filename variables */
                    579:   File_splitpath(path_and_name, path, fname, NULL);
                    580:   File_ShrinkName(dlgpath, path, 38);
                    581:   File_ShrinkName(dlgfname, fname, 32);
                    582: 
                    583:   /* Save old mouse cursor state and enable cursor anyway */
                    584:   oldcursorstate = SDL_ShowCursor(SDL_QUERY);
                    585:   if( oldcursorstate==SDL_DISABLE )
                    586:     SDL_ShowCursor(SDL_ENABLE);
                    587: 
                    588:   do
                    589:   {
                    590:     if( reloaddir )
                    591:     {
                    592:       if( strlen(path)>=MAX_FILENAME_LENGTH )
                    593:       {
                    594:         fprintf(stderr, "SDLGui_FileSelect: Path name too long!\n");
                    595:         return FALSE;
                    596:       }
                    597: 
                    598:       /* Free old allocated memory: */
                    599:       if( files!=NULL )
                    600:       {
                    601:         for(i=0; i<entries; i++)
                    602:         {
                    603:           free(files[i]);
                    604:         }
                    605:         free(files);
                    606:         files = NULL;
                    607:       }
                    608: 
                    609:       /* Load directory entries: */
                    610:       entries = scandir(path, &files, 0, alphasort);
                    611:       if(entries<0)
                    612:       {
                    613:         fprintf(stderr, "SDLGui_FileSelect: Path not found.\n");
                    614:         return FALSE;
                    615:       }
                    616:       reloaddir = FALSE;
                    617:       refreshentries = TRUE;
                    618:     }
                    619: 
                    620:     if( refreshentries )
                    621:     {
                    622:       /* Copy entries to dialog: */
                    623:       for(i=0; i<16; i++)
                    624:       {
                    625:         if( i+ypos<entries )
                    626:         {
                    627:           char tempstr[MAX_FILENAME_LENGTH];
                    628:           struct stat filestat;
                    629:           /* Prepare entries: */
                    630:           strcpy(tempstr, "  ");
                    631:           strcat(tempstr, files[i+ypos]->d_name);
                    632:           File_ShrinkName(dlgfilenames[i], tempstr, 35);
                    633:           /* Mark folders: */
                    634:           strcpy(tempstr, path);
                    635:           strcat(tempstr, files[i+ypos]->d_name);
                    636:           if( stat(tempstr, &filestat)==0 && S_ISDIR(filestat.st_mode) )
                    637:             dlgfilenames[i][0] = SGFOLDER;    /* Mark folders */
                    638:         }
                    639:         else
                    640:           dlgfilenames[i][0] = 0;  /* Clear entry */
                    641:       }
                    642:       refreshentries = FALSE;
                    643:     }
                    644: 
                    645:     /* Show dialog: */
                    646:     retbut = SDLGui_DoDialog(fsdlg);
                    647: 
                    648:     /* Has the user clicked on a file or folder? */
                    649:     if( retbut>=SGFSDLG_ENTRY1 && retbut<=SGFSDLG_ENTRY16 && retbut-SGFSDLG_ENTRY1+ypos<entries)
                    650:     {
                    651:       char tempstr[MAX_FILENAME_LENGTH];
                    652:       struct stat filestat;
                    653: 
                    654:       strcpy(tempstr, path);
                    655:       strcat(tempstr, files[retbut-SGFSDLG_ENTRY1+ypos]->d_name);
                    656:       if( stat(tempstr, &filestat)==0 && S_ISDIR(filestat.st_mode) )
                    657:       {
                    658:         /* Set the new directory */
                    659:         strcpy(path, tempstr);
                    660:         if( strlen(path)>=3 )
                    661:         {
                    662:           if(path[strlen(path)-2]=='/' && path[strlen(path)-1]=='.')
                    663:             path[strlen(path)-2] = 0;  /* Strip a single dot at the end of the path name */
                    664:           if(path[strlen(path)-3]=='/' && path[strlen(path)-2]=='.' && path[strlen(path)-1]=='.')
                    665:           {
                    666:             /* Handle the ".." folder */
                    667:             char *ptr;
                    668:             if( strlen(path)==3 )
                    669:               path[1] = 0;
                    670:             else
                    671:             {
                    672:               path[strlen(path)-3] = 0;
                    673:               ptr = strrchr(path, '/');
                    674:               if(ptr)  *(ptr+1) = 0;
                    675:             }
                    676:           }
                    677:         }
                    678:         File_AddSlashToEndFileName(path);
                    679:         reloaddir = TRUE;
                    680:         /* Copy the path name to the dialog */
                    681:         File_ShrinkName(dlgpath, path, 38);
                    682:         selection = -1;                /* Remove old selection */
                    683:         fname[0] = 0;
                    684:         dlgfname[0] = 0;
                    685:         ypos = 0;
                    686:       }
                    687:       else
                    688:       {
                    689:         /* Select a file */
                    690:         selection = retbut-SGFSDLG_ENTRY1+ypos;
                    691:         strcpy(fname, files[selection]->d_name);
                    692:         File_ShrinkName(dlgfname, fname, 32);
                    693:       }
                    694:     }
                    695:     else    /* Has the user clicked on another button? */
                    696:     {
                    697:       switch(retbut)
                    698:       {
                    699:         case SGFSDLG_UPDIR:                 /* Change path to parent directory */
                    700:           if( strlen(path)>2 )
                    701:           {
                    702:             char *ptr;
                    703:             File_CleanFileName(path);
                    704:             ptr = strrchr(path, '/');
                    705:             if(ptr)  *(ptr+1) = 0;
                    706:             File_AddSlashToEndFileName(path);
                    707:             reloaddir = TRUE;
                    708:             File_ShrinkName(dlgpath, path, 38);  /* Copy the path name to the dialog */
                    709:             selection = -1;                 /* Remove old selection */
                    710:             fname[0] = 0;
                    711:             dlgfname[0] = 0;
                    712:             ypos = 0;
                    713:           }
                    714:           break;
                    715:         case SGFSDLG_ROOTDIR:               /* Change to root directory */
                    716:           strcpy(path, "/");
                    717:           reloaddir = TRUE;
                    718:           strcpy(dlgpath, path);
                    719:           selection = -1;                   /* Remove old selection */
                    720:           fname[0] = 0;
                    721:           dlgfname[0] = 0;
                    722:           ypos = 0;
                    723:           break;
                    724:         case SGFSDLG_UP:                    /* Scroll up */
                    725:           if( ypos>0 )
                    726:           {
                    727:             --ypos;
                    728:             refreshentries = TRUE;
                    729:           }
                    730:           SDL_Delay(20);
                    731:           break;
                    732:         case SGFSDLG_DOWN:                  /* Scroll down */
                    733:           if( ypos+17<=entries )
                    734:           {
                    735:             ++ypos;
                    736:             refreshentries = TRUE;
                    737:           }
                    738:           SDL_Delay(20);
                    739:           break;
                    740:       }
                    741:     }
                    742: 
                    743:   }
                    744:   while(retbut!=SGFSDLG_OKAY && retbut!=SGFSDLG_CANCEL && !bQuitProgram);
                    745: 
                    746:   if( oldcursorstate==SDL_DISABLE )
                    747:     SDL_ShowCursor(SDL_DISABLE);
                    748: 
                    749:   File_makepath(path_and_name, path, fname, NULL);
                    750: 
                    751:   /* Free old allocated memory: */
                    752:   if( files!=NULL )
                    753:   {
                    754:     for(i=0; i<entries; i++)
                    755:     {
                    756:       free(files[i]);
                    757:     }
                    758:     free(files);
                    759:     files = NULL;
                    760:   }
                    761: 
                    762:   return( retbut==SGFSDLG_OKAY );
                    763: }
                    764: 

unix.superglobalmegacorp.com

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