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: }