[BACK]Return to screen-write.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/screen-write.c, Revision 1.39

1.39    ! nicm        1: /* $OpenBSD: screen-write.c,v 1.38 2009/11/16 13:40:45 nicm Exp $ */
1.1       nicm        2:
                      3: /*
                      4:  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net>
                      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:
1.31      nicm       25: void   screen_write_initctx(struct screen_write_ctx *, struct tty_ctx *, int);
1.1       nicm       26: void   screen_write_overwrite(struct screen_write_ctx *);
1.36      nicm       27: int    screen_write_combine(
                     28:            struct screen_write_ctx *, const struct utf8_data *);
1.1       nicm       29:
                     30: /* Initialise writing with a window. */
                     31: void
                     32: screen_write_start(
                     33:     struct screen_write_ctx *ctx, struct window_pane *wp, struct screen *s)
                     34: {
                     35:        ctx->wp = wp;
                     36:        if (wp != NULL && s == NULL)
                     37:                ctx->s = wp->screen;
                     38:        else
                     39:                ctx->s = s;
                     40: }
                     41:
                     42: /* Finish writing. */
                     43: void
                     44: screen_write_stop(unused struct screen_write_ctx *ctx)
                     45: {
                     46: }
                     47:
                     48: /* Write character. */
                     49: void
                     50: screen_write_putc(
                     51:     struct screen_write_ctx *ctx, struct grid_cell *gc, u_char ch)
                     52: {
                     53:        gc->data = ch;
                     54:        screen_write_cell(ctx, gc, NULL);
                     55: }
                     56:
1.24      nicm       57: /* Calculate string length, with embedded formatting. */
                     58: size_t printflike2
                     59: screen_write_cstrlen(int utf8flag, const char *fmt, ...)
                     60: {
                     61:        va_list ap;
                     62:        char   *msg, *msg2, *ptr, *ptr2;
                     63:        size_t  size;
                     64:
                     65:        va_start(ap, fmt);
                     66:        xvasprintf(&msg, fmt, ap);
                     67:        va_end(ap);
                     68:        msg2 = xmalloc(strlen(msg) + 1);
                     69:
                     70:        ptr = msg;
                     71:        ptr2 = msg2;
                     72:        while (*ptr != '\0') {
                     73:                if (ptr[0] == '#' && ptr[1] == '[') {
                     74:                        while (*ptr != ']' && *ptr != '\0')
                     75:                                ptr++;
                     76:                        if (*ptr == ']')
                     77:                                ptr++;
                     78:                        continue;
                     79:                }
                     80:                *ptr2++ = *ptr++;
                     81:        }
                     82:        *ptr2 = '\0';
                     83:
                     84:        size = screen_write_strlen(utf8flag, "%s", msg2);
                     85:
                     86:        xfree(msg);
                     87:        xfree(msg2);
                     88:
                     89:        return (size);
                     90: }
                     91:
1.2       nicm       92: /* Calculate string length. */
1.3       nicm       93: size_t printflike2
                     94: screen_write_strlen(int utf8flag, const char *fmt, ...)
1.2       nicm       95: {
1.36      nicm       96:        va_list                 ap;
                     97:        char                   *msg;
                     98:        struct utf8_data        utf8data;
                     99:        u_char                 *ptr;
                    100:        size_t                  left, size = 0;
1.2       nicm      101:
                    102:        va_start(ap, fmt);
                    103:        xvasprintf(&msg, fmt, ap);
                    104:        va_end(ap);
                    105:
                    106:        ptr = msg;
                    107:        while (*ptr != '\0') {
1.36      nicm      108:                if (utf8flag && *ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
                    109:                        ptr++;
1.2       nicm      110:
                    111:                        left = strlen(ptr);
1.36      nicm      112:                        if (left < utf8data.size - 1)
                    113:                                break;
                    114:                        while (utf8_append(&utf8data, *ptr))
1.2       nicm      115:                                ptr++;
1.36      nicm      116:                        ptr++;
                    117:
                    118:                        size += utf8data.width;
1.2       nicm      119:                } else {
                    120:                        size++;
                    121:                        ptr++;
                    122:                }
1.7       ray       123:        }
1.2       nicm      124:
1.19      nicm      125:        xfree(msg);
1.2       nicm      126:        return (size);
                    127: }
                    128:
1.3       nicm      129: /* Write simple string (no UTF-8 or maximum length). */
1.1       nicm      130: void printflike3
                    131: screen_write_puts(
                    132:     struct screen_write_ctx *ctx, struct grid_cell *gc, const char *fmt, ...)
                    133: {
                    134:        va_list ap;
                    135:
                    136:        va_start(ap, fmt);
1.3       nicm      137:        screen_write_vnputs(ctx, -1, gc, 0, fmt, ap);
1.2       nicm      138:        va_end(ap);
                    139: }
                    140:
                    141: /* Write string with length limit (-1 for unlimited). */
1.3       nicm      142: void printflike5
1.2       nicm      143: screen_write_nputs(struct screen_write_ctx *ctx,
1.3       nicm      144:     ssize_t maxlen, struct grid_cell *gc, int utf8flag, const char *fmt, ...)
1.2       nicm      145: {
                    146:        va_list ap;
                    147:
                    148:        va_start(ap, fmt);
1.3       nicm      149:        screen_write_vnputs(ctx, maxlen, gc, utf8flag, fmt, ap);
1.2       nicm      150:        va_end(ap);
                    151: }
                    152:
                    153: void
1.3       nicm      154: screen_write_vnputs(struct screen_write_ctx *ctx, ssize_t maxlen,
                    155:     struct grid_cell *gc, int utf8flag, const char *fmt, va_list ap)
1.2       nicm      156: {
1.36      nicm      157:        char                   *msg;
                    158:        struct utf8_data        utf8data;
                    159:        u_char                 *ptr;
                    160:        size_t                  left, size = 0;
1.2       nicm      161:
1.1       nicm      162:        xvasprintf(&msg, fmt, ap);
                    163:
1.2       nicm      164:        ptr = msg;
                    165:        while (*ptr != '\0') {
1.36      nicm      166:                if (utf8flag && *ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
                    167:                        ptr++;
1.2       nicm      168:
                    169:                        left = strlen(ptr);
1.36      nicm      170:                        if (left < utf8data.size - 1)
                    171:                                break;
                    172:                        while (utf8_append(&utf8data, *ptr))
1.2       nicm      173:                                ptr++;
1.36      nicm      174:                        ptr++;
1.7       ray       175:
1.36      nicm      176:                        if (maxlen > 0 &&
                    177:                            size + utf8data.width > (size_t) maxlen) {
1.2       nicm      178:                                while (size < (size_t) maxlen) {
                    179:                                        screen_write_putc(ctx, gc, ' ');
                    180:                                        size++;
                    181:                                }
                    182:                                break;
                    183:                        }
1.36      nicm      184:                        size += utf8data.width;
                    185:
1.2       nicm      186:                        gc->flags |= GRID_FLAG_UTF8;
1.36      nicm      187:                        screen_write_cell(ctx, gc, &utf8data);
1.2       nicm      188:                        gc->flags &= ~GRID_FLAG_UTF8;
                    189:                } else {
1.8       nicm      190:                        if (maxlen > 0 && size + 1 > (size_t) maxlen)
1.2       nicm      191:                                break;
                    192:
                    193:                        size++;
                    194:                        screen_write_putc(ctx, gc, *ptr);
                    195:                        ptr++;
                    196:                }
                    197:        }
1.1       nicm      198:
                    199:        xfree(msg);
1.24      nicm      200: }
                    201:
                    202: /* Write string, similar to nputs, but with embedded formatting (#[]). */
                    203: void printflike5
                    204: screen_write_cnputs(struct screen_write_ctx *ctx,
                    205:     ssize_t maxlen, struct grid_cell *gc, int utf8flag, const char *fmt, ...)
                    206: {
                    207:        struct grid_cell         lgc;
1.36      nicm      208:        struct utf8_data         utf8data;
1.24      nicm      209:        va_list                  ap;
                    210:        char                    *msg;
1.36      nicm      211:        u_char                  *ptr, *last;
1.24      nicm      212:        size_t                   left, size = 0;
                    213:
                    214:        va_start(ap, fmt);
                    215:        xvasprintf(&msg, fmt, ap);
                    216:        va_end(ap);
                    217:
                    218:        memcpy(&lgc, gc, sizeof lgc);
                    219:
                    220:        ptr = msg;
                    221:        while (*ptr != '\0') {
                    222:                if (ptr[0] == '#' && ptr[1] == '[') {
                    223:                        ptr += 2;
                    224:                        last = ptr + strcspn(ptr, "]");
                    225:                        if (*last == '\0') {
                    226:                                /* No ]. Not much point in doing anything. */
                    227:                                break;
                    228:                        }
                    229:                        *last = '\0';
                    230:
                    231:                        screen_write_parsestyle(gc, &lgc, ptr);
                    232:                        ptr = last + 1;
                    233:                        continue;
                    234:                }
                    235:
1.36      nicm      236:                if (utf8flag && *ptr > 0x7f && utf8_open(&utf8data, *ptr)) {
                    237:                        ptr++;
1.24      nicm      238:
                    239:                        left = strlen(ptr);
1.36      nicm      240:                        if (left < utf8data.size - 1)
                    241:                                break;
                    242:                        while (utf8_append(&utf8data, *ptr))
1.24      nicm      243:                                ptr++;
1.36      nicm      244:                        ptr++;
1.24      nicm      245:
1.36      nicm      246:                        if (maxlen > 0 &&
                    247:                            size + utf8data.width > (size_t) maxlen) {
1.24      nicm      248:                                while (size < (size_t) maxlen) {
                    249:                                        screen_write_putc(ctx, gc, ' ');
                    250:                                        size++;
                    251:                                }
                    252:                                break;
                    253:                        }
1.36      nicm      254:                        size += utf8data.width;
1.24      nicm      255:
                    256:                        lgc.flags |= GRID_FLAG_UTF8;
1.36      nicm      257:                        screen_write_cell(ctx, &lgc, &utf8data);
1.24      nicm      258:                        lgc.flags &= ~GRID_FLAG_UTF8;
                    259:                } else {
                    260:                        if (maxlen > 0 && size + 1 > (size_t) maxlen)
                    261:                                break;
                    262:
                    263:                        size++;
                    264:                        screen_write_putc(ctx, &lgc, *ptr);
                    265:                        ptr++;
                    266:                }
                    267:        }
                    268:
                    269:        xfree(msg);
                    270: }
                    271:
                    272: /* Parse an embedded style of the form "fg=colour,bg=colour,bright,...". */
                    273: void
                    274: screen_write_parsestyle(
                    275:     struct grid_cell *defgc, struct grid_cell *gc, const char *in)
                    276: {
                    277:        const char      delimiters[] = " ,";
                    278:        char            tmp[32];
                    279:        int             val;
                    280:        size_t          end;
1.25      nicm      281:        u_char          fg, bg, attr, flags;
1.24      nicm      282:
                    283:        if (*in == '\0')
                    284:                return;
                    285:        if (strchr(delimiters, in[strlen(in) - 1]) != NULL)
                    286:                return;
                    287:
                    288:        fg = gc->fg;
                    289:        bg = gc->bg;
1.25      nicm      290:        attr = gc->attr;
                    291:        flags = gc->flags;
1.24      nicm      292:        do {
                    293:                end = strcspn(in, delimiters);
                    294:                if (end > (sizeof tmp) - 1)
                    295:                        return;
                    296:                memcpy(tmp, in, end);
                    297:                tmp[end] = '\0';
                    298:
                    299:                if (strcasecmp(tmp, "default") == 0) {
                    300:                        fg = defgc->fg;
                    301:                        bg = defgc->bg;
                    302:                        attr = defgc->attr;
                    303:                } else if (end > 3 && strncasecmp(tmp + 1, "g=", 2) == 0) {
                    304:                        if ((val = colour_fromstring(tmp + 3)) == -1)
                    305:                                return;
                    306:                        if (*in == 'f' || *in == 'F') {
1.25      nicm      307:                                if (val != 8) {
                    308:                                        if (val & 0x100) {
                    309:                                                flags |= GRID_FLAG_FG256;
                    310:                                                val &= ~0x100;
                    311:                                        } else
                    312:                                                flags &= ~GRID_FLAG_FG256;
1.24      nicm      313:                                        fg = val;
1.25      nicm      314:                                } else
1.24      nicm      315:                                        fg = defgc->fg;
                    316:                        } else if (*in == 'b' || *in == 'B') {
1.25      nicm      317:                                if (val != 8) {
                    318:                                        if (val & 0x100) {
                    319:                                                flags |= GRID_FLAG_BG256;
                    320:                                                val &= ~0x100;
                    321:                                        } else
                    322:                                                flags &= ~GRID_FLAG_BG256;
1.24      nicm      323:                                        bg = val;
1.25      nicm      324:                                } else
1.24      nicm      325:                                        bg = defgc->bg;
                    326:                        } else
                    327:                                return;
1.27      nicm      328:                } else if (end > 2 && strncasecmp(tmp, "no", 2) == 0) {
                    329:                        if ((val = attributes_fromstring(tmp + 2)) == -1)
                    330:                                return;
                    331:                        attr &= ~val;
1.24      nicm      332:                } else {
                    333:                        if ((val = attributes_fromstring(tmp)) == -1)
                    334:                                return;
                    335:                        attr |= val;
                    336:                }
                    337:
                    338:                in += end + strspn(in + end, delimiters);
                    339:        } while (*in != '\0');
                    340:        gc->fg = fg;
                    341:        gc->bg = bg;
                    342:        gc->attr = attr;
1.25      nicm      343:        gc->flags = flags;
1.1       nicm      344: }
                    345:
                    346: /* Copy from another screen. */
                    347: void
                    348: screen_write_copy(struct screen_write_ctx *ctx,
                    349:     struct screen *src, u_int px, u_int py, u_int nx, u_int ny)
                    350: {
                    351:        struct screen           *s = ctx->s;
                    352:        struct grid             *gd = src->grid;
1.21      nicm      353:        struct grid_line        *gl;
1.1       nicm      354:        const struct grid_cell  *gc;
1.36      nicm      355:        const struct grid_utf8  *gu;
                    356:        struct utf8_data         utf8data;
1.39    ! nicm      357:        u_int                    xx, yy, cx, cy, ax, bx;
1.1       nicm      358:
                    359:        cx = s->cx;
                    360:        cy = s->cy;
                    361:        for (yy = py; yy < py + ny; yy++) {
1.21      nicm      362:                gl = &gd->linedata[yy];
1.26      nicm      363:                if (yy < gd->hsize + gd->sy) {
                    364:                        /*
                    365:                         * Find start and end position and copy between
                    366:                         * them. Limit to the real end of the line then use a
                    367:                         * clear EOL only if copying to the end, otherwise
                    368:                         * could overwrite whatever is there already.
                    369:                         */
                    370:                        if (px > gl->cellsize)
                    371:                                ax = gl->cellsize;
                    372:                        else
                    373:                                ax = px;
                    374:                        if (px + nx == gd->sx && px + nx > gl->cellsize)
                    375:                                bx = gl->cellsize;
                    376:                        else
                    377:                                bx = px + nx;
1.36      nicm      378:
1.26      nicm      379:                        for (xx = ax; xx < bx; xx++) {
                    380:                                if (xx >= gl->cellsize)
                    381:                                        gc = &grid_default_cell;
1.36      nicm      382:                                else
1.26      nicm      383:                                        gc = &gl->celldata[xx];
1.39    ! nicm      384:                                if (!(gc->flags & GRID_FLAG_UTF8)) {
        !           385:                                        screen_write_cell(ctx, gc, NULL);
        !           386:                                        continue;
1.26      nicm      387:                                }
1.39    ! nicm      388:                                /* Reinject the UTF-8 sequence. */
        !           389:                                gu = &gl->utf8data[xx];
        !           390:                                utf8data.size = grid_utf8_copy(
        !           391:                                    gu, utf8data.data, sizeof utf8data.data);
        !           392:                                utf8data.width = gu->width;
1.36      nicm      393:                                screen_write_cell(ctx, gc, &utf8data);
1.1       nicm      394:                        }
1.26      nicm      395:                        if (px + nx == gd->sx && px + nx > gl->cellsize)
                    396:                                screen_write_clearendofline(ctx);
                    397:                } else
1.36      nicm      398:                        screen_write_clearline(ctx);
1.1       nicm      399:                cy++;
                    400:                screen_write_cursormove(ctx, cx, cy);
                    401:        }
                    402: }
                    403:
1.17      nicm      404: /* Set up context for TTY command. */
1.1       nicm      405: void
1.31      nicm      406: screen_write_initctx(
                    407:     struct screen_write_ctx *ctx, struct tty_ctx *ttyctx, int save_last)
1.1       nicm      408: {
1.31      nicm      409:        struct screen           *s = ctx->s;
                    410:        struct grid             *gd = s->grid;
                    411:        const struct grid_cell  *gc;
                    412:        const struct grid_utf8  *gu;
                    413:        u_int                    xx;
1.1       nicm      414:
1.17      nicm      415:        ttyctx->wp = ctx->wp;
1.1       nicm      416:
1.17      nicm      417:        ttyctx->ocx = s->cx;
                    418:        ttyctx->ocy = s->cy;
                    419:
                    420:        ttyctx->orlower = s->rlower;
                    421:        ttyctx->orupper = s->rupper;
1.31      nicm      422:
                    423:        if (!save_last)
                    424:                return;
                    425:
                    426:        /* Save the last cell on the screen. */
1.38      nicm      427:        gc = &grid_default_cell;
                    428:        for (xx = 1; xx <= screen_size_x(s); xx++) {
1.31      nicm      429:                gc = grid_view_peek_cell(gd, screen_size_x(s) - xx, s->cy);
                    430:                if (!(gc->flags & GRID_FLAG_PADDING))
                    431:                        break;
                    432:        }
                    433:        ttyctx->last_width = xx;
                    434:        memcpy(&ttyctx->last_cell, gc, sizeof ttyctx->last_cell);
                    435:        if (gc->flags & GRID_FLAG_UTF8) {
                    436:                gu = grid_view_peek_utf8(gd, screen_size_x(s) - xx, s->cy);
                    437:                memcpy(&ttyctx->last_utf8, gu, sizeof ttyctx->last_utf8);
                    438:        }
1.1       nicm      439: }
                    440:
                    441: /* Cursor up by ny. */
                    442: void
                    443: screen_write_cursorup(struct screen_write_ctx *ctx, u_int ny)
                    444: {
                    445:        struct screen   *s = ctx->s;
                    446:
                    447:        if (ny == 0)
                    448:                ny = 1;
                    449:
1.12      nicm      450:        if (s->cy < s->rupper) {
                    451:                /* Above region. */
                    452:                if (ny > s->cy)
                    453:                        ny = s->cy;
                    454:        } else {
                    455:                /* Below region. */
                    456:                if (ny > s->cy - s->rupper)
                    457:                        ny = s->cy - s->rupper;
                    458:        }
1.1       nicm      459:        if (ny == 0)
                    460:                return;
                    461:
                    462:        s->cy -= ny;
                    463: }
                    464:
                    465: /* Cursor down by ny. */
                    466: void
                    467: screen_write_cursordown(struct screen_write_ctx *ctx, u_int ny)
                    468: {
                    469:        struct screen   *s = ctx->s;
                    470:
                    471:        if (ny == 0)
                    472:                ny = 1;
                    473:
1.12      nicm      474:        if (s->cy > s->rlower) {
                    475:                /* Below region. */
                    476:                if (ny > screen_size_y(s) - 1 - s->cy)
                    477:                        ny = screen_size_y(s) - 1 - s->cy;
                    478:        } else {
                    479:                /* Above region. */
                    480:                if (ny > s->rlower - s->cy)
                    481:                        ny = s->rlower - s->cy;
                    482:        }
1.1       nicm      483:        if (ny == 0)
                    484:                return;
                    485:
                    486:        s->cy += ny;
                    487: }
                    488:
                    489: /* Cursor right by nx.  */
                    490: void
                    491: screen_write_cursorright(struct screen_write_ctx *ctx, u_int nx)
                    492: {
                    493:        struct screen   *s = ctx->s;
                    494:
                    495:        if (nx == 0)
                    496:                nx = 1;
                    497:
                    498:        if (nx > screen_size_x(s) - 1 - s->cx)
                    499:                nx = screen_size_x(s) - 1 - s->cx;
                    500:        if (nx == 0)
                    501:                return;
                    502:
                    503:        s->cx += nx;
                    504: }
                    505:
                    506: /* Cursor left by nx. */
                    507: void
                    508: screen_write_cursorleft(struct screen_write_ctx *ctx, u_int nx)
                    509: {
                    510:        struct screen   *s = ctx->s;
                    511:
                    512:        if (nx == 0)
                    513:                nx = 1;
                    514:
                    515:        if (nx > s->cx)
                    516:                nx = s->cx;
                    517:        if (nx == 0)
                    518:                return;
                    519:
                    520:        s->cx -= nx;
1.5       nicm      521: }
                    522:
1.29      nicm      523: /* Backspace; cursor left unless at start of wrapped line when can move up. */
                    524: void
                    525: screen_write_backspace(struct screen_write_ctx *ctx)
                    526: {
                    527:        struct screen           *s = ctx->s;
                    528:        struct grid_line        *gl;
                    529:
                    530:        if (s->cx == 0) {
                    531:                if (s->cy == 0)
                    532:                        return;
                    533:                gl = &s->grid->linedata[s->grid->hsize + s->cy - 1];
                    534:                if (gl->flags & GRID_LINE_WRAPPED) {
                    535:                        s->cy--;
                    536:                        s->cx = screen_size_x(s) - 1;
                    537:                }
                    538:        } else
                    539:                s->cx--;
                    540: }
                    541:
1.5       nicm      542: /* VT100 alignment test. */
                    543: void
                    544: screen_write_alignmenttest(struct screen_write_ctx *ctx)
                    545: {
                    546:        struct screen           *s = ctx->s;
1.17      nicm      547:        struct tty_ctx           ttyctx;
1.5       nicm      548:        struct grid_cell         gc;
                    549:        u_int                    xx, yy;
                    550:
1.31      nicm      551:        screen_write_initctx(ctx, &ttyctx, 0);
1.17      nicm      552:
1.5       nicm      553:        memcpy(&gc, &grid_default_cell, sizeof gc);
                    554:        gc.data = 'E';
1.7       ray       555:
1.5       nicm      556:        for (yy = 0; yy < screen_size_y(s); yy++) {
                    557:                for (xx = 0; xx < screen_size_x(s); xx++)
                    558:                        grid_view_set_cell(s->grid, xx, yy, &gc);
                    559:        }
1.7       ray       560:
1.5       nicm      561:        s->cx = 0;
                    562:        s->cy = 0;
                    563:
                    564:        s->rupper = 0;
1.29      nicm      565:
1.5       nicm      566:        s->rlower = screen_size_y(s) - 1;
                    567:
1.17      nicm      568:        tty_write(tty_cmd_alignmenttest, &ttyctx);
1.1       nicm      569: }
                    570:
                    571: /* Insert nx characters. */
                    572: void
                    573: screen_write_insertcharacter(struct screen_write_ctx *ctx, u_int nx)
                    574: {
                    575:        struct screen   *s = ctx->s;
1.17      nicm      576:        struct tty_ctx   ttyctx;
1.1       nicm      577:
                    578:        if (nx == 0)
                    579:                nx = 1;
                    580:
1.9       nicm      581:        if (nx > screen_size_x(s) - s->cx)
                    582:                nx = screen_size_x(s) - s->cx;
1.1       nicm      583:        if (nx == 0)
                    584:                return;
                    585:
1.31      nicm      586:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      587:
                    588:        if (s->cx <= screen_size_x(s) - 1)
                    589:                grid_view_insert_cells(s->grid, s->cx, s->cy, nx);
                    590:
1.17      nicm      591:        ttyctx.num = nx;
                    592:        tty_write(tty_cmd_insertcharacter, &ttyctx);
1.1       nicm      593: }
                    594:
                    595: /* Delete nx characters. */
                    596: void
                    597: screen_write_deletecharacter(struct screen_write_ctx *ctx, u_int nx)
                    598: {
                    599:        struct screen   *s = ctx->s;
1.17      nicm      600:        struct tty_ctx   ttyctx;
1.1       nicm      601:
                    602:        if (nx == 0)
                    603:                nx = 1;
                    604:
1.9       nicm      605:        if (nx > screen_size_x(s) - s->cx)
                    606:                nx = screen_size_x(s) - s->cx;
1.1       nicm      607:        if (nx == 0)
                    608:                return;
                    609:
1.31      nicm      610:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      611:
                    612:        if (s->cx <= screen_size_x(s) - 1)
                    613:                grid_view_delete_cells(s->grid, s->cx, s->cy, nx);
                    614:
1.17      nicm      615:        ttyctx.num = nx;
                    616:        tty_write(tty_cmd_deletecharacter, &ttyctx);
1.1       nicm      617: }
                    618:
                    619: /* Insert ny lines. */
                    620: void
                    621: screen_write_insertline(struct screen_write_ctx *ctx, u_int ny)
                    622: {
                    623:        struct screen   *s = ctx->s;
1.17      nicm      624:        struct tty_ctx   ttyctx;
1.1       nicm      625:
                    626:        if (ny == 0)
                    627:                ny = 1;
                    628:
1.11      nicm      629:        if (s->cy < s->rupper || s->cy > s->rlower) {
                    630:                if (ny > screen_size_y(s) - s->cy)
                    631:                        ny = screen_size_y(s) - s->cy;
                    632:                if (ny == 0)
                    633:                        return;
                    634:
1.31      nicm      635:                screen_write_initctx(ctx, &ttyctx, 0);
1.11      nicm      636:
                    637:                grid_view_insert_lines(s->grid, s->cy, ny);
                    638:
1.17      nicm      639:                ttyctx.num = ny;
                    640:                tty_write(tty_cmd_insertline, &ttyctx);
1.11      nicm      641:                return;
                    642:        }
                    643:
                    644:        if (ny > s->rlower + 1 - s->cy)
                    645:                ny = s->rlower + 1 - s->cy;
1.1       nicm      646:        if (ny == 0)
                    647:                return;
1.11      nicm      648:
1.31      nicm      649:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      650:
                    651:        if (s->cy < s->rupper || s->cy > s->rlower)
                    652:                grid_view_insert_lines(s->grid, s->cy, ny);
1.10      nicm      653:        else
                    654:                grid_view_insert_lines_region(s->grid, s->rlower, s->cy, ny);
1.1       nicm      655:
1.17      nicm      656:        ttyctx.num = ny;
                    657:        tty_write(tty_cmd_insertline, &ttyctx);
1.1       nicm      658: }
                    659:
                    660: /* Delete ny lines. */
                    661: void
                    662: screen_write_deleteline(struct screen_write_ctx *ctx, u_int ny)
                    663: {
                    664:        struct screen   *s = ctx->s;
1.17      nicm      665:        struct tty_ctx   ttyctx;
1.1       nicm      666:
                    667:        if (ny == 0)
                    668:                ny = 1;
                    669:
1.11      nicm      670:        if (s->cy < s->rupper || s->cy > s->rlower) {
                    671:                if (ny > screen_size_y(s) - s->cy)
                    672:                        ny = screen_size_y(s) - s->cy;
                    673:                if (ny == 0)
                    674:                        return;
                    675:
1.31      nicm      676:                screen_write_initctx(ctx, &ttyctx, 0);
1.11      nicm      677:
                    678:                grid_view_delete_lines(s->grid, s->cy, ny);
                    679:
1.17      nicm      680:                ttyctx.num = ny;
                    681:                tty_write(tty_cmd_deleteline, &ttyctx);
1.11      nicm      682:                return;
                    683:        }
                    684:
                    685:        if (ny > s->rlower + 1 - s->cy)
                    686:                ny = s->rlower + 1 - s->cy;
1.1       nicm      687:        if (ny == 0)
                    688:                return;
                    689:
1.31      nicm      690:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      691:
                    692:        if (s->cy < s->rupper || s->cy > s->rlower)
                    693:                grid_view_delete_lines(s->grid, s->cy, ny);
1.10      nicm      694:        else
                    695:                grid_view_delete_lines_region(s->grid, s->rlower, s->cy, ny);
1.1       nicm      696:
1.17      nicm      697:        ttyctx.num = ny;
                    698:        tty_write(tty_cmd_deleteline, &ttyctx);
1.1       nicm      699: }
                    700:
                    701: /* Clear line at cursor. */
                    702: void
                    703: screen_write_clearline(struct screen_write_ctx *ctx)
                    704: {
                    705:        struct screen   *s = ctx->s;
1.17      nicm      706:        struct tty_ctx   ttyctx;
1.1       nicm      707:
1.31      nicm      708:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      709:
                    710:        grid_view_clear(s->grid, 0, s->cy, screen_size_x(s), 1);
                    711:
1.17      nicm      712:        tty_write(tty_cmd_clearline, &ttyctx);
1.1       nicm      713: }
                    714:
                    715: /* Clear to end of line from cursor. */
                    716: void
                    717: screen_write_clearendofline(struct screen_write_ctx *ctx)
                    718: {
                    719:        struct screen   *s = ctx->s;
1.17      nicm      720:        struct tty_ctx   ttyctx;
1.1       nicm      721:        u_int            sx;
                    722:
1.31      nicm      723:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      724:
                    725:        sx = screen_size_x(s);
                    726:
                    727:        if (s->cx <= sx - 1)
                    728:                grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
                    729:
1.17      nicm      730:        tty_write(tty_cmd_clearendofline, &ttyctx);
1.1       nicm      731: }
                    732:
                    733: /* Clear to start of line from cursor. */
                    734: void
                    735: screen_write_clearstartofline(struct screen_write_ctx *ctx)
                    736: {
                    737:        struct screen   *s = ctx->s;
1.17      nicm      738:        struct tty_ctx   ttyctx;
1.1       nicm      739:        u_int            sx;
                    740:
1.31      nicm      741:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      742:
                    743:        sx = screen_size_x(s);
                    744:
                    745:        if (s->cx > sx - 1)
                    746:                grid_view_clear(s->grid, 0, s->cy, sx, 1);
                    747:        else
                    748:                grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
                    749:
1.17      nicm      750:        tty_write(tty_cmd_clearstartofline, &ttyctx);
1.1       nicm      751: }
                    752:
                    753: /* Move cursor to px,py.  */
                    754: void
                    755: screen_write_cursormove(struct screen_write_ctx *ctx, u_int px, u_int py)
                    756: {
                    757:        struct screen   *s = ctx->s;
                    758:
                    759:        if (px > screen_size_x(s) - 1)
                    760:                px = screen_size_x(s) - 1;
                    761:        if (py > screen_size_y(s) - 1)
                    762:                py = screen_size_y(s) - 1;
                    763:
                    764:        s->cx = px;
                    765:        s->cy = py;
                    766: }
                    767:
                    768: /* Set cursor mode. */
                    769: void
                    770: screen_write_cursormode(struct screen_write_ctx *ctx, int state)
                    771: {
                    772:        struct screen   *s = ctx->s;
                    773:
                    774:        if (state)
                    775:                s->mode |= MODE_CURSOR;
                    776:        else
                    777:                s->mode &= ~MODE_CURSOR;
                    778: }
                    779:
                    780: /* Reverse index (up with scroll).  */
                    781: void
                    782: screen_write_reverseindex(struct screen_write_ctx *ctx)
                    783: {
                    784:        struct screen   *s = ctx->s;
1.17      nicm      785:        struct tty_ctx   ttyctx;
1.1       nicm      786:
1.31      nicm      787:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      788:
                    789:        if (s->cy == s->rupper)
                    790:                grid_view_scroll_region_down(s->grid, s->rupper, s->rlower);
                    791:        else if (s->cy > 0)
                    792:                s->cy--;
                    793:
1.17      nicm      794:        tty_write(tty_cmd_reverseindex, &ttyctx);
1.1       nicm      795: }
                    796:
                    797: /* Set scroll region. */
                    798: void
                    799: screen_write_scrollregion(
                    800:     struct screen_write_ctx *ctx, u_int rupper, u_int rlower)
                    801: {
                    802:        struct screen   *s = ctx->s;
                    803:
                    804:        if (rupper > screen_size_y(s) - 1)
                    805:                rupper = screen_size_y(s) - 1;
                    806:        if (rlower > screen_size_y(s) - 1)
                    807:                rlower = screen_size_y(s) - 1;
1.13      nicm      808:        if (rupper >= rlower)   /* cannot be one line */
1.1       nicm      809:                return;
                    810:
                    811:        /* Cursor moves to top-left. */
                    812:        s->cx = 0;
                    813:        s->cy = 0;
                    814:
                    815:        s->rupper = rupper;
                    816:        s->rlower = rlower;
                    817: }
                    818:
                    819: /* Set insert mode. */
                    820: void
                    821: screen_write_insertmode(struct screen_write_ctx *ctx, int state)
                    822: {
                    823:        struct screen   *s = ctx->s;
                    824:
                    825:        if (state)
                    826:                s->mode |= MODE_INSERT;
                    827:        else
                    828:                s->mode &= ~MODE_INSERT;
                    829: }
                    830:
                    831: /* Set mouse mode.  */
                    832: void
                    833: screen_write_mousemode(struct screen_write_ctx *ctx, int state)
                    834: {
                    835:        struct screen   *s = ctx->s;
                    836:
                    837:        if (state)
                    838:                s->mode |= MODE_MOUSE;
                    839:        else
                    840:                s->mode &= ~MODE_MOUSE;
                    841: }
                    842:
1.34      nicm      843: /* Line feed. */
1.1       nicm      844: void
1.34      nicm      845: screen_write_linefeed(struct screen_write_ctx *ctx, int wrapped)
1.1       nicm      846: {
1.20      nicm      847:        struct screen           *s = ctx->s;
                    848:        struct grid_line        *gl;
1.34      nicm      849:        struct tty_ctx           ttyctx;
                    850:
                    851:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      852:
1.20      nicm      853:        gl = &s->grid->linedata[s->grid->hsize + s->cy];
                    854:        if (wrapped)
                    855:                gl->flags |= GRID_LINE_WRAPPED;
                    856:        else
                    857:                gl->flags &= ~GRID_LINE_WRAPPED;
                    858:
1.1       nicm      859:        if (s->cy == s->rlower)
                    860:                grid_view_scroll_region_up(s->grid, s->rupper, s->rlower);
                    861:        else if (s->cy < screen_size_y(s) - 1)
                    862:                s->cy++;
                    863:
1.34      nicm      864:        ttyctx.num = wrapped;
1.17      nicm      865:        tty_write(tty_cmd_linefeed, &ttyctx);
1.1       nicm      866: }
                    867:
                    868: /* Carriage return (cursor to start of line). */
                    869: void
                    870: screen_write_carriagereturn(struct screen_write_ctx *ctx)
                    871: {
                    872:        struct screen   *s = ctx->s;
                    873:
                    874:        s->cx = 0;
                    875: }
                    876:
                    877: /* Set keypad cursor keys mode. */
                    878: void
                    879: screen_write_kcursormode(struct screen_write_ctx *ctx, int state)
                    880: {
                    881:        struct screen   *s = ctx->s;
                    882:
                    883:        if (state)
                    884:                s->mode |= MODE_KCURSOR;
                    885:        else
                    886:                s->mode &= ~MODE_KCURSOR;
                    887: }
                    888:
                    889: /* Set keypad number keys mode. */
                    890: void
                    891: screen_write_kkeypadmode(struct screen_write_ctx *ctx, int state)
                    892: {
                    893:        struct screen   *s = ctx->s;
                    894:
                    895:        if (state)
                    896:                s->mode |= MODE_KKEYPAD;
                    897:        else
                    898:                s->mode &= ~MODE_KKEYPAD;
                    899: }
                    900:
                    901: /* Clear to end of screen from cursor. */
                    902: void
                    903: screen_write_clearendofscreen(struct screen_write_ctx *ctx)
                    904: {
                    905:        struct screen   *s = ctx->s;
1.17      nicm      906:        struct tty_ctx   ttyctx;
1.1       nicm      907:        u_int            sx, sy;
                    908:
1.31      nicm      909:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      910:
                    911:        sx = screen_size_x(s);
                    912:        sy = screen_size_y(s);
                    913:
                    914:        if (s->cx <= sx - 1)
                    915:                grid_view_clear(s->grid, s->cx, s->cy, sx - s->cx, 1);
                    916:        grid_view_clear(s->grid, 0, s->cy + 1, sx, sy - (s->cy + 1));
                    917:
1.17      nicm      918:        tty_write(tty_cmd_clearendofscreen, &ttyctx);
1.1       nicm      919: }
                    920:
                    921: /* Clear to start of screen. */
                    922: void
                    923: screen_write_clearstartofscreen(struct screen_write_ctx *ctx)
                    924: {
                    925:        struct screen   *s = ctx->s;
1.17      nicm      926:        struct tty_ctx   ttyctx;
1.1       nicm      927:        u_int            sx;
                    928:
1.31      nicm      929:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      930:
                    931:        sx = screen_size_x(s);
                    932:
                    933:        if (s->cy > 0)
1.4       nicm      934:                grid_view_clear(s->grid, 0, 0, sx, s->cy);
1.1       nicm      935:        if (s->cx > sx - 1)
                    936:                grid_view_clear(s->grid, 0, s->cy, sx, 1);
                    937:        else
1.4       nicm      938:                grid_view_clear(s->grid, 0, s->cy, s->cx + 1, 1);
1.1       nicm      939:
1.17      nicm      940:        tty_write(tty_cmd_clearstartofscreen, &ttyctx);
1.1       nicm      941: }
                    942:
                    943: /* Clear entire screen. */
                    944: void
                    945: screen_write_clearscreen(struct screen_write_ctx *ctx)
                    946: {
                    947:        struct screen   *s = ctx->s;
1.17      nicm      948:        struct tty_ctx   ttyctx;
1.1       nicm      949:
1.31      nicm      950:        screen_write_initctx(ctx, &ttyctx, 0);
1.1       nicm      951:
                    952:        grid_view_clear(s->grid, 0, 0, screen_size_x(s), screen_size_y(s));
                    953:
1.17      nicm      954:        tty_write(tty_cmd_clearscreen, &ttyctx);
1.1       nicm      955: }
                    956:
                    957: /* Write cell data. */
                    958: void
1.36      nicm      959: screen_write_cell(struct screen_write_ctx *ctx,
                    960:     const struct grid_cell *gc, const struct utf8_data *utf8data)
1.1       nicm      961: {
                    962:        struct screen           *s = ctx->s;
                    963:        struct grid             *gd = s->grid;
1.15      nicm      964:        struct tty_ctx           ttyctx;
1.35      nicm      965:        struct grid_utf8         gu;
                    966:        u_int                    width, xx;
1.33      nicm      967:        struct grid_cell         tmp_gc, *tmp_gcp;
1.6       nicm      968:        int                      insert = 0;
1.1       nicm      969:
                    970:        /* Ignore padding. */
                    971:        if (gc->flags & GRID_FLAG_PADDING)
                    972:                return;
                    973:
                    974:        /* Find character width. */
1.36      nicm      975:        if (gc->flags & GRID_FLAG_UTF8)
                    976:                width = utf8data->width;
                    977:        else
1.1       nicm      978:                width = 1;
                    979:
1.32      nicm      980:        /*
                    981:         * If this is a wide character and there is no room on the screen, for
                    982:         * the entire character, don't print it.
                    983:         */
                    984:        if (width > 1 && (width > screen_size_x(s) ||
                    985:            (s->cx != screen_size_x(s) && s->cx > screen_size_x(s) - width)))
                    986:                return;
                    987:
1.35      nicm      988:        /*
                    989:         * If the width is zero, combine onto the previous character, if
                    990:         * there is space.
                    991:         */
1.1       nicm      992:        if (width == 0) {
1.36      nicm      993:                if (screen_write_combine(ctx, utf8data) == 0) {
1.35      nicm      994:                        screen_write_initctx(ctx, &ttyctx, 0);
                    995:                        tty_write(tty_cmd_utf8character, &ttyctx);
1.1       nicm      996:                }
                    997:                return;
                    998:        }
                    999:
1.31      nicm     1000:        /* Initialise the redraw context, saving the last cell. */
                   1001:        screen_write_initctx(ctx, &ttyctx, 1);
                   1002:
1.6       nicm     1003:        /* If in insert mode, make space for the cells. */
                   1004:        if (s->mode & MODE_INSERT && s->cx <= screen_size_x(s) - width) {
                   1005:                xx = screen_size_x(s) - s->cx - width;
                   1006:                grid_move_cells(s->grid, s->cx + width, s->cx, s->cy, xx);
                   1007:                insert = 1;
                   1008:        }
                   1009:
1.20      nicm     1010:        /* Check this will fit on the current line and wrap if not. */
1.1       nicm     1011:        if (s->cx > screen_size_x(s) - width) {
1.34      nicm     1012:                screen_write_linefeed(ctx, 1);
1.30      nicm     1013:                s->cx = 0;      /* carriage return */
1.1       nicm     1014:        }
                   1015:
                   1016:        /* Sanity checks. */
                   1017:        if (s->cx > screen_size_x(s) - 1 || s->cy > screen_size_y(s) - 1)
                   1018:                return;
                   1019:
                   1020:        /* Handle overwriting of UTF-8 characters. */
                   1021:        screen_write_overwrite(ctx);
                   1022:
                   1023:        /*
                   1024:         * If the new character is UTF-8 wide, fill in padding cells. Have
                   1025:         * already ensured there is enough room.
                   1026:         */
                   1027:        for (xx = s->cx + 1; xx < s->cx + width; xx++) {
1.18      nicm     1028:                tmp_gcp = grid_view_get_cell(gd, xx, s->cy);
                   1029:                if (tmp_gcp != NULL)
                   1030:                        tmp_gcp->flags |= GRID_FLAG_PADDING;
1.1       nicm     1031:        }
                   1032:
                   1033:        /* Set the cell. */
                   1034:        grid_view_set_cell(gd, s->cx, s->cy, gc);
1.36      nicm     1035:        if (gc->flags & GRID_FLAG_UTF8) {
                   1036:                /* Construct UTF-8 and write it. */
1.39    ! nicm     1037:                grid_utf8_set(&gu, utf8data);
1.1       nicm     1038:                grid_view_set_utf8(gd, s->cx, s->cy, &gu);
1.36      nicm     1039:        }
1.1       nicm     1040:
                   1041:        /* Move the cursor. */
                   1042:        s->cx += width;
                   1043:
                   1044:        /* Draw to the screen if necessary. */
1.17      nicm     1045:        if (insert) {
                   1046:                ttyctx.num = width;
                   1047:                tty_write(tty_cmd_insertcharacter, &ttyctx);
                   1048:        }
1.15      nicm     1049:        ttyctx.utf8 = &gu;
1.1       nicm     1050:        if (screen_check_selection(s, s->cx - width, s->cy)) {
1.33      nicm     1051:                memcpy(&tmp_gc, &s->sel.cell, sizeof tmp_gc);
                   1052:                tmp_gc.data = gc->data;
                   1053:                tmp_gc.flags = gc->flags &
1.28      nicm     1054:                    ~(GRID_FLAG_FG256|GRID_FLAG_BG256);
1.33      nicm     1055:                tmp_gc.flags |= s->sel.cell.flags &
1.28      nicm     1056:                    (GRID_FLAG_FG256|GRID_FLAG_BG256);
1.33      nicm     1057:                ttyctx.cell = &tmp_gc;
1.16      nicm     1058:                tty_write(tty_cmd_cell, &ttyctx);
1.15      nicm     1059:        } else {
                   1060:                ttyctx.cell = gc;
1.16      nicm     1061:                tty_write(tty_cmd_cell, &ttyctx);
1.15      nicm     1062:        }
1.35      nicm     1063: }
                   1064:
                   1065: /* Combine a UTF-8 zero-width character onto the previous. */
                   1066: int
1.36      nicm     1067: screen_write_combine(
                   1068:     struct screen_write_ctx *ctx, const struct utf8_data *utf8data)
1.35      nicm     1069: {
                   1070:        struct screen           *s = ctx->s;
                   1071:        struct grid             *gd = s->grid;
                   1072:        struct grid_cell        *gc;
                   1073:        struct grid_utf8        *gu, tmp_gu;
1.39    ! nicm     1074:        u_int                    i;
1.35      nicm     1075:
                   1076:        /* Can't combine if at 0. */
                   1077:        if (s->cx == 0)
                   1078:                return (-1);
                   1079:
1.37      nicm     1080:        /* Empty utf8data is out. */
                   1081:        if (utf8data->size == 0)
                   1082:                fatalx("UTF-8 data empty");
                   1083:
1.35      nicm     1084:        /* Retrieve the previous cell and convert to UTF-8 if not already. */
                   1085:        gc = grid_view_get_cell(gd, s->cx - 1, s->cy);
                   1086:        if (!(gc->flags & GRID_FLAG_UTF8)) {
1.39    ! nicm     1087:                tmp_gu.data[0] = gc->data;
        !          1088:                tmp_gu.data[1] = 0xff;
1.35      nicm     1089:                tmp_gu.width = 1;
                   1090:
                   1091:                grid_view_set_utf8(gd, s->cx - 1, s->cy, &tmp_gu);
                   1092:                gc->flags |= GRID_FLAG_UTF8;
                   1093:        }
                   1094:
1.39    ! nicm     1095:        /* Append the current cell. */
1.35      nicm     1096:        gu = grid_view_get_utf8(gd, s->cx - 1, s->cy);
1.39    ! nicm     1097:        if (grid_utf8_append(gu, utf8data) != 0) {
        !          1098:                /* Failed: scrap this character and replace with underscores. */
        !          1099:                if (gu->width == 1) {
        !          1100:                        gc->data = '_';
        !          1101:                        gc->flags &= ~GRID_FLAG_UTF8;
        !          1102:                } else {
        !          1103:                        for (i = 0; i < gu->width && i != sizeof gu->data; i++)
        !          1104:                                gu->data[i] = '_';
        !          1105:                        if (i != sizeof gu->data)
        !          1106:                                gu->data[i] = 0xff;
        !          1107:                        gu->width = i;
        !          1108:                }
1.35      nicm     1109:        }
                   1110:
                   1111:        return (0);
1.1       nicm     1112: }
                   1113:
                   1114: /*
                   1115:  * UTF-8 wide characters are a bit of an annoyance. They take up more than one
                   1116:  * cell on the screen, so following cells must not be drawn by marking them as
                   1117:  * padding.
                   1118:  *
                   1119:  * So far, so good. The problem is, when overwriting a padding cell, or a UTF-8
                   1120:  * character, it is necessary to also overwrite any other cells which covered
                   1121:  * by the same character.
                   1122:  */
                   1123: void
                   1124: screen_write_overwrite(struct screen_write_ctx *ctx)
                   1125: {
                   1126:        struct screen           *s = ctx->s;
                   1127:        struct grid             *gd = s->grid;
                   1128:        const struct grid_cell  *gc;
                   1129:        const struct grid_utf8  *gu;
                   1130:        u_int                    xx;
                   1131:
                   1132:        gc = grid_view_peek_cell(gd, s->cx, s->cy);
                   1133:        if (gc->flags & GRID_FLAG_PADDING) {
                   1134:                /*
                   1135:                 * A padding cell, so clear any following and leading padding
                   1136:                 * cells back to the character. Don't overwrite the current
                   1137:                 * cell as that happens later anyway.
                   1138:                 */
                   1139:                xx = s->cx + 1;
                   1140:                while (--xx > 0) {
                   1141:                        gc = grid_view_peek_cell(gd, xx, s->cy);
                   1142:                        if (!(gc->flags & GRID_FLAG_PADDING))
                   1143:                                break;
                   1144:                        grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
                   1145:                }
                   1146:
                   1147:                /* Overwrite the character at the start of this padding. */
                   1148:                grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
                   1149:
                   1150:                /* Overwrite following padding cells. */
                   1151:                xx = s->cx;
                   1152:                while (++xx < screen_size_x(s)) {
                   1153:                        gc = grid_view_peek_cell(gd, xx, s->cy);
                   1154:                        if (!(gc->flags & GRID_FLAG_PADDING))
                   1155:                                break;
                   1156:                        grid_view_set_cell(gd, xx, s->cy, &grid_default_cell);
                   1157:                }
1.22      nicm     1158:        } else if (gc->flags & GRID_FLAG_UTF8) {
                   1159:                gu = grid_view_peek_utf8(gd, s->cx, s->cy);
                   1160:                if (gu->width > 1) {
                   1161:                        /*
1.37      nicm     1162:                         * An UTF-8 wide cell; overwrite following padding
                   1163:                         * cells only.
1.22      nicm     1164:                         */
                   1165:                        xx = s->cx;
                   1166:                        while (++xx < screen_size_x(s)) {
                   1167:                                gc = grid_view_peek_cell(gd, xx, s->cy);
                   1168:                                if (!(gc->flags & GRID_FLAG_PADDING))
                   1169:                                        break;
1.37      nicm     1170:                                grid_view_set_cell(
                   1171:                                    gd, xx, s->cy, &grid_default_cell);
1.22      nicm     1172:                        }
1.1       nicm     1173:                }
                   1174:        }
                   1175: }