Annotation of previous/src/statusbar.c, revision 1.1.1.4

1.1       root        1: /*
                      2:   Hatari - statusbar.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:   Code to draw statusbar area, floppy leds etc.
                      8: 
                      9:   Use like this:
                     10:   - Before screen surface is (re-)created Statusbar_SetHeight()
                     11:     has to be called with the new screen height. Add the returned
                     12:     value to screen height (zero means no statusbar).  After this,
                     13:     Statusbar_GetHeight() can be used to retrieve the statusbar size
                     14:   - After screen surface is (re-)created, call Statusbar_Init()
                     15:     to re-initialize / re-draw the statusbar
                     16:   - Call Statusbar_SetFloppyLed() to set floppy drive led ON/OFF,
                     17:     or call Statusbar_EnableHDLed() to enabled HD led for a while
                     18:   - Whenever screen is redrawn, call Statusbar_Update() to draw the
                     19:     updated information to the statusbar (outside of screen locking)
                     20:   - If screen redraws may be partial, Statusbar_OverlayRestore()
                     21:     needs to be called before locking the screen for drawing and
                     22:     Statusbar_OverlayBackup() needs to be called after screen unlocking,
                     23:     but before calling Statusbar_Update().  These are needed for
                     24:     hiding the overlay drive led when drive leds are turned OFF.
                     25:   - If other information shown by Statusbar (TOS version etc) changes,
                     26:     call Statusbar_UpdateInfo()
                     27: 
                     28:   TODO:
                     29:   - re-calculate colors on each update to make sure they're
                     30:     correct in Falcon & TT 8-bit palette modes?
                     31:   - call Statusbar_AddMessage() from log.c?
                     32: */
                     33: const char Statusbar_fileid[] = "Hatari statusbar.c : " __DATE__ " " __TIME__;
                     34: 
                     35: #include <assert.h>
                     36: #include "main.h"
                     37: #include "configuration.h"
                     38: #include "screenSnapShot.h"
                     39: #include "sdlgui.h"
                     40: #include "statusbar.h"
1.1.1.2   root       41: #include "screen.h"
1.1       root       42: #include "video.h"
1.1.1.4 ! root       43: #include "dimension.h"
1.1       root       44: 
                     45: #define DEBUG 0
                     46: #if DEBUG
                     47: #define DEBUGPRINT(x) printf x
                     48: #else
                     49: #define DEBUGPRINT(x)
                     50: #endif
                     51: 
                     52: /* whether drive leds should be ON and their previous shown state */
                     53: static struct {
                     54:        bool state;
                     55:        bool oldstate;
                     56:        Uint32 expire;  /* when to disable led, valid only if >0 && state=TRUE */
                     57:        int offset;     /* led x-pos on screen */
1.1.1.4 ! root       58: } Led[NUM_DEVICE_LEDS];
1.1       root       59: 
                     60: /* drive leds size & y-pos */
                     61: static SDL_Rect LedRect;
                     62: 
                     63: /* overlay led size & pos */
                     64: static SDL_Rect OverlayLedRect;
                     65: 
                     66: /* screen contents left under overlay led */
                     67: static SDL_Surface *OverlayUnderside;
                     68: 
                     69: static enum {
                     70:        OVERLAY_NONE,
                     71:        OVERLAY_DRAWN,
                     72:        OVERLAY_RESTORED
                     73: } bOverlayState;
                     74: 
1.1.1.4 ! root       75: static SDL_Rect SystemLedRect;
        !            76: static bool bOldSystemLed;
        !            77: 
        !            78: static SDL_Rect DspLedRect;
        !            79: static bool bOldDspLed;
        !            80: 
        !            81: #if ENABLE_DIMENSION
        !            82: static SDL_Rect NdLedRect;
        !            83: static int nOldNdLed;
        !            84: #endif
1.1       root       85: 
                     86: /* led colors */
1.1.1.4 ! root       87: static Uint32 LedColorOn, LedColorOff, SysColorOn, SysColorOff, DspColorOn, DspColorOff;
        !            88: #if ENABLE_DIMENSION
        !            89: static Uint32 NdColorOn, NdColorCS8, NdColorOff;
        !            90: #endif
1.1       root       91: static Uint32 GrayBg, LedColorBg;
                     92: 
                     93: 
1.1.1.4 ! root       94: #define MAX_MESSAGE_LEN 66 /* changed for Previous, was 50 */
1.1       root       95: typedef struct msg_item {
                     96:        struct msg_item *next;
                     97:        char msg[MAX_MESSAGE_LEN+1];
                     98:        Uint32 timeout; /* msecs, zero=no timeout */
                     99:        Uint32 expire;  /* when to expire message */
                    100:        bool shown;
                    101: } msg_item_t;
                    102: 
                    103: static msg_item_t DefaultMessage;
                    104: static msg_item_t *MessageList = &DefaultMessage;
                    105: static SDL_Rect MessageRect;
1.1.1.4 ! root      106: #if 0
1.1       root      107: /* rect for both frame skip value and fast forward indicator */
                    108: static SDL_Rect FrameSkipsRect;
                    109: static int nOldFrameSkips;
                    110: static int bOldFastForward;
1.1.1.4 ! root      111: #endif
1.1       root      112: 
                    113: /* screen height above statusbar and height of statusbar below screen */
                    114: static int ScreenHeight;
                    115: static int StatusbarHeight;
                    116: 
                    117: 
                    118: /*-----------------------------------------------------------------------*/
                    119: /**
                    120:  * Return statusbar height for given width and height
                    121:  */
                    122: int Statusbar_GetHeightForSize(int width, int height)
                    123: {
                    124:        if (ConfigureParams.Screen.bShowStatusbar) {
                    125:                /* Should check the same thing as SDLGui_SetScreen()
                    126:                 * does to decide the font size.
                    127:                 */
                    128:                if (width >= 640 && height >= (400-24)) {
                    129:                        return 24;
                    130:                } else {
                    131:                        return 12;
                    132:                }
                    133:        }
                    134:        return 0;
                    135: }
                    136: 
                    137: /*-----------------------------------------------------------------------*/
                    138: /**
                    139:  * Set screen height used for statusbar height calculation.
                    140:  *
                    141:  * Return height of statusbar that should be added to the screen
                    142:  * height when screen is (re-)created, or zero if statusbar will
                    143:  * not be shown
                    144:  */
                    145: int Statusbar_SetHeight(int width, int height)
                    146: {
                    147:        ScreenHeight = height;
                    148:        StatusbarHeight = Statusbar_GetHeightForSize(width, height);
                    149:        return StatusbarHeight;
                    150: }
                    151: 
                    152: /*-----------------------------------------------------------------------*/
                    153: /**
                    154:  * Return height of statusbar set with Statusbar_SetHeight()
                    155:  */
                    156: int Statusbar_GetHeight(void)
                    157: {
                    158:        return StatusbarHeight;
                    159: }
                    160: 
                    161: 
                    162: /*-----------------------------------------------------------------------*/
                    163: /**
1.1.1.4 ! root      164:  * Enable device led, it will be automatically disabled after a while.
1.1       root      165:  */
1.1.1.4 ! root      166: void Statusbar_BlinkLed(drive_index_t drive)
1.1       root      167: {
                    168:        /* leds are shown for 1/2 sec after enabling */
1.1.1.4 ! root      169:        Led[drive].expire = SDL_GetTicks() + 1000/2;
        !           170:        Led[drive].state = true;
1.1       root      171: }
                    172: 
1.1.1.4 ! root      173: 
1.1       root      174: /*-----------------------------------------------------------------------*/
                    175: /**
1.1.1.4 ! root      176:  * Set system, dsp and nextdimension led state, anything enabling led with 
        !           177:  * this needs also to take care of disabling it.
1.1       root      178:  */
1.1.1.4 ! root      179: void Statusbar_SetSystemLed(bool state)
1.1       root      180: {
1.1.1.4 ! root      181:        bOldSystemLed = state;
1.1       root      182: }
                    183: 
1.1.1.4 ! root      184: void Statusbar_SetDspLed(bool state)
1.1.1.3   root      185: {
1.1.1.4 ! root      186:        bOldDspLed = state;
1.1.1.3   root      187: }
                    188: 
1.1.1.4 ! root      189: #if ENABLE_DIMENSION
        !           190: void Statusbar_SetNdLed(int state)
        !           191: {
        !           192:     nOldNdLed = state;
        !           193: }
        !           194: #endif
1.1       root      195: 
                    196: /*-----------------------------------------------------------------------*/
                    197: /**
                    198:  * Set overlay led size/pos on given screen to internal Rect
                    199:  * and free previous resources.
                    200:  */
                    201: static void Statusbar_OverlayInit(const SDL_Surface *surf)
                    202: {
                    203:        int h;
                    204:        /* led size/pos needs to be re-calculated in case screen changed */
                    205:        h = surf->h / 50;
                    206:        OverlayLedRect.w = 2*h;
                    207:        OverlayLedRect.h = h;
                    208:        OverlayLedRect.x = surf->w - 5*h/2;
                    209:        OverlayLedRect.y = h/2;
                    210:        /* free previous restore surface if it's incompatible */
                    211:        if (OverlayUnderside &&
                    212:            OverlayUnderside->w == OverlayLedRect.w &&
                    213:            OverlayUnderside->h == OverlayLedRect.h &&
                    214:            OverlayUnderside->format->BitsPerPixel == surf->format->BitsPerPixel) {
                    215:                SDL_FreeSurface(OverlayUnderside);
                    216:                OverlayUnderside = NULL;
                    217:        }
                    218:        bOverlayState = OVERLAY_NONE;
                    219: }
                    220: 
                    221: /*-----------------------------------------------------------------------*/
                    222: /**
                    223:  * (re-)initialize statusbar internal variables for given screen surface
                    224:  * (sizes&colors may need to be re-calculated for the new SDL surface)
                    225:  * and draw the statusbar background.
                    226:  */
                    227: void Statusbar_Init(SDL_Surface *surf)
                    228: {
                    229:        msg_item_t *item;
                    230:        SDL_Rect ledbox, sbarbox;
                    231:        int i, fontw, fonth, offset;
1.1.1.4 ! root      232:        const char *text[NUM_DEVICE_LEDS] = { "EN:", "MO:", "SD:", "FD:" };
1.1       root      233: 
                    234:        assert(surf);
                    235: 
                    236:        /* dark green and light green for leds themselves */
                    237:        LedColorOff = SDL_MapRGB(surf->format, 0x00, 0x40, 0x00);
                    238:        LedColorOn  = SDL_MapRGB(surf->format, 0x00, 0xe0, 0x00);
                    239:        LedColorBg  = SDL_MapRGB(surf->format, 0x00, 0x00, 0x00);
1.1.1.4 ! root      240:        SysColorOff = SDL_MapRGB(surf->format, 0x40, 0x00, 0x00);
        !           241:        SysColorOn  = SDL_MapRGB(surf->format, 0xe0, 0x00, 0x00);
        !           242:        DspColorOff = SDL_MapRGB(surf->format, 0x00, 0x00, 0x40);
        !           243:        DspColorOn  = SDL_MapRGB(surf->format, 0x00, 0x00, 0xe0);
        !           244: #if ENABLE_DIMENSION
        !           245:     NdColorOff  = SDL_MapRGB(surf->format, 0x00, 0x00, 0x40);
        !           246:     NdColorCS8  = SDL_MapRGB(surf->format, 0xe0, 0x00, 0x00);
        !           247:     NdColorOn   = SDL_MapRGB(surf->format, 0x00, 0x00, 0xe0);
        !           248: #endif
        !           249:        GrayBg      = SDL_MapRGB(surf->format, 0xb5, 0xb7, 0xaa);
1.1       root      250: 
                    251:        /* disable leds */
1.1.1.4 ! root      252:        for (i = 0; i < NUM_DEVICE_LEDS; i++) {
1.1       root      253:                Led[i].state = Led[i].oldstate = false;
                    254:                Led[i].expire = 0;
                    255:        }
                    256:        Statusbar_OverlayInit(surf);
                    257:        
                    258:        /* disable statusbar if it doesn't fit to video mode */
                    259:        if (surf->h < ScreenHeight + StatusbarHeight) {
                    260:                StatusbarHeight = 0;
                    261:        }
                    262:        if (!StatusbarHeight) {
                    263:                return;
                    264:        }
                    265: 
                    266:        /* prepare fonts */
                    267:        SDLGui_Init();
                    268:        SDLGui_SetScreen(surf);
                    269:        SDLGui_GetFontSize(&fontw, &fonth);
                    270: 
                    271:        /* video mode didn't match, need to recalculate sizes */
                    272:        if (surf->h > ScreenHeight + StatusbarHeight) {
                    273:                StatusbarHeight = fonth + 2;
                    274:                /* actually statusbar vertical offset */
                    275:                ScreenHeight = surf->h - StatusbarHeight;
                    276:        } else {
                    277:                assert(fonth+2 < StatusbarHeight);
                    278:        }
                    279: 
                    280:        /* draw statusbar background gray so that text shows */
                    281:        sbarbox.x = 0;
                    282:        sbarbox.y = surf->h - StatusbarHeight;
                    283:        sbarbox.w = surf->w;
                    284:        sbarbox.h = StatusbarHeight;
                    285:        SDL_FillRect(surf, &sbarbox, GrayBg);
                    286: 
                    287:        /* led size */
                    288:        LedRect.w = fonth/2;
                    289:        LedRect.h = fonth - 4;
                    290:        LedRect.y = ScreenHeight + StatusbarHeight/2 - LedRect.h/2;
                    291: 
                    292:        /* black box for the leds */
                    293:        ledbox = LedRect;
                    294:        ledbox.y -= 1;
                    295:        ledbox.w += 2;
                    296:        ledbox.h += 2;
                    297: 
                    298:        offset = fontw;
                    299:        MessageRect.y = LedRect.y - 2;
                    300:        /* draw led texts and boxes + calculate box offsets */
1.1.1.4 ! root      301:        for (i = 0; i < NUM_DEVICE_LEDS; i++) {
1.1       root      302:                SDLGui_Text(offset, MessageRect.y, text[i]);
                    303:                offset += strlen(text[i]) * fontw;
                    304:                offset += fontw/2;
                    305: 
                    306:                ledbox.x = offset - 1;
                    307:                SDL_FillRect(surf, &ledbox, LedColorBg);
                    308: 
                    309:                LedRect.x = offset;
                    310:                SDL_FillRect(surf, &LedRect, LedColorOff);
                    311: 
                    312:                Led[i].offset = offset;
                    313:                offset += LedRect.w + fontw;
                    314:        }
1.1.1.4 ! root      315: #if 0
1.1       root      316:        /* draw frameskip */
                    317:        FrameSkipsRect.x = offset;
                    318:        FrameSkipsRect.y = MessageRect.y;
                    319:        SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, "FS:");
                    320:        FrameSkipsRect.x += 3 * fontw + fontw/2;
                    321:        FrameSkipsRect.w = 4 * fontw;
                    322:        FrameSkipsRect.h = fonth;
                    323: 
                    324:        if(ConfigureParams.System.bFastForward) {
                    325:                SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, "0 >>");
                    326:        } else {
                    327:                SDLGui_Text(FrameSkipsRect.x, FrameSkipsRect.y, "0");
                    328:        }
                    329: 
                    330:        nOldFrameSkips = 0;
                    331: 
                    332:        /* intialize messages */
                    333:        MessageRect.x = FrameSkipsRect.x + FrameSkipsRect.w + fontw;
1.1.1.4 ! root      334: #else
        !           335:     MessageRect.x = offset + fontw;
        !           336: #endif
1.1       root      337:        MessageRect.w = MAX_MESSAGE_LEN * fontw;
                    338:        MessageRect.h = fonth;
                    339:        for (item = MessageList; item; item = item->next) {
                    340:                item->shown = false;
                    341:        }
                    342: 
1.1.1.4 ! root      343: #if ENABLE_DIMENSION
        !           344:     /* draw i860 led box */
        !           345:     NdLedRect = LedRect;
        !           346:     NdLedRect.x = surf->w - 15*fontw - NdLedRect.w;
        !           347:     ledbox.x = NdLedRect.x - 1;
        !           348:     SDLGui_Text(ledbox.x - 3*fontw - fontw/2, MessageRect.y, "ND:");
        !           349:     SDL_FillRect(surf, &ledbox, LedColorBg);
        !           350:     SDL_FillRect(surf, &NdLedRect, NdColorOff);
        !           351:     nOldNdLed = 0;
        !           352: #endif
        !           353: 
        !           354:        /* draw dsp led box */
        !           355:        DspLedRect = LedRect;
        !           356:        DspLedRect.x = surf->w - 8*fontw - DspLedRect.w;
        !           357:        ledbox.x = DspLedRect.x - 1;
        !           358:        SDLGui_Text(ledbox.x - 4*fontw - fontw/2, MessageRect.y, "DSP:");
        !           359:        SDL_FillRect(surf, &ledbox, LedColorBg);
        !           360:        SDL_FillRect(surf, &DspLedRect, DspColorOff);
        !           361:        bOldDspLed = false;
        !           362: 
        !           363:        /* draw system led box */
        !           364:        SystemLedRect = LedRect;
        !           365:        SystemLedRect.x = surf->w - fontw - SystemLedRect.w;
        !           366:        ledbox.x = SystemLedRect.x - 1;
1.1.1.3   root      367:        SDLGui_Text(ledbox.x - 4*fontw - fontw/2, MessageRect.y, "LED:");
1.1       root      368:        SDL_FillRect(surf, &ledbox, LedColorBg);
1.1.1.4 ! root      369:        SDL_FillRect(surf, &SystemLedRect, SysColorOff);
        !           370:        bOldSystemLed = false;
1.1       root      371: 
                    372:        /* and blit statusbar on screen */
                    373:        SDL_UpdateRects(surf, 1, &sbarbox);
                    374:        DEBUGPRINT(("Draw statusbar\n"));
                    375: }
                    376: 
                    377: 
                    378: /*-----------------------------------------------------------------------*/
                    379: /**
                    380:  * Qeueue new statusbar message 'msg' to be shown for 'msecs' milliseconds
                    381:  */
                    382: void Statusbar_AddMessage(const char *msg, Uint32 msecs)
                    383: {
                    384:        msg_item_t *item;
                    385: 
                    386:        if (!ConfigureParams.Screen.bShowStatusbar) {
                    387:                /* no sense in queuing messages that aren't shown */
                    388:                return;
                    389:        }
                    390:        item = calloc(1, sizeof(msg_item_t));
                    391:        assert(item);
                    392: 
                    393:        item->next = MessageList;
                    394:        MessageList = item;
                    395: 
                    396:        strncpy(item->msg, msg, MAX_MESSAGE_LEN);
                    397:        item->msg[MAX_MESSAGE_LEN] = '\0';
                    398:        DEBUGPRINT(("Add message: '%s'\n", item->msg));
                    399: 
                    400:        if (msecs) {
                    401:                item->timeout = msecs;
                    402:        } else {
                    403:                /* show items by default for 2.5 secs */
                    404:                item->timeout = 2500;
                    405:        }
                    406:        item->shown = false;
                    407: }
                    408: 
                    409: /*-----------------------------------------------------------------------*/
                    410: /**
                    411:  * Write given 'more' string to 'buffer' and return new end of 'buffer'
                    412:  */
                    413: static char *Statusbar_AddString(char *buffer, const char *more)
                    414: {
                    415:        while(*more) {
                    416:                *buffer++ = *more++;
                    417:        }
                    418:        return buffer;
                    419: }
                    420: 
                    421: /*-----------------------------------------------------------------------*/
                    422: /**
                    423:  * Retrieve/update default statusbar information
                    424:  */
                    425: void Statusbar_UpdateInfo(void)
                    426: {
                    427:        char *end = DefaultMessage.msg;
1.1.1.4 ! root      428:        char memsize[8];
        !           429:        
        !           430: #if ENABLE_DIMENSION
        !           431:        /* Message for NeXTdimension */
        !           432:        if (ConfigureParams.Dimension.bEnabled &&
        !           433:                ConfigureParams.Screen.nMonitorType==MONITOR_TYPE_DIMENSION) {
        !           434:                end = Statusbar_AddString(end, "33MHz/i860XR/");
        !           435:                sprintf(memsize, "%iMB/",Configuration_CheckDimensionMemory(ConfigureParams.Dimension.nMemoryBankSize));
        !           436:                end = Statusbar_AddString(end, memsize);
        !           437:                end = Statusbar_AddString(end, "NeXTdimension");
        !           438:                *end = '\0';
        !           439:                assert(end - DefaultMessage.msg < MAX_MESSAGE_LEN);
        !           440:                DefaultMessage.shown = false;
        !           441:                return;
        !           442:        }
        !           443: #endif
        !           444:        
1.1       root      445:        /* CPU MHz */
                    446:        if (ConfigureParams.System.nCpuFreq > 9) {
                    447:                *end++ = '0' + ConfigureParams.System.nCpuFreq / 10;
                    448:        }
                    449:        *end++ = '0' + ConfigureParams.System.nCpuFreq % 10;
                    450:        end = Statusbar_AddString(end, "MHz/");
                    451: 
                    452:        /* CPU type */
                    453:        if(ConfigureParams.System.nCpuLevel > 0) {
1.1.1.3   root      454:         *end++ = '6';
                    455:         *end++ = '8';
1.1       root      456:                *end++ = '0';
1.1.1.3   root      457:         switch (ConfigureParams.System.nCpuLevel) {
                    458:             case 0: *end++ = '0'; break;
                    459:             case 1: *end++ = '1'; break;
                    460:             case 2: *end++ = '2'; break;
                    461:             case 3: *end++ = '3'; break;
                    462:             case 4: *end++ = '4'; break;
                    463:             case 5: *end++ = '6'; break;
                    464:             default: break;
                    465:         }
1.1       root      466:                *end++ = '0';
                    467:                *end++ = '/';
                    468:        }
                    469: 
                    470:        /* amount of memory */
1.1.1.3   root      471:     sprintf(memsize, "%iMB/", Configuration_CheckMemory(ConfigureParams.Memory.nMemoryBankSize));
                    472:     end = Statusbar_AddString(end, memsize);
1.1       root      473: 
                    474:        /* machine type */
1.1.1.3   root      475:     switch (ConfigureParams.System.nMachineType) {
                    476:         case NEXT_CUBE030:
                    477:             end = Statusbar_AddString(end, "NeXT Computer");
                    478:             break;
                    479:         case NEXT_CUBE040:
                    480:             end = Statusbar_AddString(end, "NeXTcube");
                    481:             break;
                    482:         case NEXT_STATION:
                    483:             end = Statusbar_AddString(end, "NeXTstation");
                    484:             break;
                    485:             
                    486:         default:
                    487:             break;
                    488:     }
                    489:     if (ConfigureParams.System.bTurbo)
1.1.1.4 ! root      490:         end = Statusbar_AddString(end, (ConfigureParams.System.nCpuFreq==40)?" Nitro":" Turbo");
        !           491: 
1.1.1.3   root      492:     if (ConfigureParams.System.bColor)
                    493:         end = Statusbar_AddString(end, " Color");
1.1       root      494: 
                    495:        *end = '\0';
                    496: 
                    497:        assert(end - DefaultMessage.msg < MAX_MESSAGE_LEN);
                    498:        DEBUGPRINT(("Set default message: '%s'\n", DefaultMessage.msg));
1.1.1.2   root      499:     /* make sure default message gets (re-)drawn when next checked */
1.1       root      500:        DefaultMessage.shown = false;
                    501: }
                    502: 
                    503: /*-----------------------------------------------------------------------*/
                    504: /**
                    505:  * Draw 'msg' centered to the message area
                    506:  */
                    507: static void Statusbar_DrawMessage(SDL_Surface *surf, const char *msg)
                    508: {
                    509:        int fontw, fonth, offset;
                    510:        SDL_FillRect(surf, &MessageRect, GrayBg);
                    511:        if (*msg) {
                    512:                SDLGui_GetFontSize(&fontw, &fonth);
                    513:                offset = (MessageRect.w - strlen(msg) * fontw) / 2;
                    514:                SDLGui_Text(MessageRect.x + offset, MessageRect.y, msg);
                    515:        }
                    516:        SDL_UpdateRects(surf, 1, &MessageRect);
                    517:        DEBUGPRINT(("Draw message: '%s'\n", msg));
                    518: }
                    519: 
                    520: /*-----------------------------------------------------------------------*/
                    521: /**
                    522:  * If message's not shown, show it.  If message's timed out,
                    523:  * remove it and show next one.
                    524:  */
                    525: static void Statusbar_ShowMessage(SDL_Surface *surf, Uint32 ticks)
                    526: {
                    527:        msg_item_t *next;
                    528: 
                    529:        if (MessageList->shown) {
                    530:                if (!MessageList->expire) {
1.1.1.2   root      531:                        /* last/default message never expires */
1.1       root      532:                        return;
                    533:                }
                    534:                if (MessageList->expire > ticks) {
                    535:                        /* not timed out yet */
                    536:                        return;
                    537:                }
                    538:                assert(MessageList->next); /* last message shouldn't end here */
                    539:                next = MessageList->next;
                    540:                free(MessageList);
                    541:                MessageList = next;
                    542:                /* make sure next message gets shown */
                    543:                MessageList->shown = false;
                    544:        }
                    545:        if (!MessageList->shown) {
                    546:                /* not shown yet, show */
                    547:                Statusbar_DrawMessage(surf,  MessageList->msg);
                    548:                if (MessageList->timeout && !MessageList->expire) {
                    549:                        MessageList->expire = ticks + MessageList->timeout;
                    550:                }
                    551:                MessageList->shown = true;
                    552:        }
                    553: }
                    554: 
                    555: 
                    556: /*-----------------------------------------------------------------------*/
                    557: /**
                    558:  * Save the area that will be left under overlay led
                    559:  */
                    560: void Statusbar_OverlayBackup(SDL_Surface *surf)
                    561: {
                    562:        if ((StatusbarHeight && ConfigureParams.Screen.bShowStatusbar)
                    563:            || !ConfigureParams.Screen.bShowDriveLed) {
                    564:                /* overlay not used with statusbar */
                    565:                return;
                    566:        }
                    567:        assert(surf);
                    568:        if (!OverlayUnderside) {
                    569:                SDL_Surface *bak;
                    570:                SDL_PixelFormat *fmt = surf->format;
                    571:                bak = SDL_CreateRGBSurface(surf->flags,
                    572:                                           OverlayLedRect.w, OverlayLedRect.h,
                    573:                                           fmt->BitsPerPixel,
                    574:                                           fmt->Rmask, fmt->Gmask, fmt->Bmask,
                    575:                                           fmt->Amask);
                    576:                assert(bak);
                    577:                OverlayUnderside = bak;
                    578:        }
                    579:        SDL_BlitSurface(surf, &OverlayLedRect, OverlayUnderside, NULL);
                    580: }
                    581: 
                    582: /*-----------------------------------------------------------------------*/
                    583: /**
                    584:  * Restore the area left under overlay led
                    585:  */
                    586: void Statusbar_OverlayRestore(SDL_Surface *surf)
                    587: {
                    588:        if ((StatusbarHeight && ConfigureParams.Screen.bShowStatusbar)
                    589:            || !ConfigureParams.Screen.bShowDriveLed) {
                    590:                /* overlay not used with statusbar */
                    591:                return;
                    592:        }
                    593:        if (bOverlayState == OVERLAY_DRAWN && OverlayUnderside) {
                    594:                assert(surf);
                    595:                SDL_BlitSurface(OverlayUnderside, NULL, surf, &OverlayLedRect);
                    596:                /* this will make the draw function to update this the screen */
                    597:                bOverlayState = OVERLAY_RESTORED;
                    598:        }
                    599: }
                    600: 
                    601: /*-----------------------------------------------------------------------*/
                    602: /**
                    603:  * Draw overlay led
                    604:  */
                    605: static void Statusbar_OverlayDrawLed(SDL_Surface *surf, Uint32 color)
                    606: {
                    607:        SDL_Rect rect;
                    608:        if (bOverlayState == OVERLAY_DRAWN) {
                    609:                /* some led already drawn */
                    610:                return;
                    611:        }
                    612:        bOverlayState = OVERLAY_DRAWN;
                    613: 
                    614:        /* enabled led with border */
                    615:        rect = OverlayLedRect;
                    616:        rect.x += 1;
                    617:        rect.y += 1;
                    618:        rect.w -= 2;
                    619:        rect.h -= 2;
                    620:        SDL_FillRect(surf, &OverlayLedRect, LedColorBg);
                    621:        SDL_FillRect(surf, &rect, color);
                    622: }
                    623: 
                    624: /*-----------------------------------------------------------------------*/
                    625: /**
                    626:  * Draw overlay led onto screen surface if any drives are enabled.
                    627:  */
                    628: static void Statusbar_OverlayDraw(SDL_Surface *surf)
                    629: {
                    630:        Uint32 currentticks = SDL_GetTicks();
                    631:        int i;
                    632: 
                    633:        assert(surf);
1.1.1.4 ! root      634:        for (i = 0; i < NUM_DEVICE_LEDS; i++) {
1.1       root      635:                if (Led[i].state) {
                    636:                        if (Led[i].expire && Led[i].expire < currentticks) {
                    637:                                Led[i].state = false;
                    638:                                continue;
                    639:                        }
                    640:                        Statusbar_OverlayDrawLed(surf, LedColorOn);
                    641:                        break;
                    642:                }
                    643:        }
                    644:        /* possible state transitions:
                    645:         *   NONE -> DRAWN -> RESTORED -> DRAWN -> RESTORED -> NONE
                    646:         * Other than NONE state needs to be updated on screen
                    647:         */
                    648:        switch (bOverlayState) {
                    649:        case OVERLAY_RESTORED:
                    650:                bOverlayState = OVERLAY_NONE;
                    651:        case OVERLAY_DRAWN:
                    652:                SDL_UpdateRects(surf, 1, &OverlayLedRect);
                    653:                DEBUGPRINT(("Overlay LED = %s\n", bOverlayState==OVERLAY_DRAWN?"ON":"OFF"));
                    654:                break;
                    655:        case OVERLAY_NONE:
                    656:                break;
                    657:        }
                    658: }
                    659: 
                    660: 
                    661: /*-----------------------------------------------------------------------*/
                    662: /**
                    663:  * Update statusbar information (leds etc) if/when needed.
                    664:  * 
                    665:  * May not be called when screen is locked (SDL limitation).
                    666:  */
                    667: void Statusbar_Update(SDL_Surface *surf)
                    668: {
                    669:        Uint32 color, currentticks;
                    670:        SDL_Rect rect;
                    671:        int i;
                    672: 
                    673:        if (!(StatusbarHeight && ConfigureParams.Screen.bShowStatusbar)) {
                    674:                /* not enabled (anymore), show overlay led instead? */
                    675:                if (ConfigureParams.Screen.bShowDriveLed) {
                    676:                        Statusbar_OverlayDraw(surf);
                    677:                }
                    678:                return;
                    679:        }
                    680:        assert(surf);
                    681:        /* Statusbar_Init() not called before this? */
                    682:        assert(surf->h == ScreenHeight + StatusbarHeight);
                    683: 
                    684:        rect = LedRect;
                    685:        currentticks = SDL_GetTicks();
1.1.1.4 ! root      686:        for (i = 0; i < NUM_DEVICE_LEDS; i++) {
1.1       root      687:                if (Led[i].expire && Led[i].expire < currentticks) {
                    688:                        Led[i].state = false;
                    689:                }
                    690:                if (Led[i].state == Led[i].oldstate) {
                    691:                        continue;
                    692:                }
                    693:                Led[i].oldstate = Led[i].state;
                    694:                if (Led[i].state) {
                    695:                        color = LedColorOn;
                    696:                } else {
                    697:                        color = LedColorOff;
                    698:                }
                    699:                rect.x = Led[i].offset;
                    700:                SDL_FillRect(surf, &rect, color);
                    701:                SDL_UpdateRects(surf, 1, &rect);
                    702:                DEBUGPRINT(("LED[%d] = %s\n", i, Led[i].state?"ON":"OFF"));
                    703:        }
                    704: 
                    705:        Statusbar_ShowMessage(surf, currentticks);
                    706: 
1.1.1.4 ! root      707:        /* Draw dsp LED */
        !           708:        if (bOldDspLed) {
        !           709:                color = DspColorOn;
        !           710:        } else {
        !           711:                color = DspColorOff;
        !           712:        }
        !           713:        SDL_FillRect(surf, &DspLedRect, color);
        !           714:        SDL_UpdateRects(surf, 1, &DspLedRect);
        !           715:        DEBUGPRINT(("DSP LED = ON\n"));
        !           716: 
1.1.1.3   root      717:     /* Draw scr2 LED */
1.1.1.4 ! root      718:     if (bOldSystemLed) {
        !           719:         color = SysColorOn;
1.1.1.3   root      720:     } else {
1.1.1.4 ! root      721:         color = SysColorOff;
1.1.1.3   root      722:     }
1.1.1.4 ! root      723:     SDL_FillRect(surf, &SystemLedRect, color);
        !           724:     SDL_UpdateRects(surf, 1, &SystemLedRect);
1.1.1.3   root      725:     DEBUGPRINT(("SCR2 LED = ON\n"));
1.1.1.4 ! root      726:     
        !           727: #if ENABLE_DIMENSION
        !           728:     /* Draw NeXTdimension LED */
        !           729:     switch(nOldNdLed) {
        !           730:         case 0: color = NdColorOff; break;
        !           731:         case 1: color = NdColorCS8;  break;
        !           732:         case 2: color = NdColorOn;  break;
        !           733:                default: color = NdColorOff; break;
        !           734:     }
        !           735:     SDL_FillRect(surf, &NdLedRect, color);
        !           736:     SDL_UpdateRects(surf, 1, &NdLedRect);
        !           737:     DEBUGPRINT(("ND LED = ON\n"));
        !           738: #endif
1.1       root      739: }

unix.superglobalmegacorp.com

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