Annotation of embedaddon/tmux/screen-redraw.c, revision 1.1

1.1     ! misho       1: /* $OpenBSD$ */
        !             2: 
        !             3: /*
        !             4:  * Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice and this permission notice appear in all copies.
        !             9:  *
        !            10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            14:  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
        !            15:  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
        !            16:  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            17:  */
        !            18: 
        !            19: #include <sys/types.h>
        !            20: 
        !            21: #include <string.h>
        !            22: 
        !            23: #include "tmux.h"
        !            24: 
        !            25: static int     screen_redraw_cell_border1(struct window_pane *, u_int, u_int);
        !            26: static int     screen_redraw_cell_border(struct client *, u_int, u_int);
        !            27: static int     screen_redraw_check_cell(struct client *, u_int, u_int, int,
        !            28:                    struct window_pane **);
        !            29: static int     screen_redraw_check_is(u_int, u_int, int, int, struct window *,
        !            30:                    struct window_pane *, struct window_pane *);
        !            31: 
        !            32: static int     screen_redraw_make_pane_status(struct client *, struct window *,
        !            33:                    struct window_pane *);
        !            34: static void    screen_redraw_draw_pane_status(struct client *, int);
        !            35: 
        !            36: static void    screen_redraw_draw_borders(struct client *, int, int, u_int);
        !            37: static void    screen_redraw_draw_panes(struct client *, u_int);
        !            38: static void    screen_redraw_draw_status(struct client *, u_int);
        !            39: static void    screen_redraw_draw_number(struct client *, struct window_pane *,
        !            40:                    u_int);
        !            41: 
        !            42: #define CELL_INSIDE 0
        !            43: #define CELL_LEFTRIGHT 1
        !            44: #define CELL_TOPBOTTOM 2
        !            45: #define CELL_TOPLEFT 3
        !            46: #define CELL_TOPRIGHT 4
        !            47: #define CELL_BOTTOMLEFT 5
        !            48: #define CELL_BOTTOMRIGHT 6
        !            49: #define CELL_TOPJOIN 7
        !            50: #define CELL_BOTTOMJOIN 8
        !            51: #define CELL_LEFTJOIN 9
        !            52: #define CELL_RIGHTJOIN 10
        !            53: #define CELL_JOIN 11
        !            54: #define CELL_OUTSIDE 12
        !            55: 
        !            56: #define CELL_BORDERS " xqlkmjwvtun~"
        !            57: 
        !            58: #define CELL_STATUS_OFF 0
        !            59: #define CELL_STATUS_TOP 1
        !            60: #define CELL_STATUS_BOTTOM 2
        !            61: 
        !            62: /* Check if cell is on the border of a particular pane. */
        !            63: static int
        !            64: screen_redraw_cell_border1(struct window_pane *wp, u_int px, u_int py)
        !            65: {
        !            66:        /* Inside pane. */
        !            67:        if (px >= wp->xoff && px < wp->xoff + wp->sx &&
        !            68:            py >= wp->yoff && py < wp->yoff + wp->sy)
        !            69:                return (0);
        !            70: 
        !            71:        /* Left/right borders. */
        !            72:        if ((wp->yoff == 0 || py >= wp->yoff - 1) && py <= wp->yoff + wp->sy) {
        !            73:                if (wp->xoff != 0 && px == wp->xoff - 1)
        !            74:                        return (1);
        !            75:                if (px == wp->xoff + wp->sx)
        !            76:                        return (2);
        !            77:        }
        !            78: 
        !            79:        /* Top/bottom borders. */
        !            80:        if ((wp->xoff == 0 || px >= wp->xoff - 1) && px <= wp->xoff + wp->sx) {
        !            81:                if (wp->yoff != 0 && py == wp->yoff - 1)
        !            82:                        return (3);
        !            83:                if (py == wp->yoff + wp->sy)
        !            84:                        return (4);
        !            85:        }
        !            86: 
        !            87:        /* Outside pane. */
        !            88:        return (-1);
        !            89: }
        !            90: 
        !            91: /* Check if a cell is on the pane border. */
        !            92: static int
        !            93: screen_redraw_cell_border(struct client *c, u_int px, u_int py)
        !            94: {
        !            95:        struct window           *w = c->session->curw->window;
        !            96:        struct window_pane      *wp;
        !            97:        int                      retval;
        !            98: 
        !            99:        /* Check all the panes. */
        !           100:        TAILQ_FOREACH(wp, &w->panes, entry) {
        !           101:                if (!window_pane_visible(wp))
        !           102:                        continue;
        !           103:                if ((retval = screen_redraw_cell_border1(wp, px, py)) != -1)
        !           104:                        return (!!retval);
        !           105:        }
        !           106: 
        !           107:        return (0);
        !           108: }
        !           109: 
        !           110: /* Check if cell inside a pane. */
        !           111: static int
        !           112: screen_redraw_check_cell(struct client *c, u_int px, u_int py, int pane_status,
        !           113:     struct window_pane **wpp)
        !           114: {
        !           115:        struct window           *w = c->session->curw->window;
        !           116:        struct window_pane      *wp;
        !           117:        int                      borders;
        !           118:        u_int                    right, line;
        !           119: 
        !           120:        *wpp = NULL;
        !           121: 
        !           122:        if (px > w->sx || py > w->sy)
        !           123:                return (CELL_OUTSIDE);
        !           124: 
        !           125:        if (pane_status != CELL_STATUS_OFF) {
        !           126:                TAILQ_FOREACH(wp, &w->panes, entry) {
        !           127:                        if (!window_pane_visible(wp))
        !           128:                                continue;
        !           129: 
        !           130:                        if (pane_status == CELL_STATUS_TOP)
        !           131:                                line = wp->yoff - 1;
        !           132:                        else
        !           133:                                line = wp->yoff + wp->sy;
        !           134:                        right = wp->xoff + 2 + wp->status_size - 1;
        !           135: 
        !           136:                        if (py == line && px >= wp->xoff + 2 && px <= right)
        !           137:                                return (CELL_INSIDE);
        !           138:                }
        !           139:        }
        !           140: 
        !           141:        TAILQ_FOREACH(wp, &w->panes, entry) {
        !           142:                if (!window_pane_visible(wp))
        !           143:                        continue;
        !           144:                *wpp = wp;
        !           145: 
        !           146:                /* If outside the pane and its border, skip it. */
        !           147:                if ((wp->xoff != 0 && px < wp->xoff - 1) ||
        !           148:                    px > wp->xoff + wp->sx ||
        !           149:                    (wp->yoff != 0 && py < wp->yoff - 1) ||
        !           150:                    py > wp->yoff + wp->sy)
        !           151:                        continue;
        !           152: 
        !           153:                /* If definitely inside, return so. */
        !           154:                if (!screen_redraw_cell_border(c, px, py))
        !           155:                        return (CELL_INSIDE);
        !           156: 
        !           157:                /*
        !           158:                 * Construct a bitmask of whether the cells to the left (bit
        !           159:                 * 4), right, top, and bottom (bit 1) of this cell are borders.
        !           160:                 */
        !           161:                borders = 0;
        !           162:                if (px == 0 || screen_redraw_cell_border(c, px - 1, py))
        !           163:                        borders |= 8;
        !           164:                if (px <= w->sx && screen_redraw_cell_border(c, px + 1, py))
        !           165:                        borders |= 4;
        !           166:                if (pane_status == CELL_STATUS_TOP) {
        !           167:                        if (py != 0 && screen_redraw_cell_border(c, px, py - 1))
        !           168:                                borders |= 2;
        !           169:                } else {
        !           170:                        if (py == 0 || screen_redraw_cell_border(c, px, py - 1))
        !           171:                                borders |= 2;
        !           172:                }
        !           173:                if (py <= w->sy && screen_redraw_cell_border(c, px, py + 1))
        !           174:                        borders |= 1;
        !           175: 
        !           176:                /*
        !           177:                 * Figure out what kind of border this cell is. Only one bit
        !           178:                 * set doesn't make sense (can't have a border cell with no
        !           179:                 * others connected).
        !           180:                 */
        !           181:                switch (borders) {
        !           182:                case 15:        /* 1111, left right top bottom */
        !           183:                        return (CELL_JOIN);
        !           184:                case 14:        /* 1110, left right top */
        !           185:                        return (CELL_BOTTOMJOIN);
        !           186:                case 13:        /* 1101, left right bottom */
        !           187:                        return (CELL_TOPJOIN);
        !           188:                case 12:        /* 1100, left right */
        !           189:                        return (CELL_TOPBOTTOM);
        !           190:                case 11:        /* 1011, left top bottom */
        !           191:                        return (CELL_RIGHTJOIN);
        !           192:                case 10:        /* 1010, left top */
        !           193:                        return (CELL_BOTTOMRIGHT);
        !           194:                case 9:         /* 1001, left bottom */
        !           195:                        return (CELL_TOPRIGHT);
        !           196:                case 7:         /* 0111, right top bottom */
        !           197:                        return (CELL_LEFTJOIN);
        !           198:                case 6:         /* 0110, right top */
        !           199:                        return (CELL_BOTTOMLEFT);
        !           200:                case 5:         /* 0101, right bottom */
        !           201:                        return (CELL_TOPLEFT);
        !           202:                case 3:         /* 0011, top bottom */
        !           203:                        return (CELL_LEFTRIGHT);
        !           204:                }
        !           205:        }
        !           206: 
        !           207:        return (CELL_OUTSIDE);
        !           208: }
        !           209: 
        !           210: /* Check if the border of a particular pane. */
        !           211: static int
        !           212: screen_redraw_check_is(u_int px, u_int py, int type, int pane_status,
        !           213:     struct window *w, struct window_pane *wantwp, struct window_pane *wp)
        !           214: {
        !           215:        int     border;
        !           216: 
        !           217:        /* Is this off the active pane border? */
        !           218:        border = screen_redraw_cell_border1(wantwp, px, py);
        !           219:        if (border == 0 || border == -1)
        !           220:                return (0);
        !           221:        if (pane_status == CELL_STATUS_TOP && border == 4)
        !           222:                return (0);
        !           223:        if (pane_status == CELL_STATUS_BOTTOM && border == 3)
        !           224:                return (0);
        !           225: 
        !           226:        /* If there are more than two panes, that's enough. */
        !           227:        if (window_count_panes(w) != 2)
        !           228:                return (1);
        !           229: 
        !           230:        /* Else if the cell is not a border cell, forget it. */
        !           231:        if (wp == NULL || (type == CELL_OUTSIDE || type == CELL_INSIDE))
        !           232:                return (1);
        !           233: 
        !           234:        /* With status lines mark the entire line. */
        !           235:        if (pane_status != CELL_STATUS_OFF)
        !           236:                return (1);
        !           237: 
        !           238:        /* Check if the pane covers the whole width. */
        !           239:        if (wp->xoff == 0 && wp->sx == w->sx) {
        !           240:                /* This can either be the top pane or the bottom pane. */
        !           241:                if (wp->yoff == 0) { /* top pane */
        !           242:                        if (wp == wantwp)
        !           243:                                return (px <= wp->sx / 2);
        !           244:                        return (px > wp->sx / 2);
        !           245:                }
        !           246:                return (0);
        !           247:        }
        !           248: 
        !           249:        /* Check if the pane covers the whole height. */
        !           250:        if (wp->yoff == 0 && wp->sy == w->sy) {
        !           251:                /* This can either be the left pane or the right pane. */
        !           252:                if (wp->xoff == 0) { /* left pane */
        !           253:                        if (wp == wantwp)
        !           254:                                return (py <= wp->sy / 2);
        !           255:                        return (py > wp->sy / 2);
        !           256:                }
        !           257:                return (0);
        !           258:        }
        !           259: 
        !           260:        return (1);
        !           261: }
        !           262: 
        !           263: /* Update pane status. */
        !           264: static int
        !           265: screen_redraw_make_pane_status(struct client *c, struct window *w,
        !           266:     struct window_pane *wp)
        !           267: {
        !           268:        struct grid_cell         gc;
        !           269:        const char              *fmt;
        !           270:        struct format_tree      *ft;
        !           271:        char                    *out;
        !           272:        size_t                   outlen;
        !           273:        struct screen_write_ctx  ctx;
        !           274:        struct screen            old;
        !           275: 
        !           276:        if (wp == w->active)
        !           277:                style_apply(&gc, w->options, "pane-active-border-style");
        !           278:        else
        !           279:                style_apply(&gc, w->options, "pane-border-style");
        !           280: 
        !           281:        fmt = options_get_string(w->options, "pane-border-format");
        !           282: 
        !           283:        ft = format_create(NULL, FORMAT_PANE|wp->id, 0);
        !           284:        format_defaults(ft, c, NULL, NULL, wp);
        !           285: 
        !           286:        memcpy(&old, &wp->status_screen, sizeof old);
        !           287:        screen_init(&wp->status_screen, wp->sx, 1, 0);
        !           288:        wp->status_screen.mode = 0;
        !           289: 
        !           290:        out = format_expand(ft, fmt);
        !           291:        outlen = screen_write_cstrlen("%s", out);
        !           292:        if (outlen > wp->sx - 4)
        !           293:                outlen = wp->sx - 4;
        !           294:        screen_resize(&wp->status_screen, outlen, 1, 0);
        !           295: 
        !           296:        screen_write_start(&ctx, NULL, &wp->status_screen);
        !           297:        screen_write_cursormove(&ctx, 0, 0);
        !           298:        screen_write_clearline(&ctx, 8);
        !           299:        screen_write_cnputs(&ctx, outlen, &gc, "%s", out);
        !           300:        screen_write_stop(&ctx);
        !           301: 
        !           302:        format_free(ft);
        !           303: 
        !           304:        wp->status_size = outlen;
        !           305: 
        !           306:        if (grid_compare(wp->status_screen.grid, old.grid) == 0) {
        !           307:                screen_free(&old);
        !           308:                return (0);
        !           309:        }
        !           310:        screen_free(&old);
        !           311:        return (1);
        !           312: }
        !           313: 
        !           314: /* Draw pane status. */
        !           315: static void
        !           316: screen_redraw_draw_pane_status(struct client *c, int pane_status)
        !           317: {
        !           318:        struct window           *w = c->session->curw->window;
        !           319:        struct options          *oo = c->session->options;
        !           320:        struct tty              *tty = &c->tty;
        !           321:        struct window_pane      *wp;
        !           322:        int                      spos;
        !           323:        u_int                    yoff;
        !           324: 
        !           325:        spos = options_get_number(oo, "status-position");
        !           326:        TAILQ_FOREACH(wp, &w->panes, entry) {
        !           327:                if (!window_pane_visible(wp))
        !           328:                        continue;
        !           329:                if (pane_status == CELL_STATUS_TOP)
        !           330:                        yoff = wp->yoff - 1;
        !           331:                else
        !           332:                        yoff = wp->yoff + wp->sy;
        !           333:                if (spos == 0)
        !           334:                        yoff += 1;
        !           335: 
        !           336:                tty_draw_line(tty, NULL, &wp->status_screen, 0, wp->xoff + 2,
        !           337:                    yoff);
        !           338:        }
        !           339:        tty_cursor(tty, 0, 0);
        !           340: }
        !           341: 
        !           342: /* Update status line and change flags if unchanged. */
        !           343: void
        !           344: screen_redraw_update(struct client *c)
        !           345: {
        !           346:        struct window           *w = c->session->curw->window;
        !           347:        struct window_pane      *wp;
        !           348:        struct options          *wo = w->options;
        !           349:        int                      redraw;
        !           350: 
        !           351:        if (c->message_string != NULL)
        !           352:                redraw = status_message_redraw(c);
        !           353:        else if (c->prompt_string != NULL)
        !           354:                redraw = status_prompt_redraw(c);
        !           355:        else
        !           356:                redraw = status_redraw(c);
        !           357:        if (!redraw)
        !           358:                c->flags &= ~CLIENT_STATUS;
        !           359: 
        !           360:        if (options_get_number(wo, "pane-border-status") != CELL_STATUS_OFF) {
        !           361:                redraw = 0;
        !           362:                TAILQ_FOREACH(wp, &w->panes, entry) {
        !           363:                        if (screen_redraw_make_pane_status(c, w, wp))
        !           364:                                redraw = 1;
        !           365:                }
        !           366:                if (redraw)
        !           367:                        c->flags |= CLIENT_BORDERS;
        !           368:        }
        !           369: }
        !           370: 
        !           371: /* Redraw entire screen. */
        !           372: void
        !           373: screen_redraw_screen(struct client *c, int draw_panes, int draw_status,
        !           374:     int draw_borders)
        !           375: {
        !           376:        struct options          *oo = c->session->options;
        !           377:        struct tty              *tty = &c->tty;
        !           378:        struct window           *w = c->session->curw->window;
        !           379:        struct options          *wo = w->options;
        !           380:        u_int                    top;
        !           381:        int                      status, pane_status, spos;
        !           382: 
        !           383:        /* Suspended clients should not be updated. */
        !           384:        if (c->flags & CLIENT_SUSPENDED)
        !           385:                return;
        !           386: 
        !           387:        /* Get status line, er, status. */
        !           388:        spos = options_get_number(oo, "status-position");
        !           389:        if (c->message_string != NULL || c->prompt_string != NULL)
        !           390:                status = 1;
        !           391:        else
        !           392:                status = options_get_number(oo, "status");
        !           393:        top = 0;
        !           394:        if (status && spos == 0)
        !           395:                top = 1;
        !           396:        if (!status)
        !           397:                draw_status = 0;
        !           398: 
        !           399:        /* Draw the elements. */
        !           400:        if (draw_borders) {
        !           401:                pane_status = options_get_number(wo, "pane-border-status");
        !           402:                screen_redraw_draw_borders(c, status, pane_status, top);
        !           403:                if (pane_status != CELL_STATUS_OFF)
        !           404:                        screen_redraw_draw_pane_status(c, pane_status);
        !           405:        }
        !           406:        if (draw_panes)
        !           407:                screen_redraw_draw_panes(c, top);
        !           408:        if (draw_status)
        !           409:                screen_redraw_draw_status(c, top);
        !           410:        tty_reset(tty);
        !           411: }
        !           412: 
        !           413: /* Draw a single pane. */
        !           414: void
        !           415: screen_redraw_pane(struct client *c, struct window_pane *wp)
        !           416: {
        !           417:        u_int   i, yoff;
        !           418: 
        !           419:        if (!window_pane_visible(wp))
        !           420:                return;
        !           421: 
        !           422:        yoff = wp->yoff;
        !           423:        if (status_at_line(c) == 0)
        !           424:                yoff++;
        !           425: 
        !           426:        log_debug("%s: redraw pane %%%u (at %u,%u)", c->name, wp->id,
        !           427:            wp->xoff, yoff);
        !           428: 
        !           429:        for (i = 0; i < wp->sy; i++)
        !           430:                tty_draw_pane(&c->tty, wp, i, wp->xoff, yoff);
        !           431:        tty_reset(&c->tty);
        !           432: }
        !           433: 
        !           434: /* Draw the borders. */
        !           435: static void
        !           436: screen_redraw_draw_borders(struct client *c, int status, int pane_status,
        !           437:     u_int top)
        !           438: {
        !           439:        struct session          *s = c->session;
        !           440:        struct window           *w = s->curw->window;
        !           441:        struct options          *oo = w->options;
        !           442:        struct tty              *tty = &c->tty;
        !           443:        struct window_pane      *wp;
        !           444:        struct grid_cell         m_active_gc, active_gc, m_other_gc, other_gc;
        !           445:        struct grid_cell         msg_gc;
        !           446:        u_int                    i, j, type, msgx = 0, msgy = 0;
        !           447:        int                      active, small, flags;
        !           448:        char                     msg[256];
        !           449:        const char              *tmp;
        !           450:        size_t                   msglen = 0;
        !           451: 
        !           452:        small = (tty->sy - status + top > w->sy) || (tty->sx > w->sx);
        !           453:        if (small) {
        !           454:                flags = w->flags & (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT);
        !           455:                if (flags == (WINDOW_FORCEWIDTH|WINDOW_FORCEHEIGHT))
        !           456:                        tmp = "force-width, force-height";
        !           457:                else if (flags == WINDOW_FORCEWIDTH)
        !           458:                        tmp = "force-width";
        !           459:                else if (flags == WINDOW_FORCEHEIGHT)
        !           460:                        tmp = "force-height";
        !           461:                else
        !           462:                        tmp = "a smaller client";
        !           463:                xsnprintf(msg, sizeof msg, "(size %ux%u from %s)",
        !           464:                    w->sx, w->sy, tmp);
        !           465:                msglen = strlen(msg);
        !           466: 
        !           467:                if (tty->sy - 1 - status + top > w->sy && tty->sx >= msglen) {
        !           468:                        msgx = tty->sx - msglen;
        !           469:                        msgy = tty->sy - 1 - status + top;
        !           470:                } else if (tty->sx - w->sx > msglen) {
        !           471:                        msgx = tty->sx - msglen;
        !           472:                        msgy = tty->sy - 1 - status + top;
        !           473:                } else
        !           474:                        small = 0;
        !           475:        }
        !           476: 
        !           477:        style_apply(&other_gc, oo, "pane-border-style");
        !           478:        style_apply(&active_gc, oo, "pane-active-border-style");
        !           479:        active_gc.attr = other_gc.attr = GRID_ATTR_CHARSET;
        !           480: 
        !           481:        memcpy(&m_other_gc, &other_gc, sizeof m_other_gc);
        !           482:        m_other_gc.attr ^= GRID_ATTR_REVERSE;
        !           483:        memcpy(&m_active_gc, &active_gc, sizeof m_active_gc);
        !           484:        m_active_gc.attr ^= GRID_ATTR_REVERSE;
        !           485: 
        !           486:        for (j = 0; j < tty->sy - status; j++) {
        !           487:                for (i = 0; i < tty->sx; i++) {
        !           488:                        type = screen_redraw_check_cell(c, i, j, pane_status,
        !           489:                            &wp);
        !           490:                        if (type == CELL_INSIDE)
        !           491:                                continue;
        !           492:                        if (type == CELL_OUTSIDE && small &&
        !           493:                            i > msgx && j == msgy)
        !           494:                                continue;
        !           495:                        active = screen_redraw_check_is(i, j, type, pane_status,
        !           496:                            w, w->active, wp);
        !           497:                        if (server_is_marked(s, s->curw, marked_pane.wp) &&
        !           498:                            screen_redraw_check_is(i, j, type, pane_status, w,
        !           499:                            marked_pane.wp, wp)) {
        !           500:                                if (active)
        !           501:                                        tty_attributes(tty, &m_active_gc, NULL);
        !           502:                                else
        !           503:                                        tty_attributes(tty, &m_other_gc, NULL);
        !           504:                        } else if (active)
        !           505:                                tty_attributes(tty, &active_gc, NULL);
        !           506:                        else
        !           507:                                tty_attributes(tty, &other_gc, NULL);
        !           508:                        tty_cursor(tty, i, top + j);
        !           509:                        tty_putc(tty, CELL_BORDERS[type]);
        !           510:                }
        !           511:        }
        !           512: 
        !           513:        if (small) {
        !           514:                memcpy(&msg_gc, &grid_default_cell, sizeof msg_gc);
        !           515:                tty_attributes(tty, &msg_gc, NULL);
        !           516:                tty_cursor(tty, msgx, msgy);
        !           517:                tty_puts(tty, msg);
        !           518:        }
        !           519: }
        !           520: 
        !           521: /* Draw the panes. */
        !           522: static void
        !           523: screen_redraw_draw_panes(struct client *c, u_int top)
        !           524: {
        !           525:        struct window           *w = c->session->curw->window;
        !           526:        struct tty              *tty = &c->tty;
        !           527:        struct window_pane      *wp;
        !           528:        u_int                    i;
        !           529: 
        !           530:        TAILQ_FOREACH(wp, &w->panes, entry) {
        !           531:                if (!window_pane_visible(wp))
        !           532:                        continue;
        !           533:                for (i = 0; i < wp->sy; i++)
        !           534:                        tty_draw_pane(tty, wp, i, wp->xoff, top + wp->yoff);
        !           535:                if (c->flags & CLIENT_IDENTIFY)
        !           536:                        screen_redraw_draw_number(c, wp, top);
        !           537:        }
        !           538: }
        !           539: 
        !           540: /* Draw the status line. */
        !           541: static void
        !           542: screen_redraw_draw_status(struct client *c, u_int top)
        !           543: {
        !           544:        struct tty      *tty = &c->tty;
        !           545: 
        !           546:        if (top)
        !           547:                tty_draw_line(tty, NULL, &c->status, 0, 0, 0);
        !           548:        else
        !           549:                tty_draw_line(tty, NULL, &c->status, 0, 0, tty->sy - 1);
        !           550: }
        !           551: 
        !           552: /* Draw number on a pane. */
        !           553: static void
        !           554: screen_redraw_draw_number(struct client *c, struct window_pane *wp, u_int top)
        !           555: {
        !           556:        struct tty              *tty = &c->tty;
        !           557:        struct session          *s = c->session;
        !           558:        struct options          *oo = s->options;
        !           559:        struct window           *w = wp->window;
        !           560:        struct grid_cell         gc;
        !           561:        u_int                    idx, px, py, i, j, xoff, yoff;
        !           562:        int                      colour, active_colour;
        !           563:        char                     buf[16], *ptr;
        !           564:        size_t                   len;
        !           565: 
        !           566:        if (window_pane_index(wp, &idx) != 0)
        !           567:                fatalx("index not found");
        !           568:        len = xsnprintf(buf, sizeof buf, "%u", idx);
        !           569: 
        !           570:        if (wp->sx < len)
        !           571:                return;
        !           572:        colour = options_get_number(oo, "display-panes-colour");
        !           573:        active_colour = options_get_number(oo, "display-panes-active-colour");
        !           574: 
        !           575:        px = wp->sx / 2; py = wp->sy / 2;
        !           576:        xoff = wp->xoff; yoff = wp->yoff;
        !           577: 
        !           578:        if (top)
        !           579:                yoff++;
        !           580: 
        !           581:        if (wp->sx < len * 6 || wp->sy < 5) {
        !           582:                tty_cursor(tty, xoff + px - len / 2, yoff + py);
        !           583:                goto draw_text;
        !           584:        }
        !           585: 
        !           586:        px -= len * 3;
        !           587:        py -= 2;
        !           588: 
        !           589:        memcpy(&gc, &grid_default_cell, sizeof gc);
        !           590:        if (w->active == wp)
        !           591:                gc.bg = active_colour;
        !           592:        else
        !           593:                gc.bg = colour;
        !           594:        gc.flags |= GRID_FLAG_NOPALETTE;
        !           595: 
        !           596:        tty_attributes(tty, &gc, wp);
        !           597:        for (ptr = buf; *ptr != '\0'; ptr++) {
        !           598:                if (*ptr < '0' || *ptr > '9')
        !           599:                        continue;
        !           600:                idx = *ptr - '0';
        !           601: 
        !           602:                for (j = 0; j < 5; j++) {
        !           603:                        for (i = px; i < px + 5; i++) {
        !           604:                                tty_cursor(tty, xoff + i, yoff + py + j);
        !           605:                                if (window_clock_table[idx][j][i - px])
        !           606:                                        tty_putc(tty, ' ');
        !           607:                        }
        !           608:                }
        !           609:                px += 6;
        !           610:        }
        !           611: 
        !           612:        len = xsnprintf(buf, sizeof buf, "%ux%u", wp->sx, wp->sy);
        !           613:        if (wp->sx < len || wp->sy < 6)
        !           614:                return;
        !           615:        tty_cursor(tty, xoff + wp->sx - len, yoff);
        !           616: 
        !           617: draw_text:
        !           618:        memcpy(&gc, &grid_default_cell, sizeof gc);
        !           619:        if (w->active == wp)
        !           620:                gc.fg = active_colour;
        !           621:        else
        !           622:                gc.fg = colour;
        !           623:        gc.flags |= GRID_FLAG_NOPALETTE;
        !           624: 
        !           625:        tty_attributes(tty, &gc, wp);
        !           626:        tty_puts(tty, buf);
        !           627: 
        !           628:        tty_cursor(tty, 0, 0);
        !           629: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>