Annotation of src/usr.bin/tmux/screen.c, Revision 1.79
1.79 ! nicm 1: /* $OpenBSD: screen.c,v 1.78 2021/11/03 13:37:17 nicm Exp $ */
1.1 nicm 2:
3: /*
1.37 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.3 nicm 21: #include <stdlib.h>
1.1 nicm 22: #include <string.h>
1.16 nicm 23: #include <unistd.h>
1.47 nicm 24: #include <vis.h>
1.1 nicm 25:
26: #include "tmux.h"
27:
1.52 nicm 28: /* Selected area in screen. */
29: struct screen_sel {
30: int hidden;
31: int rectangle;
32: int modekeys;
33:
34: u_int sx;
35: u_int sy;
36:
37: u_int ex;
38: u_int ey;
39:
40: struct grid_cell cell;
41: };
42:
43: /* Entry on title stack. */
1.48 nicm 44: struct screen_title_entry {
45: char *text;
46:
47: TAILQ_ENTRY(screen_title_entry) entry;
48: };
49: TAILQ_HEAD(screen_titles, screen_title_entry);
50:
1.66 nicm 51: static void screen_resize_y(struct screen *, u_int, int, u_int *);
1.67 nicm 52: static void screen_reflow(struct screen *, u_int, u_int *, u_int *, int);
1.42 nicm 53:
1.48 nicm 54: /* Free titles stack. */
55: static void
56: screen_free_titles(struct screen *s)
57: {
58: struct screen_title_entry *title_entry;
59:
60: if (s->titles == NULL)
61: return;
62:
63: while ((title_entry = TAILQ_FIRST(s->titles)) != NULL) {
64: TAILQ_REMOVE(s->titles, title_entry, entry);
65: free(title_entry->text);
66: free(title_entry);
67: }
68:
69: free(s->titles);
70: s->titles = NULL;
71: }
72:
1.1 nicm 73: /* Create a new screen. */
74: void
75: screen_init(struct screen *s, u_int sx, u_int sy, u_int hlimit)
76: {
77: s->grid = grid_create(sx, sy, hlimit);
1.59 nicm 78: s->saved_grid = NULL;
79:
1.34 nicm 80: s->title = xstrdup("");
1.48 nicm 81: s->titles = NULL;
1.68 nicm 82: s->path = NULL;
1.1 nicm 83:
1.72 nicm 84: s->cstyle = SCREEN_CURSOR_DEFAULT;
1.78 nicm 85: s->default_cstyle = SCREEN_CURSOR_DEFAULT;
86: s->default_mode = 0;
1.77 nicm 87: s->ccolour = -1;
88: s->default_ccolour = -1;
1.3 nicm 89: s->tabs = NULL;
1.52 nicm 90: s->sel = NULL;
1.3 nicm 91:
1.64 nicm 92: s->write_list = NULL;
93:
1.1 nicm 94: screen_reinit(s);
95: }
96:
97: /* Reinitialise screen. */
98: void
99: screen_reinit(struct screen *s)
100: {
101: s->cx = 0;
102: s->cy = 0;
103:
104: s->rupper = 0;
105: s->rlower = screen_size_y(s) - 1;
106:
1.79 ! nicm 107: s->mode = MODE_CURSOR|MODE_WRAP|(s->mode & MODE_CRLF);
1.71 nicm 108: if (options_get_number(global_options, "extended-keys") == 2)
109: s->mode |= MODE_KEXTENDED;
1.12 nicm 110:
1.59 nicm 111: if (s->saved_grid != NULL)
112: screen_alternate_off(s, NULL, 0);
113: s->saved_cx = UINT_MAX;
114: s->saved_cy = UINT_MAX;
115:
1.3 nicm 116: screen_reset_tabs(s);
1.1 nicm 117:
1.44 nicm 118: grid_clear_lines(s->grid, s->grid->hsize, s->grid->sy, 8);
1.1 nicm 119:
120: screen_clear_selection(s);
1.48 nicm 121: screen_free_titles(s);
1.1 nicm 122: }
123:
124: /* Destroy a screen. */
125: void
126: screen_free(struct screen *s)
127: {
1.52 nicm 128: free(s->sel);
1.23 nicm 129: free(s->tabs);
1.68 nicm 130: free(s->path);
1.23 nicm 131: free(s->title);
1.48 nicm 132:
1.64 nicm 133: if (s->write_list != NULL)
134: screen_write_free_list(s);
135:
1.59 nicm 136: if (s->saved_grid != NULL)
137: grid_destroy(s->saved_grid);
1.1 nicm 138: grid_destroy(s->grid);
1.48 nicm 139:
140: screen_free_titles(s);
1.1 nicm 141: }
142:
1.3 nicm 143: /* Reset tabs to default, eight spaces apart. */
144: void
145: screen_reset_tabs(struct screen *s)
146: {
147: u_int i;
148:
1.23 nicm 149: free(s->tabs);
1.3 nicm 150:
151: if ((s->tabs = bit_alloc(screen_size_x(s))) == NULL)
152: fatal("bit_alloc failed");
153: for (i = 8; i < screen_size_x(s); i += 8)
154: bit_set(s->tabs, i);
1.21 nicm 155: }
156:
1.78 nicm 157: /* Set screen cursor style and mode. */
1.21 nicm 158: void
1.78 nicm 159: screen_set_cursor_style(u_int style, enum screen_cursor_style *cstyle,
160: int *mode)
1.21 nicm 161: {
1.73 nicm 162: switch (style) {
1.72 nicm 163: case 0:
1.78 nicm 164: *cstyle = SCREEN_CURSOR_DEFAULT;
1.72 nicm 165: break;
166: case 1:
1.78 nicm 167: *cstyle = SCREEN_CURSOR_BLOCK;
168: *mode |= MODE_CURSOR_BLINKING;
1.72 nicm 169: break;
170: case 2:
1.78 nicm 171: *cstyle = SCREEN_CURSOR_BLOCK;
172: *mode &= ~MODE_CURSOR_BLINKING;
1.72 nicm 173: break;
174: case 3:
1.78 nicm 175: *cstyle = SCREEN_CURSOR_UNDERLINE;
176: *mode |= MODE_CURSOR_BLINKING;
1.72 nicm 177: break;
178: case 4:
1.78 nicm 179: *cstyle = SCREEN_CURSOR_UNDERLINE;
180: *mode &= ~MODE_CURSOR_BLINKING;
1.72 nicm 181: break;
182: case 5:
1.78 nicm 183: *cstyle = SCREEN_CURSOR_BAR;
184: *mode |= MODE_CURSOR_BLINKING;
1.72 nicm 185: break;
186: case 6:
1.78 nicm 187: *cstyle = SCREEN_CURSOR_BAR;
188: *mode &= ~MODE_CURSOR_BLINKING;
1.72 nicm 189: break;
1.70 nicm 190: }
1.20 nicm 191: }
192:
193: /* Set screen cursor colour. */
194: void
1.77 nicm 195: screen_set_cursor_colour(struct screen *s, int colour)
1.20 nicm 196: {
1.77 nicm 197: s->ccolour = colour;
1.3 nicm 198: }
199:
1.1 nicm 200: /* Set screen title. */
1.57 nicm 201: int
1.1 nicm 202: screen_set_title(struct screen *s, const char *title)
203: {
1.57 nicm 204: if (!utf8_isvalid(title))
205: return (0);
1.23 nicm 206: free(s->title);
1.57 nicm 207: s->title = xstrdup(title);
208: return (1);
1.56 nicm 209: }
210:
211: /* Set screen path. */
212: void
213: screen_set_path(struct screen *s, const char *path)
214: {
215: free(s->path);
216: utf8_stravis(&s->path, path, VIS_OCTAL|VIS_CSTYLE|VIS_TAB|VIS_NL);
1.48 nicm 217: }
218:
219: /* Push the current title onto the stack. */
220: void
221: screen_push_title(struct screen *s)
222: {
223: struct screen_title_entry *title_entry;
224:
225: if (s->titles == NULL) {
226: s->titles = xmalloc(sizeof *s->titles);
227: TAILQ_INIT(s->titles);
228: }
229: title_entry = xmalloc(sizeof *title_entry);
230: title_entry->text = xstrdup(s->title);
231: TAILQ_INSERT_HEAD(s->titles, title_entry, entry);
232: }
233:
234: /*
235: * Pop a title from the stack and set it as the screen title. If the stack is
236: * empty, do nothing.
237: */
238: void
239: screen_pop_title(struct screen *s)
240: {
241: struct screen_title_entry *title_entry;
242:
243: if (s->titles == NULL)
244: return;
245:
246: title_entry = TAILQ_FIRST(s->titles);
247: if (title_entry != NULL) {
248: screen_set_title(s, title_entry->text);
249:
250: TAILQ_REMOVE(s->titles, title_entry, entry);
251: free(title_entry->text);
252: free(title_entry);
253: }
1.1 nicm 254: }
255:
1.67 nicm 256: /* Resize screen with options. */
1.1 nicm 257: void
1.62 nicm 258: screen_resize_cursor(struct screen *s, u_int sx, u_int sy, int reflow,
1.67 nicm 259: int eat_empty, int cursor)
1.1 nicm 260: {
1.67 nicm 261: u_int cx = s->cx, cy = s->grid->hsize + s->cy;
1.64 nicm 262:
1.65 nicm 263: if (s->write_list != NULL)
1.64 nicm 264: screen_write_free_list(s);
1.62 nicm 265:
1.63 nicm 266: log_debug("%s: new size %ux%u, now %ux%u (cursor %u,%u = %u,%u)",
267: __func__, sx, sy, screen_size_x(s), screen_size_y(s), s->cx, s->cy,
1.67 nicm 268: cx, cy);
1.62 nicm 269:
1.1 nicm 270: if (sx < 1)
271: sx = 1;
272: if (sy < 1)
273: sy = 1;
274:
1.3 nicm 275: if (sx != screen_size_x(s)) {
1.54 nicm 276: s->grid->sx = sx;
1.3 nicm 277: screen_reset_tabs(s);
1.49 nicm 278: } else
279: reflow = 0;
1.3 nicm 280:
1.1 nicm 281: if (sy != screen_size_y(s))
1.67 nicm 282: screen_resize_y(s, sy, eat_empty, &cy);
1.24 nicm 283:
284: if (reflow)
1.67 nicm 285: screen_reflow(s, sx, &cx, &cy, cursor);
1.62 nicm 286:
1.67 nicm 287: if (cy >= s->grid->hsize) {
288: s->cx = cx;
289: s->cy = cy - s->grid->hsize;
1.62 nicm 290: } else {
291: s->cx = 0;
292: s->cy = 0;
293: }
1.67 nicm 294:
1.63 nicm 295: log_debug("%s: cursor finished at %u,%u = %u,%u", __func__, s->cx,
1.67 nicm 296: s->cy, cx, cy);
1.65 nicm 297:
298: if (s->write_list != NULL)
299: screen_write_make_list(s);
1.62 nicm 300: }
301:
302: /* Resize screen. */
303: void
304: screen_resize(struct screen *s, u_int sx, u_int sy, int reflow)
305: {
1.67 nicm 306: screen_resize_cursor(s, sx, sy, reflow, 1, 1);
1.1 nicm 307: }
308:
1.41 nicm 309: static void
1.66 nicm 310: screen_resize_y(struct screen *s, u_int sy, int eat_empty, u_int *cy)
1.1 nicm 311: {
312: struct grid *gd = s->grid;
1.4 nicm 313: u_int needed, available, oldy, i;
1.1 nicm 314:
315: if (sy == 0)
316: fatalx("zero size");
1.4 nicm 317: oldy = screen_size_y(s);
318:
1.12 nicm 319: /*
1.4 nicm 320: * When resizing:
321: *
322: * If the height is decreasing, delete lines from the bottom until
323: * hitting the cursor, then push lines from the top into the history.
1.12 nicm 324: *
1.40 nicm 325: * When increasing, pull as many lines as possible from scrolled
326: * history (not explicitly cleared from view) to the top, then fill the
327: * remaining with blanks at the bottom.
1.4 nicm 328: */
1.1 nicm 329:
330: /* Size decreasing. */
1.4 nicm 331: if (sy < oldy) {
332: needed = oldy - sy;
1.1 nicm 333:
1.4 nicm 334: /* Delete as many lines as possible from the bottom. */
1.62 nicm 335: if (eat_empty) {
336: available = oldy - 1 - s->cy;
337: if (available > 0) {
338: if (available > needed)
339: available = needed;
340: grid_view_delete_lines(gd, oldy - available,
341: available, 8);
342: }
343: needed -= available;
1.1 nicm 344: }
345:
1.4 nicm 346: /*
1.8 nicm 347: * Now just increase the history size, if possible, to take
348: * over the lines which are left. If history is off, delete
349: * lines from the top.
1.4 nicm 350: */
1.8 nicm 351: available = s->cy;
1.40 nicm 352: if (gd->flags & GRID_HISTORY) {
353: gd->hscrolled += needed;
1.8 nicm 354: gd->hsize += needed;
1.40 nicm 355: } else if (needed > 0 && available > 0) {
1.8 nicm 356: if (available > needed)
357: available = needed;
1.44 nicm 358: grid_view_delete_lines(gd, 0, available, 8);
1.66 nicm 359: (*cy) -= available;
1.8 nicm 360: }
1.12 nicm 361: }
1.1 nicm 362:
1.51 nicm 363: /* Resize line array. */
364: grid_adjust_lines(gd, gd->hsize + sy);
1.1 nicm 365:
366: /* Size increasing. */
1.4 nicm 367: if (sy > oldy) {
368: needed = sy - oldy;
369:
1.8 nicm 370: /*
1.41 nicm 371: * Try to pull as much as possible out of scrolled history, if
372: * is is enabled.
1.8 nicm 373: */
1.40 nicm 374: available = gd->hscrolled;
1.8 nicm 375: if (gd->flags & GRID_HISTORY && available > 0) {
1.4 nicm 376: if (available > needed)
377: available = needed;
1.40 nicm 378: gd->hscrolled -= available;
1.4 nicm 379: gd->hsize -= available;
1.8 nicm 380: } else
381: available = 0;
1.4 nicm 382: needed -= available;
383:
384: /* Then fill the rest in with blanks. */
1.11 nicm 385: for (i = gd->hsize + sy - needed; i < gd->hsize + sy; i++)
1.61 nicm 386: grid_empty_line(gd, i, 8);
1.1 nicm 387: }
388:
1.4 nicm 389: /* Set the new size, and reset the scroll region. */
1.1 nicm 390: gd->sy = sy;
391: s->rupper = 0;
392: s->rlower = screen_size_y(s) - 1;
393: }
394:
395: /* Set selection. */
396: void
1.14 nicm 397: screen_set_selection(struct screen *s, u_int sx, u_int sy,
1.52 nicm 398: u_int ex, u_int ey, u_int rectangle, int modekeys, struct grid_cell *gc)
1.1 nicm 399: {
1.52 nicm 400: if (s->sel == NULL)
401: s->sel = xcalloc(1, sizeof *s->sel);
1.1 nicm 402:
1.52 nicm 403: memcpy(&s->sel->cell, gc, sizeof s->sel->cell);
404: s->sel->hidden = 0;
405: s->sel->rectangle = rectangle;
406: s->sel->modekeys = modekeys;
407:
408: s->sel->sx = sx;
409: s->sel->sy = sy;
410: s->sel->ex = ex;
411: s->sel->ey = ey;
1.1 nicm 412: }
413:
414: /* Clear selection. */
415: void
416: screen_clear_selection(struct screen *s)
417: {
1.52 nicm 418: free(s->sel);
419: s->sel = NULL;
1.1 nicm 420: }
421:
1.45 nicm 422: /* Hide selection. */
423: void
424: screen_hide_selection(struct screen *s)
425: {
1.52 nicm 426: if (s->sel != NULL)
427: s->sel->hidden = 1;
1.45 nicm 428: }
429:
1.1 nicm 430: /* Check if cell in selection. */
431: int
432: screen_check_selection(struct screen *s, u_int px, u_int py)
433: {
1.52 nicm 434: struct screen_sel *sel = s->sel;
1.28 nicm 435: u_int xx;
1.1 nicm 436:
1.52 nicm 437: if (sel == NULL || sel->hidden)
1.1 nicm 438: return (0);
439:
1.52 nicm 440: if (sel->rectangle) {
1.14 nicm 441: if (sel->sy < sel->ey) {
442: /* start line < end line -- downward selection. */
443: if (py < sel->sy || py > sel->ey)
444: return (0);
445: } else if (sel->sy > sel->ey) {
446: /* start line > end line -- upward selection. */
447: if (py > sel->sy || py < sel->ey)
448: return (0);
449: } else {
450: /* starting line == ending line. */
451: if (py != sel->sy)
452: return (0);
453: }
454:
455: /*
456: * Need to include the selection start row, but not the cursor
457: * row, which means the selection changes depending on which
458: * one is on the left.
459: */
460: if (sel->ex < sel->sx) {
461: /* Cursor (ex) is on the left. */
1.17 nicm 462: if (px < sel->ex)
1.14 nicm 463: return (0);
464:
465: if (px > sel->sx)
466: return (0);
467: } else {
468: /* Selection start (sx) is on the left. */
469: if (px < sel->sx)
470: return (0);
471:
1.17 nicm 472: if (px > sel->ex)
1.14 nicm 473: return (0);
474: }
475: } else {
476: /*
477: * Like emacs, keep the top-left-most character, and drop the
478: * bottom-right-most, regardless of copy direction.
479: */
480: if (sel->sy < sel->ey) {
481: /* starting line < ending line -- downward selection. */
482: if (py < sel->sy || py > sel->ey)
483: return (0);
484:
1.28 nicm 485: if (py == sel->sy && px < sel->sx)
1.29 nicm 486: return (0);
1.28 nicm 487:
1.53 nicm 488: if (sel->modekeys == MODEKEY_EMACS)
489: xx = (sel->ex == 0 ? 0 : sel->ex - 1);
490: else
491: xx = sel->ex;
492: if (py == sel->ey && px > xx)
1.14 nicm 493: return (0);
494: } else if (sel->sy > sel->ey) {
495: /* starting line > ending line -- upward selection. */
496: if (py > sel->sy || py < sel->ey)
497: return (0);
498:
1.28 nicm 499: if (py == sel->ey && px < sel->ex)
500: return (0);
501:
502: if (sel->modekeys == MODEKEY_EMACS)
503: xx = sel->sx - 1;
504: else
505: xx = sel->sx;
1.46 nicm 506: if (py == sel->sy && (sel->sx == 0 || px > xx))
1.14 nicm 507: return (0);
508: } else {
509: /* starting line == ending line. */
510: if (py != sel->sy)
511: return (0);
512:
513: if (sel->ex < sel->sx) {
514: /* cursor (ex) is on the left */
1.28 nicm 515: if (sel->modekeys == MODEKEY_EMACS)
516: xx = sel->sx - 1;
517: else
518: xx = sel->sx;
519: if (px > xx || px < sel->ex)
1.14 nicm 520: return (0);
521: } else {
522: /* selection start (sx) is on the left */
1.53 nicm 523: if (sel->modekeys == MODEKEY_EMACS)
524: xx = (sel->ex == 0 ? 0 : sel->ex - 1);
525: else
526: xx = sel->ex;
527: if (px < sel->sx || px > xx)
1.14 nicm 528: return (0);
529: }
530: }
1.1 nicm 531: }
532:
533: return (1);
1.43 nicm 534: }
535:
536: /* Get selected grid cell. */
537: void
538: screen_select_cell(struct screen *s, struct grid_cell *dst,
539: const struct grid_cell *src)
540: {
1.52 nicm 541: if (s->sel == NULL || s->sel->hidden)
1.43 nicm 542: return;
543:
1.52 nicm 544: memcpy(dst, &s->sel->cell, sizeof *dst);
1.43 nicm 545:
546: utf8_copy(&dst->data, &src->data);
547: dst->attr = dst->attr & ~GRID_ATTR_CHARSET;
548: dst->attr |= src->attr & GRID_ATTR_CHARSET;
549: dst->flags = src->flags;
1.24 nicm 550: }
551:
552: /* Reflow wrapped lines. */
1.42 nicm 553: static void
1.67 nicm 554: screen_reflow(struct screen *s, u_int new_x, u_int *cx, u_int *cy, int cursor)
1.24 nicm 555: {
1.62 nicm 556: u_int wx, wy;
1.54 nicm 557:
1.67 nicm 558: if (cursor) {
559: grid_wrap_position(s->grid, *cx, *cy, &wx, &wy);
560: log_debug("%s: cursor %u,%u is %u,%u", __func__, *cx, *cy, wx,
561: wy);
562: }
1.54 nicm 563:
564: grid_reflow(s->grid, new_x);
565:
1.67 nicm 566: if (cursor) {
567: grid_unwrap_position(s->grid, cx, cy, wx, wy);
568: log_debug("%s: new cursor is %u,%u", __func__, *cx, *cy);
569: }
570: else {
571: *cx = 0;
572: *cy = s->grid->hsize;
573: }
1.59 nicm 574: }
575:
576: /*
577: * Enter alternative screen mode. A copy of the visible screen is saved and the
578: * history is not updated.
579: */
580: void
581: screen_alternate_on(struct screen *s, struct grid_cell *gc, int cursor)
582: {
583: u_int sx, sy;
584:
585: if (s->saved_grid != NULL)
586: return;
587: sx = screen_size_x(s);
588: sy = screen_size_y(s);
589:
590: s->saved_grid = grid_create(sx, sy, 0);
591: grid_duplicate_lines(s->saved_grid, 0, s->grid, screen_hsize(s), sy);
592: if (cursor) {
593: s->saved_cx = s->cx;
594: s->saved_cy = s->cy;
595: }
596: memcpy(&s->saved_cell, gc, sizeof s->saved_cell);
597:
598: grid_view_clear(s->grid, 0, 0, sx, sy, 8);
599:
1.60 nicm 600: s->saved_flags = s->grid->flags;
1.59 nicm 601: s->grid->flags &= ~GRID_HISTORY;
602: }
603:
604: /* Exit alternate screen mode and restore the copied grid. */
605: void
606: screen_alternate_off(struct screen *s, struct grid_cell *gc, int cursor)
607: {
1.69 nicm 608: u_int sx = screen_size_x(s), sy = screen_size_y(s);
609:
610: /*
611: * If the current size is different, temporarily resize to the old size
612: * before copying back.
613: */
614: if (s->saved_grid != NULL)
615: screen_resize(s, s->saved_grid->sx, s->saved_grid->sy, 1);
1.59 nicm 616:
617: /*
618: * Restore the cursor position and cell. This happens even if not
619: * currently in the alternate screen.
620: */
621: if (cursor && s->saved_cx != UINT_MAX && s->saved_cy != UINT_MAX) {
622: s->cx = s->saved_cx;
623: s->cy = s->saved_cy;
624: if (gc != NULL)
625: memcpy(gc, &s->saved_cell, sizeof *gc);
626: }
627:
1.69 nicm 628: /* If not in the alternate screen, do nothing more. */
629: if (s->saved_grid == NULL) {
630: if (s->cx > screen_size_x(s) - 1)
631: s->cx = screen_size_x(s) - 1;
632: if (s->cy > screen_size_y(s) - 1)
633: s->cy = screen_size_y(s) - 1;
1.59 nicm 634: return;
1.69 nicm 635: }
1.59 nicm 636:
637: /* Restore the saved grid. */
1.69 nicm 638: grid_duplicate_lines(s->grid, screen_hsize(s), s->saved_grid, 0,
639: s->saved_grid->sy);
1.59 nicm 640:
641: /*
642: * Turn history back on (so resize can use it) and then resize back to
643: * the current size.
644: */
1.60 nicm 645: if (s->saved_flags & GRID_HISTORY)
646: s->grid->flags |= GRID_HISTORY;
1.69 nicm 647: screen_resize(s, sx, sy, 1);
1.59 nicm 648:
649: grid_destroy(s->saved_grid);
650: s->saved_grid = NULL;
1.69 nicm 651:
652: if (s->cx > screen_size_x(s) - 1)
653: s->cx = screen_size_x(s) - 1;
654: if (s->cy > screen_size_y(s) - 1)
655: s->cy = screen_size_y(s) - 1;
1.73 nicm 656: }
657:
658: /* Get mode as a string. */
659: const char *
660: screen_mode_to_string(int mode)
661: {
662: static char tmp[1024];
663:
664: if (mode == 0)
665: return "NONE";
666: if (mode == ALL_MODES)
667: return "ALL";
668:
669: *tmp = '\0';
670: if (mode & MODE_CURSOR)
671: strlcat(tmp, "CURSOR,", sizeof tmp);
672: if (mode & MODE_INSERT)
673: strlcat(tmp, "INSERT,", sizeof tmp);
674: if (mode & MODE_KCURSOR)
675: strlcat(tmp, "KCURSOR,", sizeof tmp);
676: if (mode & MODE_KKEYPAD)
677: strlcat(tmp, "KKEYPAD,", sizeof tmp);
678: if (mode & MODE_WRAP)
679: strlcat(tmp, "WRAP,", sizeof tmp);
680: if (mode & MODE_MOUSE_STANDARD)
1.75 nicm 681: strlcat(tmp, "MOUSE_STANDARD,", sizeof tmp);
1.73 nicm 682: if (mode & MODE_MOUSE_BUTTON)
1.75 nicm 683: strlcat(tmp, "MOUSE_BUTTON,", sizeof tmp);
1.76 nicm 684: if (mode & MODE_CURSOR_BLINKING)
685: strlcat(tmp, "CURSOR_BLINKING,", sizeof tmp);
686: if (mode & MODE_CURSOR_VERY_VISIBLE)
687: strlcat(tmp, "CURSOR_VERY_VISIBLE,", sizeof tmp);
1.73 nicm 688: if (mode & MODE_MOUSE_UTF8)
689: strlcat(tmp, "UTF8,", sizeof tmp);
690: if (mode & MODE_MOUSE_SGR)
691: strlcat(tmp, "SGR,", sizeof tmp);
692: if (mode & MODE_BRACKETPASTE)
693: strlcat(tmp, "BRACKETPASTE,", sizeof tmp);
694: if (mode & MODE_FOCUSON)
695: strlcat(tmp, "FOCUSON,", sizeof tmp);
696: if (mode & MODE_MOUSE_ALL)
1.75 nicm 697: strlcat(tmp, "MOUSE_ALL,", sizeof tmp);
1.73 nicm 698: if (mode & MODE_ORIGIN)
699: strlcat(tmp, "ORIGIN,", sizeof tmp);
700: if (mode & MODE_CRLF)
701: strlcat(tmp, "CRLF,", sizeof tmp);
702: if (mode & MODE_KEXTENDED)
703: strlcat(tmp, "KEXTENDED,", sizeof tmp);
1.74 nicm 704: tmp[strlen(tmp) - 1] = '\0';
1.73 nicm 705: return (tmp);
1.1 nicm 706: }