[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.90

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