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