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

Annotation of src/usr.bin/tmux/screen.c, Revision 1.2

1.2     ! nicm        1: /* $OpenBSD: screen.c,v 1.1 2009/06/01 22:58:49 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>
1.2     ! nicm       22: #include <vis.h>
1.1       nicm       23:
                     24: #include "tmux.h"
                     25:
                     26: void   screen_resize_x(struct screen *, u_int);
                     27: void   screen_resize_y(struct screen *, u_int);
                     28:
                     29: /* Create a new screen. */
                     30: void
                     31: screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
                     32: {
                     33:        s->grid = grid_create(sx, sy, hlimit);
                     34:
                     35:        s->title = xstrdup("");
                     36:
                     37:        screen_reinit(s);
                     38: }
                     39:
                     40: /* Reinitialise screen. */
                     41: void
                     42: screen_reinit(struct screen *s)
                     43: {
                     44:        s->cx = 0;
                     45:        s->cy = 0;
                     46:
                     47:        s->rupper = 0;
                     48:        s->rlower = screen_size_y(s) - 1;
                     49:
                     50:        s->mode = MODE_CURSOR;
                     51:
                     52:        grid_clear_lines(s->grid, s->grid->hsize, s->grid->sy - 1);
                     53:
                     54:        screen_clear_selection(s);
                     55: }
                     56:
                     57: /* Destroy a screen. */
                     58: void
                     59: screen_free(struct screen *s)
                     60: {
                     61:        xfree(s->title);
                     62:        grid_destroy(s->grid);
                     63: }
                     64:
                     65: /* Set screen title. */
                     66: void
                     67: screen_set_title(struct screen *s, const char *title)
                     68: {
1.2     ! nicm       69:        char    tmp[BUFSIZ];
        !            70:
        !            71:        strnvis(tmp, title, sizeof tmp, VIS_OCTAL|VIS_TAB|VIS_NL);
        !            72:
1.1       nicm       73:        xfree(s->title);
1.2     ! nicm       74:        s->title = xstrdup(tmp);
1.1       nicm       75: }
                     76:
                     77: /* Resize screen. */
                     78: void
                     79: screen_resize(struct screen *s, u_int sx, u_int sy)
                     80: {
                     81:        if (sx < 1)
                     82:                sx = 1;
                     83:        if (sy < 1)
                     84:                sy = 1;
                     85:
                     86:        if (sx != screen_size_x(s))
                     87:                screen_resize_x(s, sx);
                     88:        if (sy != screen_size_y(s))
                     89:                screen_resize_y(s, sy);
                     90: }
                     91:
                     92: void
                     93: screen_resize_x(struct screen *s, u_int sx)
                     94: {
                     95:        struct grid             *gd = s->grid;
                     96:        const struct grid_cell  *gc;
                     97:        const struct grid_utf8  *gu;
                     98:        u_int                    xx, yy;
                     99:
                    100:        if (sx == 0)
                    101:                fatalx("zero size");
                    102:
                    103:        /* If getting larger, not much to do. */
                    104:        if (sx > screen_size_x(s)) {
                    105:                gd->sx = sx;
                    106:                return;
                    107:        }
                    108:
                    109:        /* If getting smaller, nuke any data in lines over the new size. */
                    110:        for (yy = gd->hsize; yy < gd->hsize + screen_size_y(s); yy++) {
                    111:                /*
                    112:                 * If the character after the last is wide or padding, remove
                    113:                 * it and any leading padding.
                    114:                 */
                    115:                gc = &grid_default_cell;
                    116:                for (xx = sx; xx > 0; xx--) {
                    117:                        gc = grid_peek_cell(gd, xx - 1, yy);
                    118:                        if (!(gc->flags & GRID_FLAG_PADDING))
                    119:                                break;
                    120:                        grid_set_cell(gd, xx - 1, yy, &grid_default_cell);
                    121:                }
                    122:                if (xx > 0 && xx != sx && gc->flags & GRID_FLAG_UTF8) {
                    123:                        gu = grid_peek_utf8(gd, xx - 1, yy);
                    124:                        if (gu->width > 1) {
                    125:                                grid_set_cell(
                    126:                                    gd, xx - 1, yy, &grid_default_cell);
                    127:                        }
                    128:                }
                    129:
                    130:                /* Reduce the line size. */
                    131:                grid_reduce_line(gd, yy, sx);
                    132:        }
                    133:
                    134:        if (s->cx >= sx)
                    135:                s->cx = sx - 1;
                    136:        gd->sx = sx;
                    137: }
                    138:
                    139: void
                    140: screen_resize_y(struct screen *s, u_int sy)
                    141: {
                    142:        struct grid     *gd = s->grid;
                    143:        u_int            oy, yy, ny;
                    144:
                    145:        if (sy == 0)
                    146:                fatalx("zero size");
                    147:
                    148:        /* Size decreasing. */
                    149:        if (sy < screen_size_y(s)) {
                    150:                oy = screen_size_y(s);
                    151:
                    152:                if (s->cy != 0) {
                    153:                        /*
                    154:                         * The cursor is not at the start. Try to remove as
                    155:                         * many lines as possible from the top. (Up to the
                    156:                         * cursor line.)
                    157:                         */
                    158:                        ny = s->cy;
                    159:                        if (ny > oy - sy)
                    160:                                ny = oy - sy;
                    161:
                    162:                        grid_view_delete_lines(gd, 0, ny);
                    163:
                    164:                        s->cy -= ny;
                    165:                        oy -= ny;
                    166:                }
                    167:
                    168:                if (sy < oy) {
                    169:                        /* Remove any remaining lines from the bottom. */
                    170:                        grid_view_delete_lines(gd, sy, oy - sy);
                    171:                        if (s->cy >= sy)
                    172:                                s->cy = sy - 1;
                    173:                }
                    174:        }
                    175:
                    176:        /* Resize line arrays. */
                    177:        gd->size = xrealloc(gd->size, gd->hsize + sy, sizeof *gd->size);
                    178:        gd->data = xrealloc(gd->data, gd->hsize + sy, sizeof *gd->data);
                    179:        gd->usize = xrealloc(gd->usize, gd->hsize + sy, sizeof *gd->usize);
                    180:        gd->udata = xrealloc(gd->udata, gd->hsize + sy, sizeof *gd->udata);
                    181:
                    182:        /* Size increasing. */
                    183:        if (sy > screen_size_y(s)) {
                    184:                oy = screen_size_y(s);
                    185:                for (yy = gd->hsize + oy; yy < gd->hsize + sy; yy++) {
                    186:                        gd->size[yy] = 0;
                    187:                        gd->data[yy] = NULL;
                    188:                        gd->usize[yy] = 0;
                    189:                        gd->udata[yy] = NULL;
                    190:                }
                    191:        }
                    192:
                    193:        gd->sy = sy;
                    194:
                    195:        s->rupper = 0;
                    196:        s->rlower = screen_size_y(s) - 1;
                    197: }
                    198:
                    199: /* Set selection. */
                    200: void
                    201: screen_set_selection(struct screen *s,
                    202:     u_int sx, u_int sy, u_int ex, u_int ey, struct grid_cell *gc)
                    203: {
                    204:        struct screen_sel       *sel = &s->sel;
                    205:
                    206:        memcpy(&sel->cell, gc, sizeof sel->cell);
                    207:
                    208:        sel->flag = 1;
                    209:        if (ey < sy || (sy == ey && ex < sx)) {
                    210:                sel->sx = ex; sel->sy = ey;
                    211:                sel->ex = sx; sel->ey = sy;
                    212:        } else {
                    213:                sel->sx = sx; sel->sy = sy;
                    214:                sel->ex = ex; sel->ey = ey;
                    215:        }
                    216: }
                    217:
                    218: /* Clear selection. */
                    219: void
                    220: screen_clear_selection(struct screen *s)
                    221: {
                    222:        struct screen_sel       *sel = &s->sel;
                    223:
                    224:        sel->flag = 0;
                    225: }
                    226:
                    227: /* Check if cell in selection. */
                    228: int
                    229: screen_check_selection(struct screen *s, u_int px, u_int py)
                    230: {
                    231:        struct screen_sel       *sel = &s->sel;
                    232:
                    233:        if (!sel->flag || py < sel->sy || py > sel->ey)
                    234:                return (0);
                    235:
                    236:        if (py == sel->sy && py == sel->ey) {
                    237:                if (px < sel->sx || px > sel->ex)
                    238:                        return (0);
                    239:                return (1);
                    240:        }
                    241:
                    242:        if ((py == sel->sy && px < sel->sx) || (py == sel->ey && px > sel->ex))
                    243:                return (0);
                    244:        return (1);
                    245: }