Beispiel #1
0
/*
 * The main display function.
 */
int display_update(int timeofday, int dayofweek, int date,
                   const struct pstate *ps, const struct lstate *ls,
                   struct button *buttons)
{
    int xext[2*MAXSPRITES+2], yext[2*MAXSPRITES+2];
    struct displaysprite *olds[MAXSPRITES], *news[MAXSPRITES];
    int nolds, nnews;
    int nxext, nyext, xe, ye;
    int i, j, digits[6];
    int dispdim;
    int nbuttons = 0;

    nextnsprites = 0;

#define PUTSPRITEAT(mindex, mxoff, myoff) do { \
    int index = (mindex), xoff = (mxoff), yoff = (myoff); \
    assert(nextnsprites < MAXSPRITES); \
    nextdisp[nextnsprites].x = sprites[index]->x + xoff; \
    nextdisp[nextnsprites].y = sprites[index]->y + yoff; \
    nextdisp[nextnsprites].w = sprites[index]->w; \
    nextdisp[nextnsprites].h = sprites[index]->h; \
    nextdisp[nextnsprites].pixels = sprites[index]->pixels; \
    nextnsprites++; \
} while (0)
#define PUTSPRITE(mindex) PUTSPRITEAT(mindex, 0, 0)
#define PUTBUTTON(mbindex, mindex) do { \
    int bindex = (mbindex), sindex = (mindex); \
    PUTSPRITEAT(sindex, 0, 0); \
    assert(nbuttons < MAXBUTTONS); \
    buttons[nbuttons].x = sprites[bindex]->x; \
    buttons[nbuttons].y = sprites[bindex]->y; \
    buttons[nbuttons].w = sprites[bindex]->w; \
    buttons[nbuttons].h = sprites[bindex]->h; \
    buttons[nbuttons].id = bindex; \
    nbuttons++; \
} while (0)
#define PUTPBUTTON(mbindex, mpindex) do { \
    int bbindex = (mbindex), ppindex = (mpindex); \
    PUTBUTTON(bbindex, (ls->pressed_button_id == bbindex ? \
			ppindex : bbindex)); \
} while (0)
    /*
     * Display policy section. Go through the state inputs and
     * work out what sprites we want to display where.
     */
    switch (ls->dmode) {
    case DMODE_NORMAL:
    case DMODE_CONFIGURE:
        /*
         * Normal display mode, or top-level configuration menu.
         * Always show the week day, and the time.
         *
         * (Exception: if the network is on the fritz, replace the
         * day of the week with a big white NETWORK FAULT message.)
         */
        if (ls->network_fault)
            PUTSPRITE(NETWORK_FAULT);
        else
            PUTSPRITE(WEEKDAY_MONDAY + dayofweek);
        breakdown_time(timeofday, digits);
        for (i = 0; i < 4; i++)
            if (i || digits[i])	       /* don't display leading 0 on hours */
                PUTSPRITEAT(TIME_HM_0 + digits[i], time_offsets[i], 0);
        for (i = 0; i < 2; i++)
            PUTSPRITEAT(TIME_S_0 + digits[i+4], sec_offsets[i], 0);
        PUTSPRITE(TIME_FIXED);
        /*
         * Depending on alarm mode, display the alarm time or the
         * confirm message.
         */
        if (ls->amode == AMODE_CONFIRM) {
            /*
             * The confirm-alarm message is not shown in configure
             * mode, because it would seem strange to order the
             * user to confirm the alarm while not displaying the
             * buttons they need to press to do it.
             */
            if (ls->dmode == DMODE_NORMAL)
                PUTSPRITE(CONFIRM_ALARM);
        } else if (ls->amode == AMODE_ON) {
            PUTSPRITE(ALARMTIME_FIXED);
            breakdown_time(ls->alarm_time, digits);
            for (i = 0; i < 6; i++)
                if (i || digits[i])    /* don't display leading 0 on hours */
                    PUTSPRITEAT(ALARMTIME_0 + digits[i],
                                alarm_digit_offsets[i], 0);
        }
        if (ls->dmode == DMODE_CONFIGURE) {
            /*
             * In configure mode, always display all the configure
             * buttons, except for the one that only makes sense if we
             * have access to downloadable exception data.
             */
            PUTPBUTTON(NORM_BUTTON_ALARM_TIME, ACTIVE_BUTTON_ALARM_TIME);
            PUTPBUTTON(NORM_BUTTON_BACK, ACTIVE_BUTTON_BACK);
            PUTPBUTTON(NORM_BUTTON_RESET_TIME, ACTIVE_BUTTON_RESET_TIME);
            PUTPBUTTON(NORM_BUTTON_SNOOZE_PERIOD, ACTIVE_BUTTON_SNOOZE_PERIOD);
            if (ls->display_redownload_button)
                PUTPBUTTON(NORM_BUTTON_REDOWNLOAD, ACTIVE_BUTTON_REDOWNLOAD);
            PUTPBUTTON(NORM_BUTTON_OFF_DAYS, ACTIVE_BUTTON_OFF_DAYS);
            /*
             * In configure mode, display is always bright.
             */
            dispdim = 0;
        } else {
            /*
             * Conditionally display the main buttons. All buttons
             * are displayed if the touchscreen was recently
             * active; SNOOZE and SHUT UP are displayed if the
             * alarm is sounding; ALARM ON and ALARM OFF are
             * displayed in confirm mode; otherwise, nothing is
             * displayed.
             */
            if (ls->recent_touch || ls->alarm_sounding)
                PUTPBUTTON(NORM_BUTTON_SNOOZE, ACTIVE_BUTTON_SNOOZE);
            if (ls->recent_touch)
                PUTPBUTTON(NORM_BUTTON_SETUP, ACTIVE_BUTTON_SETUP);
            if (ls->recent_touch || ls->alarm_sounding)
                PUTPBUTTON(NORM_BUTTON_SHUT_UP, ACTIVE_BUTTON_SHUT_UP);
            if (ls->recent_touch || ls->amode == AMODE_CONFIRM)
                PUTPBUTTON(NORM_BUTTON_ALARM_ON, ACTIVE_BUTTON_ALARM_ON);
            if (ls->recent_touch)
                PUTPBUTTON(NORM_BUTTON_CONFIRM, ACTIVE_BUTTON_CONFIRM);
            if (ls->recent_touch || ls->amode == AMODE_CONFIRM)
                PUTPBUTTON(NORM_BUTTON_ALARM_OFF, ACTIVE_BUTTON_ALARM_OFF);
            /*
             * Display is dim unless something interesting has
             * happened.
             */
            dispdim = !(ls->recent_touch ||
                        ls->alarm_sounding ||
                        ls->amode == AMODE_CONFIRM);
        }
        break;

    case DMODE_SETALARM:
    case DMODE_SETSNOOZE:
    case DMODE_SETDEFALARM:
    case DMODE_SETRESET:
    case DMODE_SETDEFSNOOZE:
        /*
         * In all of these modes, we are displaying some
         * particular time from one of the configuration
         * structures, the adjustment arrows, and the button to
         * indicate which setting it was.
         */
    {
        int button;
        const int *editable = editable_value(ps, ls, NULL, &button);
        breakdown_time(*editable, digits);
        PUTSPRITE(button);
    }
    PUTSPRITE(TIME_FIXED);
    for (i = 0; i < 4; i++)
        PUTSPRITEAT(TIME_HM_0 + digits[i], time_offsets[i], 0);
    for (i = 0; i < 2; i++)
        PUTSPRITEAT(TIME_S_0 + digits[i+4], sec_offsets[i], 0);
    PUTPBUTTON(NORM_ADJUST_H10_UP, ACTIVE_ADJUST_H10_UP);
    PUTPBUTTON(NORM_ADJUST_H1_UP, ACTIVE_ADJUST_H1_UP);
    PUTPBUTTON(NORM_ADJUST_M10_UP, ACTIVE_ADJUST_M10_UP);
    PUTPBUTTON(NORM_ADJUST_M1_UP, ACTIVE_ADJUST_M1_UP);
    PUTPBUTTON(NORM_ADJUST_S10_UP, ACTIVE_ADJUST_S10_UP);
    PUTPBUTTON(NORM_ADJUST_S1_UP, ACTIVE_ADJUST_S1_UP);
    PUTPBUTTON(NORM_ADJUST_H10_DN, ACTIVE_ADJUST_H10_DN);
    PUTPBUTTON(NORM_ADJUST_H1_DN, ACTIVE_ADJUST_H1_DN);
    PUTPBUTTON(NORM_ADJUST_M10_DN, ACTIVE_ADJUST_M10_DN);
    PUTPBUTTON(NORM_ADJUST_M1_DN, ACTIVE_ADJUST_M1_DN);
    PUTPBUTTON(NORM_ADJUST_S10_DN, ACTIVE_ADJUST_S10_DN);
    PUTPBUTTON(NORM_ADJUST_S1_DN, ACTIVE_ADJUST_S1_DN);
        /*
         * Display the BACK button, to return to normal mode.
         */
    PUTPBUTTON(NORM_BUTTON_BACK, ACTIVE_BUTTON_BACK);
        /*
         * In setup modes, display is always bright.
         */
    dispdim = 0;
        /*
         * In default-alarm-time setting mode, we also display the
         * day buttons at the bottom of the display, indicating which
         * days we're currently configuring.
         */
    if (ls->dmode == DMODE_SETDEFALARM) {
        for (i = 0; i < 7; i++) {
            if (ls->configuring_days & (1 << i))
                PUTBUTTON(CONFIG_BUTTON_MONDAY + i,
                          ACTIVE_CONFIG_BUTTON_MONDAY + i);
            else
                PUTBUTTON(CONFIG_BUTTON_MONDAY + i,
                          CONFIG_BUTTON_MONDAY + i);
        }
    }
    break;

    case DMODE_SETOFFDAYS:
        /*
         * In off-days mode, we display the seven off-day buttons,
         * plus the off-days button as a mode indicator.
         */
        PUTSPRITE(ACTIVE_BUTTON_OFF_DAYS);
        for (i = 0; i < 7; i++) {
            if (ps->offdays & (1 << i))
                PUTBUTTON(OFFDAY_BUTTON_MONDAY + i, ONDAY_BUTTON_MONDAY + i);
            else
                PUTBUTTON(OFFDAY_BUTTON_MONDAY + i, OFFDAY_BUTTON_MONDAY + i);
        }
        /*
         * Display the BACK button, to return to normal mode.
         */
        PUTPBUTTON(NORM_BUTTON_BACK, ACTIVE_BUTTON_BACK);
        /*
         * In setup modes, display is always bright.
         */
        dispdim = 0;
    }

    /*
     * Sort the list of sprites.
     */
    qsort(nextdisp, nextnsprites, sizeof(*nextdisp), sprite_sort_cmp);

    /*
     * Find all the extremal x and y coordinates of all the
     * sprites, both old and new. This lets us divide the screen
     * into an irregular grid of subrectangles, within each of
     * which all pixels are part of the same subset of the
     * sprites. We can then process each subrectangle uniformly.
     */
    nxext = nyext = 0;
    xext[nxext++] = yext[nyext++] = 0;
    for (i = 0; i < nextnsprites; i++) {
        xext[nxext++] = nextdisp[i].x;
        xext[nxext++] = nextdisp[i].x + nextdisp[i].w;
        yext[nyext++] = nextdisp[i].y;
        yext[nyext++] = nextdisp[i].y + nextdisp[i].h;
    }
    for (i = 0; i < currnsprites; i++) {
        xext[nxext++] = currdisp[i].x;
        xext[nxext++] = currdisp[i].x + currdisp[i].w;
        yext[nyext++] = currdisp[i].y;
        yext[nyext++] = currdisp[i].y + currdisp[i].h;
    }
    qsort(xext, nxext, sizeof(*xext), int_cmp);
    qsort(yext, nyext, sizeof(*yext), int_cmp);
    for (i = j = 0; i < nxext; i++)
        if (j == 0 || xext[j-1] != xext[i])
            xext[j++] = xext[i];
    nxext = j;
    xext[j] = scr_width;
    for (i = j = 0; i < nyext; i++)
        if (j == 0 || yext[j-1] != yext[i])
            yext[j++] = yext[i];
    nyext = j;
    yext[j] = scr_height;

    /*
     * Now, for each subrectangle, go through the sprite list and
     * determine which sprites we need to draw in that
     * subrectangle. Also, do that for the old sprite list, and
     * see if the lists are the same.
     */
    for (ye = 0; ye < nyext; ye++) {
        int y0 = yext[ye], y1 = yext[ye+1];
        for (xe = 0; xe < nxext; xe++) {
            int x0 = xext[xe], x1 = xext[xe+1];

            nolds = 0;
            for (i = 0; i < currnsprites; i++)
                if (x0 >= currdisp[i].x && x0 < currdisp[i].x+currdisp[i].w &&
                        y0 >= currdisp[i].y && y0 < currdisp[i].y+currdisp[i].h)
                    olds[nolds++] = &currdisp[i];
            nnews = 0;
            for (i = 0; i < nextnsprites; i++)
                if (x0 >= nextdisp[i].x && x0 < nextdisp[i].x+nextdisp[i].w &&
                        y0 >= nextdisp[i].y && y0 < nextdisp[i].y+nextdisp[i].h)
                    news[nnews++] = &nextdisp[i];

            if (nolds == nnews) {
                /*
                 * The lists might be identical.
                 */
                for (i = 0; i < nolds; i++)
                    if (sprite_sort_cmp(olds[i], news[i]))
                        break;

                if (i == nolds)
                    continue;	       /* they were! */
            }

            {
                struct display_pixel_ctx ctx;
                ctx.nds = nnews;
                ctx.ds = news;
                update_display(x0, y0, x1-x0, y1-y0, display_pixel, &ctx);
            }
        }
    }

    currnsprites = nextnsprites;
    {
        struct displaysprite *tmp = currdisp;
        currdisp = nextdisp;
        nextdisp = tmp;
    }

    /*
     * Dim the display appropriately.
     */
    if (always_bright)
        dispdim = 0;
    if (currdim != dispdim) {
        dim_display(dispdim);
        currdim = dispdim;
    }

    /*
     * Expand the button rectangles a bit, to make it easier to
     * hit them. They may overlap as a result, but the next level
     * of code up from here will deal sensibly with apportioning
     * the overlap space fairly to the contending buttons.
     */
    for (i = 0; i < nbuttons; i++) {
        buttons[i].x -= buttons[i].w / 2;
        buttons[i].w *= 2;
        buttons[i].y -= buttons[i].h / 2;
        buttons[i].h *= 2;
    }

    return nbuttons;
}
Beispiel #2
0
int qse_gmtime (const qse_ntime_t* nt, qse_btime_t* bt)
{
	breakdown_time (nt, bt, 0);
	return 0;
}