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