varnish-cache/bin/varnishtest/teken_subr.h
0
/*-
1
 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
2
 *
3
 * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
4
 * All rights reserved.
5
 *
6
 * Redistribution and use in source and binary forms, with or without
7
 * modification, are permitted provided that the following conditions
8
 * are met:
9
 * 1. Redistributions of source code must retain the above copyright
10
 *    notice, this list of conditions and the following disclaimer.
11
 * 2. Redistributions in binary form must reproduce the above copyright
12
 *    notice, this list of conditions and the following disclaimer in the
13
 *    documentation and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
 * SUCH DAMAGE.
26
 *
27
 * $FreeBSD: head/sys/teken/teken_subr.h 333995 2018-05-21 20:35:16Z dumbbell $
28
 */
29
30
static void teken_subr_cursor_up(teken_t *, unsigned int);
31
static void teken_subr_erase_line(const teken_t *, unsigned int);
32
static void teken_subr_regular_character(teken_t *, teken_char_t);
33
static void teken_subr_reset_to_initial_state(teken_t *);
34
static void teken_subr_save_cursor(teken_t *);
35
36
static inline int
37 28880
teken_tab_isset(const teken_t *t, unsigned int col)
38
{
39
        unsigned int b, o;
40
41 28880
        if (col >= T_NUMCOL)
42 0
                return ((col % 8) == 0);
43
44 28880
        b = col / (sizeof(unsigned int) * 8);
45 28880
        o = col % (sizeof(unsigned int) * 8);
46
47 28880
        return (t->t_tabstops[b] & (1U << o));
48 28880
}
49
50
static inline void
51 1040
teken_tab_clear(teken_t *t, unsigned int col)
52
{
53
        unsigned int b, o;
54
55 1040
        if (col >= T_NUMCOL)
56 0
                return;
57
58 1040
        b = col / (sizeof(unsigned int) * 8);
59 1040
        o = col % (sizeof(unsigned int) * 8);
60
61 1040
        t->t_tabstops[b] &= ~(1U << o);
62 1040
}
63
64
static inline void
65 194640
teken_tab_set(teken_t *t, unsigned int col)
66
{
67
        unsigned int b, o;
68
69 194640
        if (col >= T_NUMCOL)
70 0
                return;
71
72 194640
        b = col / (sizeof(unsigned int) * 8);
73 194640
        o = col % (sizeof(unsigned int) * 8);
74
75 194640
        t->t_tabstops[b] |= 1U << o;
76 194640
}
77
78
static void
79 9920
teken_tab_default(teken_t *t)
80
{
81
        unsigned int i;
82
83 9920
        memset(t->t_tabstops, 0, T_NUMCOL / 8);
84
85 198400
        for (i = 8; i < T_NUMCOL; i += 8)
86 188480
                teken_tab_set(t, i);
87 9920
}
88
89
static void
90 34536
teken_subr_do_scroll(const teken_t *t, int amount)
91
{
92
        teken_rect_t tr;
93
        teken_pos_t tp;
94
95 34536
        teken_assert(t->t_cursor.tp_row <= t->t_winsize.tp_row);
96 34536
        teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
97 34536
        teken_assert(amount != 0);
98
99
        /* Copy existing data 1 line up. */
100 34536
        if (amount > 0) {
101
                /* Scroll down. */
102
103
                /* Copy existing data up. */
104 24216
                if (t->t_scrollreg.ts_begin + amount < t->t_scrollreg.ts_end) {
105 24216
                        tr.tr_begin.tp_row = t->t_scrollreg.ts_begin + amount;
106 24216
                        tr.tr_begin.tp_col = 0;
107 24216
                        tr.tr_end.tp_row = t->t_scrollreg.ts_end;
108 24216
                        tr.tr_end.tp_col = t->t_winsize.tp_col;
109 24216
                        tp.tp_row = t->t_scrollreg.ts_begin;
110 24216
                        tp.tp_col = 0;
111 24216
                        teken_funcs_copy(t, &tr, &tp);
112
113 24216
                        tr.tr_begin.tp_row = t->t_scrollreg.ts_end - amount;
114 24216
                } else {
115 0
                        tr.tr_begin.tp_row = t->t_scrollreg.ts_begin;
116
                }
117
118
                /* Clear the last lines. */
119 24216
                tr.tr_begin.tp_col = 0;
120 24216
                tr.tr_end.tp_row = t->t_scrollreg.ts_end;
121 24216
                tr.tr_end.tp_col = t->t_winsize.tp_col;
122 24216
                teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
123 24216
        } else {
124
                /* Scroll up. */
125 10320
                amount = -amount;
126
127
                /* Copy existing data down. */
128 10320
                if (t->t_scrollreg.ts_begin + amount < t->t_scrollreg.ts_end) {
129 10320
                        tr.tr_begin.tp_row = t->t_scrollreg.ts_begin;
130 10320
                        tr.tr_begin.tp_col = 0;
131 10320
                        tr.tr_end.tp_row = t->t_scrollreg.ts_end - amount;
132 10320
                        tr.tr_end.tp_col = t->t_winsize.tp_col;
133 10320
                        tp.tp_row = t->t_scrollreg.ts_begin + amount;
134 10320
                        tp.tp_col = 0;
135 10320
                        teken_funcs_copy(t, &tr, &tp);
136
137 10320
                        tr.tr_end.tp_row = t->t_scrollreg.ts_begin + amount;
138 10320
                } else {
139 0
                        tr.tr_end.tp_row = t->t_scrollreg.ts_end;
140
                }
141
142
                /* Clear the first lines. */
143 10320
                tr.tr_begin.tp_row = t->t_scrollreg.ts_begin;
144 10320
                tr.tr_begin.tp_col = 0;
145 10320
                tr.tr_end.tp_col = t->t_winsize.tp_col;
146 10320
                teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
147
        }
148 34536
}
149
150
static ssize_t
151 480
teken_subr_do_cpr(const teken_t *t, unsigned int cmd, char response[16])
152
{
153
154 480
        switch (cmd) {
155
        case 5: /* Operating status. */
156 80
                strcpy(response, "0n");
157 80
                return (2);
158
        case 6: { /* Cursor position. */
159
                int len;
160
161 160
                len = snprintf(response, 16, "%u;%uR",
162 80
                    (t->t_cursor.tp_row - t->t_originreg.ts_begin) + 1,
163 80
                    t->t_cursor.tp_col + 1);
164
165 80
                if (len >= 16)
166 0
                        return (-1);
167 80
                return (len);
168
        }
169
        case 15: /* Printer status. */
170 80
                strcpy(response, "13n");
171 80
                return (3);
172
        case 25: /* UDK status. */
173 80
                strcpy(response, "20n");
174 80
                return (3);
175
        case 26: /* Keyboard status. */
176 160
                strcpy(response, "27;1n");
177 160
                return (5);
178
        default:
179
                teken_printf("Unknown DSR\n");
180 0
                return (-1);
181
        }
182 480
}
183
184
static void
185 160
teken_subr_alignment_test(teken_t *t)
186
{
187
        teken_rect_t tr;
188
189 160
        t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
190 160
        t->t_scrollreg.ts_begin = 0;
191 160
        t->t_scrollreg.ts_end = t->t_winsize.tp_row;
192 160
        t->t_originreg = t->t_scrollreg;
193 160
        t->t_stateflags &= ~(TS_WRAPPED|TS_ORIGIN);
194 160
        teken_funcs_cursor(t);
195
196 160
        tr.tr_begin.tp_row = 0;
197 160
        tr.tr_begin.tp_col = 0;
198 160
        tr.tr_end = t->t_winsize;
199 160
        teken_funcs_fill(t, &tr, 'E', &t->t_defattr);
200 160
}
201
202
static void
203 36338
teken_subr_backspace(teken_t *t)
204
{
205
206 36338
        if (t->t_stateflags & TS_CONS25) {
207 160
                if (t->t_cursor.tp_col == 0) {
208 160
                        if (t->t_cursor.tp_row == t->t_originreg.ts_begin)
209 80
                                return;
210 80
                        t->t_cursor.tp_row--;
211 80
                        t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
212 80
                } else {
213 0
                        t->t_cursor.tp_col--;
214
                }
215 80
        } else {
216 36178
                if (t->t_cursor.tp_col == 0)
217 80
                        return;
218
219 36098
                t->t_cursor.tp_col--;
220 36098
                t->t_stateflags &= ~TS_WRAPPED;
221
        }
222
223 36178
        teken_funcs_cursor(t);
224 36338
}
225
226
static void
227 240
teken_subr_bell(const teken_t *t)
228
{
229
230 240
        teken_funcs_bell(t);
231 240
}
232
233
static void
234 89781
teken_subr_carriage_return(teken_t *t)
235
{
236
237 89781
        t->t_cursor.tp_col = 0;
238 89781
        t->t_stateflags &= ~TS_WRAPPED;
239 89781
        teken_funcs_cursor(t);
240 89781
}
241
242
static void
243 61120
teken_subr_cursor_backward(teken_t *t, unsigned int ncols)
244
{
245
246 61120
        if (ncols > t->t_cursor.tp_col)
247 160
                t->t_cursor.tp_col = 0;
248
        else
249 60960
                t->t_cursor.tp_col -= ncols;
250 61120
        t->t_stateflags &= ~TS_WRAPPED;
251 61120
        teken_funcs_cursor(t);
252 61120
}
253
254
static void
255 80
teken_subr_cursor_backward_tabulation(teken_t *t, unsigned int ntabs)
256
{
257
258 80
        do {
259
                /* Stop when we've reached the beginning of the line. */
260 720
                if (t->t_cursor.tp_col == 0)
261 0
                        break;
262
263 720
                t->t_cursor.tp_col--;
264
265
                /* Tab marker set. */
266 720
                if (teken_tab_isset(t, t->t_cursor.tp_col))
267 160
                        ntabs--;
268 720
        } while (ntabs > 0);
269
270 80
        teken_funcs_cursor(t);
271 80
}
272
273
static void
274 21124
teken_subr_cursor_down(teken_t *t, unsigned int nrows)
275
{
276
277 21124
        if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end)
278 880
                t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1;
279
        else
280 20244
                t->t_cursor.tp_row += nrows;
281 21124
        t->t_stateflags &= ~TS_WRAPPED;
282 21124
        teken_funcs_cursor(t);
283 21124
}
284
285
static void
286 69458
teken_subr_cursor_forward(teken_t *t, unsigned int ncols)
287
{
288
289 69458
        if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col)
290 720
                t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
291
        else
292 68738
                t->t_cursor.tp_col += ncols;
293 69458
        t->t_stateflags &= ~TS_WRAPPED;
294 69458
        teken_funcs_cursor(t);
295 69458
}
296
297
static void
298 6080
teken_subr_cursor_forward_tabulation(teken_t *t, unsigned int ntabs)
299
{
300
301 6080
        do {
302
                /* Stop when we've reached the end of the line. */
303 30160
                if (t->t_cursor.tp_col == t->t_winsize.tp_col - 1)
304 2000
                        break;
305
306 28160
                t->t_cursor.tp_col++;
307
308
                /* Tab marker set. */
309 28160
                if (teken_tab_isset(t, t->t_cursor.tp_col))
310 4080
                        ntabs--;
311 28160
        } while (ntabs > 0);
312
313 6080
        teken_funcs_cursor(t);
314 6080
}
315
316
static void
317 80
teken_subr_cursor_next_line(teken_t *t, unsigned int ncols)
318
{
319
320 80
        t->t_cursor.tp_col = 0;
321 80
        teken_subr_cursor_down(t, ncols);
322 80
}
323
324
static void
325 143796
teken_subr_cursor_position(teken_t *t, unsigned int row, unsigned int col)
326
{
327
328 143796
        row = (row - 1) + t->t_originreg.ts_begin;
329 143796
        t->t_cursor.tp_row = row < t->t_originreg.ts_end ?
330 143796
            row : t->t_originreg.ts_end - 1;
331
332 143796
        col--;
333 143796
        t->t_cursor.tp_col = col < t->t_winsize.tp_col ?
334 143796
            col : t->t_winsize.tp_col - 1;
335
336 143796
        t->t_stateflags &= ~TS_WRAPPED;
337 143796
        teken_funcs_cursor(t);
338 143796
}
339
340
static void
341 400
teken_subr_cursor_position_report(const teken_t *t, unsigned int cmd)
342
{
343 400
        char response[18] = "\x1B[";
344
        ssize_t len;
345
346 400
        len = teken_subr_do_cpr(t, cmd, response + 2);
347 400
        if (len < 0)
348 0
                return;
349
350 400
        teken_funcs_respond(t, response, len + 2);
351 400
}
352
353
static void
354 80
teken_subr_cursor_previous_line(teken_t *t, unsigned int ncols)
355
{
356
357 80
        t->t_cursor.tp_col = 0;
358 80
        teken_subr_cursor_up(t, ncols);
359 80
}
360
361
static void
362 2423
teken_subr_cursor_up(teken_t *t, unsigned int nrows)
363
{
364
365 2423
        if (t->t_scrollreg.ts_begin + nrows >= t->t_cursor.tp_row)
366 880
                t->t_cursor.tp_row = t->t_scrollreg.ts_begin;
367
        else
368 1543
                t->t_cursor.tp_row -= nrows;
369 2423
        t->t_stateflags &= ~TS_WRAPPED;
370 2423
        teken_funcs_cursor(t);
371 2423
}
372
373
static void
374 0
teken_subr_set_cursor_style(teken_t *t, unsigned int style)
375
{
376
377
        /* TODO */
378 0
        (void)t;
379 0
        (void)style;
380
381
        /*
382
         * CSI Ps SP q
383
         *   Set cursor style (DECSCUSR), VT520.
384
         *     Ps = 0  -> blinking block.
385
         *     Ps = 1  -> blinking block (default).
386
         *     Ps = 2  -> steady block.
387
         *     Ps = 3  -> blinking underline.
388
         *     Ps = 4  -> steady underline.
389
         *     Ps = 5  -> blinking bar (xterm).
390
         *     Ps = 6  -> steady bar (xterm).
391
         */
392 0
}
393
394
static void
395 7840
teken_subr_delete_character(const teken_t *t, unsigned int ncols)
396
{
397
        teken_rect_t tr;
398
399 7840
        tr.tr_begin.tp_row = t->t_cursor.tp_row;
400 7840
        tr.tr_end.tp_row = t->t_cursor.tp_row + 1;
401 7840
        tr.tr_end.tp_col = t->t_winsize.tp_col;
402
403 7840
        if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) {
404 0
                tr.tr_begin.tp_col = t->t_cursor.tp_col;
405 0
        } else {
406
                /* Copy characters to the left. */
407 7840
                tr.tr_begin.tp_col = t->t_cursor.tp_col + ncols;
408 7840
                teken_funcs_copy(t, &tr, &t->t_cursor);
409
410 7840
                tr.tr_begin.tp_col = t->t_winsize.tp_col - ncols;
411
        }
412
413
        /* Blank trailing columns. */
414 7840
        teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
415 7840
}
416
417
static void
418 3880
teken_subr_delete_line(const teken_t *t, unsigned int nrows)
419
{
420
        teken_rect_t tr;
421
422
        /* Ignore if outside scrolling region. */
423 3880
        if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin ||
424 3880
            t->t_cursor.tp_row >= t->t_scrollreg.ts_end)
425 0
                return;
426
427 3880
        tr.tr_begin.tp_col = 0;
428 3880
        tr.tr_end.tp_row = t->t_scrollreg.ts_end;
429 3880
        tr.tr_end.tp_col = t->t_winsize.tp_col;
430
431 3880
        if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) {
432 480
                tr.tr_begin.tp_row = t->t_cursor.tp_row;
433 480
        } else {
434
                teken_pos_t tp;
435
436
                /* Copy rows up. */
437 3400
                tr.tr_begin.tp_row = t->t_cursor.tp_row + nrows;
438 3400
                tp.tp_row = t->t_cursor.tp_row;
439 3400
                tp.tp_col = 0;
440 3400
                teken_funcs_copy(t, &tr, &tp);
441
442 3400
                tr.tr_begin.tp_row = t->t_scrollreg.ts_end - nrows;
443
        }
444
445
        /* Blank trailing rows. */
446 3880
        teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
447 3880
}
448
449
static void
450 80
teken_subr_device_control_string(teken_t *t)
451
{
452
453
        teken_printf("Unsupported device control string\n");
454 80
        t->t_stateflags |= TS_INSTRING;
455 80
}
456
457
static void
458 80
teken_subr_device_status_report(const teken_t *t, unsigned int cmd)
459
{
460 80
        char response[19] = "\x1B[?";
461
        ssize_t len;
462
463 80
        len = teken_subr_do_cpr(t, cmd, response + 3);
464 80
        if (len < 0)
465 0
                return;
466
467 80
        teken_funcs_respond(t, response, len + 3);
468 80
}
469
470
static void
471 1360
teken_subr_double_height_double_width_line_top(const teken_t *t)
472
{
473
474 1360
        (void)t;
475
        teken_printf("double height double width top\n");
476 1360
}
477
478
static void
479 1360
teken_subr_double_height_double_width_line_bottom(const teken_t *t)
480
{
481
482 1360
        (void)t;
483
        teken_printf("double height double width bottom\n");
484 1360
}
485
486
static void
487 80
teken_subr_erase_character(const teken_t *t, unsigned int ncols)
488
{
489
        teken_rect_t tr;
490
491 80
        tr.tr_begin = t->t_cursor;
492 80
        tr.tr_end.tp_row = t->t_cursor.tp_row + 1;
493
494 80
        if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col)
495 0
                tr.tr_end.tp_col = t->t_winsize.tp_col;
496
        else
497 80
                tr.tr_end.tp_col = t->t_cursor.tp_col + ncols;
498
499 80
        teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
500 80
}
501
502
static void
503 7600
teken_subr_erase_display(const teken_t *t, unsigned int mode)
504
{
505
        teken_rect_t r;
506
507 7600
        r.tr_begin.tp_col = 0;
508 7600
        r.tr_end.tp_col = t->t_winsize.tp_col;
509
510 7600
        switch (mode) {
511
        case 1: /* Erase from the top to the cursor. */
512 160
                teken_subr_erase_line(t, 1);
513
514
                /* Erase lines above. */
515 160
                if (t->t_cursor.tp_row == 0)
516 0
                        return;
517 160
                r.tr_begin.tp_row = 0;
518 160
                r.tr_end.tp_row = t->t_cursor.tp_row;
519 160
                break;
520
        case 2: /* Erase entire display. */
521 6120
                r.tr_begin.tp_row = 0;
522 6120
                r.tr_end.tp_row = t->t_winsize.tp_row;
523 6120
                break;
524
        default: /* Erase from cursor to the bottom. */
525 1320
                teken_subr_erase_line(t, 0);
526
527
                /* Erase lines below. */
528 1320
                if (t->t_cursor.tp_row == t->t_winsize.tp_row - 1)
529 80
                        return;
530 1240
                r.tr_begin.tp_row = t->t_cursor.tp_row + 1;
531 1240
                r.tr_end.tp_row = t->t_winsize.tp_row;
532 1240
                break;
533
        }
534
535 7520
        teken_funcs_fill(t, &r, BLANK, &t->t_curattr);
536 7600
}
537
538
static void
539 9804
teken_subr_erase_line(const teken_t *t, unsigned int mode)
540
{
541
        teken_rect_t r;
542
543 9804
        r.tr_begin.tp_row = t->t_cursor.tp_row;
544 9804
        r.tr_end.tp_row = t->t_cursor.tp_row + 1;
545
546 9804
        switch (mode) {
547
        case 1: /* Erase from the beginning of the line to the cursor. */
548 1520
                r.tr_begin.tp_col = 0;
549 1520
                r.tr_end.tp_col = t->t_cursor.tp_col + 1;
550 1520
                break;
551
        case 2: /* Erase entire line. */
552 720
                r.tr_begin.tp_col = 0;
553 720
                r.tr_end.tp_col = t->t_winsize.tp_col;
554 720
                break;
555
        default: /* Erase from cursor to the end of the line. */
556 7564
                r.tr_begin.tp_col = t->t_cursor.tp_col;
557 7564
                r.tr_end.tp_col = t->t_winsize.tp_col;
558 7564
                break;
559
        }
560
561 9804
        teken_funcs_fill(t, &r, BLANK, &t->t_curattr);
562 9804
}
563
564
static void
565 880
teken_subr_g0_scs_special_graphics(teken_t *t)
566
{
567
568 880
        t->t_scs[0] = teken_scs_special_graphics;
569 880
}
570
571
static void
572 80
teken_subr_g0_scs_uk_national(teken_t *t)
573
{
574
575 80
        t->t_scs[0] = teken_scs_uk_national;
576 80
}
577
578
static void
579 2640
teken_subr_g0_scs_us_ascii(teken_t *t)
580
{
581
582 2640
        t->t_scs[0] = teken_scs_us_ascii;
583 2640
}
584
585
static void
586 80
teken_subr_g1_scs_special_graphics(teken_t *t)
587
{
588
589 80
        t->t_scs[1] = teken_scs_special_graphics;
590 80
}
591
592
static void
593 80
teken_subr_g1_scs_uk_national(teken_t *t)
594
{
595
596 80
        t->t_scs[1] = teken_scs_uk_national;
597 80
}
598
599
static void
600 3440
teken_subr_g1_scs_us_ascii(teken_t *t)
601
{
602
603 3440
        t->t_scs[1] = teken_scs_us_ascii;
604 3440
}
605
606
static void
607 80
teken_subr_horizontal_position_absolute(teken_t *t, unsigned int col)
608
{
609
610 80
        col--;
611 80
        t->t_cursor.tp_col = col < t->t_winsize.tp_col ?
612 80
            col : t->t_winsize.tp_col - 1;
613
614 80
        t->t_stateflags &= ~TS_WRAPPED;
615 80
        teken_funcs_cursor(t);
616 80
}
617
618
static void
619 6080
teken_subr_horizontal_tab(teken_t *t)
620
{
621
622 6080
        teken_subr_cursor_forward_tabulation(t, 1);
623 6080
}
624
625
static void
626 6160
teken_subr_horizontal_tab_set(teken_t *t)
627
{
628
629 6160
        teken_tab_set(t, t->t_cursor.tp_col);
630 6160
}
631
632
static void
633 3520
teken_subr_index(teken_t *t)
634
{
635
636 3520
        if (t->t_cursor.tp_row < t->t_scrollreg.ts_end - 1) {
637 3520
                t->t_cursor.tp_row++;
638 3520
                t->t_stateflags &= ~TS_WRAPPED;
639 3520
                teken_funcs_cursor(t);
640 3520
        } else {
641 0
                teken_subr_do_scroll(t, 1);
642
        }
643 3520
}
644
645
static void
646 4160
teken_subr_insert_character(const teken_t *t, unsigned int ncols)
647
{
648
        teken_rect_t tr;
649
650 4160
        tr.tr_begin = t->t_cursor;
651 4160
        tr.tr_end.tp_row = t->t_cursor.tp_row + 1;
652
653 4160
        if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) {
654 0
                tr.tr_end.tp_col = t->t_winsize.tp_col;
655 0
        } else {
656
                teken_pos_t tp;
657
658
                /* Copy characters to the right. */
659 4160
                tr.tr_end.tp_col = t->t_winsize.tp_col - ncols;
660 4160
                tp.tp_row = t->t_cursor.tp_row;
661 4160
                tp.tp_col = t->t_cursor.tp_col + ncols;
662 4160
                teken_funcs_copy(t, &tr, &tp);
663
664 4160
                tr.tr_end.tp_col = t->t_cursor.tp_col + ncols;
665
        }
666
667
        /* Blank current location. */
668 4160
        teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
669 4160
}
670
671
static void
672 3880
teken_subr_insert_line(const teken_t *t, unsigned int nrows)
673
{
674
        teken_rect_t tr;
675
676
        /* Ignore if outside scrolling region. */
677 3880
        if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin ||
678 3880
            t->t_cursor.tp_row >= t->t_scrollreg.ts_end)
679 0
                return;
680
681 3880
        tr.tr_begin.tp_row = t->t_cursor.tp_row;
682 3880
        tr.tr_begin.tp_col = 0;
683 3880
        tr.tr_end.tp_col = t->t_winsize.tp_col;
684
685 3880
        if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) {
686 480
                tr.tr_end.tp_row = t->t_scrollreg.ts_end;
687 480
        } else {
688
                teken_pos_t tp;
689
690
                /* Copy lines down. */
691 3400
                tr.tr_end.tp_row = t->t_scrollreg.ts_end - nrows;
692 3400
                tp.tp_row = t->t_cursor.tp_row + nrows;
693 3400
                tp.tp_col = 0;
694 3400
                teken_funcs_copy(t, &tr, &tp);
695
696 3400
                tr.tr_end.tp_row = t->t_cursor.tp_row + nrows;
697
        }
698
699
        /* Blank current location. */
700 3880
        teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
701 3880
}
702
703
static void
704 280
teken_subr_keypad_application_mode(const teken_t *t)
705
{
706
707 280
        teken_funcs_param(t, TP_KEYPADAPP, 1);
708 280
}
709
710
static void
711 560
teken_subr_keypad_numeric_mode(const teken_t *t)
712
{
713
714 560
        teken_funcs_param(t, TP_KEYPADAPP, 0);
715 560
}
716
717
static void
718 74124
teken_subr_newline(teken_t *t)
719
{
720
721 74124
        t->t_cursor.tp_row++;
722
723 74124
        if (t->t_cursor.tp_row >= t->t_scrollreg.ts_end) {
724 24060
                teken_subr_do_scroll(t, 1);
725 24060
                t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1;
726 24060
        }
727
728 74124
        t->t_stateflags &= ~TS_WRAPPED;
729 74124
        teken_funcs_cursor(t);
730 74124
}
731
732
static void
733 320
teken_subr_newpage(teken_t *t)
734
{
735
736 320
        if (t->t_stateflags & TS_CONS25) {
737
                teken_rect_t tr;
738
739
                /* Clear screen. */
740 160
                tr.tr_begin.tp_row = t->t_originreg.ts_begin;
741 160
                tr.tr_begin.tp_col = 0;
742 160
                tr.tr_end.tp_row = t->t_originreg.ts_end;
743 160
                tr.tr_end.tp_col = t->t_winsize.tp_col;
744 160
                teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
745
746
                /* Cursor at top left. */
747 160
                t->t_cursor.tp_row = t->t_originreg.ts_begin;
748 160
                t->t_cursor.tp_col = 0;
749 160
                t->t_stateflags &= ~TS_WRAPPED;
750 160
                teken_funcs_cursor(t);
751 160
        } else {
752 160
                teken_subr_newline(t);
753
        }
754 320
}
755
756
static void
757 1280
teken_subr_next_line(teken_t *t)
758
{
759
760 1280
        t->t_cursor.tp_col = 0;
761 1280
        teken_subr_newline(t);
762 1280
}
763
764
static void
765 80
teken_subr_operating_system_command(teken_t *t)
766
{
767
768
        teken_printf("Unsupported operating system command\n");
769 80
        t->t_stateflags |= TS_INSTRING;
770 80
}
771
772
static void
773 80
teken_subr_pan_down(const teken_t *t, unsigned int nrows)
774
{
775
776 80
        teken_subr_do_scroll(t, (int)nrows);
777 80
}
778
779
static void
780 80
teken_subr_pan_up(const teken_t *t, unsigned int nrows)
781
{
782
783 80
        teken_subr_do_scroll(t, -(int)nrows);
784 80
}
785
786
static void
787 80
teken_subr_primary_device_attributes(const teken_t *t, unsigned int request)
788
{
789
790 80
        if (request == 0) {
791 80
                const char response[] = "\x1B[?1;2c";
792
793 80
                teken_funcs_respond(t, response, sizeof response - 1);
794 80
        } else {
795
                teken_printf("Unknown DA1\n");
796
        }
797 80
}
798
799
static void
800 5015395
teken_subr_do_putchar(teken_t *t, const teken_pos_t *tp, teken_char_t c,
801
    int width)
802
{
803
804 5015395
        t->t_last = c;
805 5015395
        if (t->t_stateflags & TS_INSERT &&
806 16640
            tp->tp_col < t->t_winsize.tp_col - width) {
807
                teken_rect_t ctr;
808
                teken_pos_t ctp;
809
810
                /* Insert mode. Move existing characters to the right. */
811 16640
                ctr.tr_begin = *tp;
812 16640
                ctr.tr_end.tp_row = tp->tp_row + 1;
813 16640
                ctr.tr_end.tp_col = t->t_winsize.tp_col - width;
814 16640
                ctp.tp_row = tp->tp_row;
815 16640
                ctp.tp_col = tp->tp_col + width;
816 16640
                teken_funcs_copy(t, &ctr, &ctp);
817 16640
        }
818
819 5015395
        teken_funcs_putchar(t, tp, c, &t->t_curattr);
820
821 5015395
        if (width == 2 && tp->tp_col + 1 < t->t_winsize.tp_col) {
822
                teken_pos_t tp2;
823
                teken_attr_t attr;
824
825
                /* Print second half of CJK fullwidth character. */
826 160
                tp2.tp_row = tp->tp_row;
827 160
                tp2.tp_col = tp->tp_col + 1;
828 160
                attr = t->t_curattr;
829 160
                attr.ta_format |= TF_CJK_RIGHT;
830 160
                teken_funcs_putchar(t, &tp2, c, &attr);
831 160
        }
832 5015395
}
833
834
static void
835 5016044
teken_subr_regular_character(teken_t *t, teken_char_t c)
836
{
837
        int width;
838
839 5016044
        if (t->t_stateflags & TS_8BIT) {
840 403
                if (!(t->t_stateflags & TS_CONS25) && (c <= 0x1b || c == 0x7f))
841 0
                        return;
842 403
                c = teken_scs_process(t, c);
843 403
                width = 1;
844 403
        } else {
845 5015641
                c = teken_scs_process(t, c);
846 5015641
                width = teken_wcwidth(c);
847
                /* XXX: Don't process zero-width characters yet. */
848 5015641
                if (width <= 0)
849 240
                        return;
850
        }
851
852 5015804
        if (t->t_stateflags & TS_CONS25) {
853 240
                teken_subr_do_putchar(t, &t->t_cursor, c, width);
854 240
                t->t_cursor.tp_col += width;
855
856 240
                if (t->t_cursor.tp_col >= t->t_winsize.tp_col) {
857 0
                        if (t->t_cursor.tp_row == t->t_scrollreg.ts_end - 1) {
858
                                /* Perform scrolling. */
859 0
                                teken_subr_do_scroll(t, 1);
860 0
                        } else {
861
                                /* No scrolling needed. */
862 0
                                if (t->t_cursor.tp_row <
863 0
                                    t->t_winsize.tp_row - 1)
864 0
                                        t->t_cursor.tp_row++;
865
                        }
866 0
                        t->t_cursor.tp_col = 0;
867 0
                }
868 10015132
        } else if (t->t_stateflags & TS_AUTOWRAP &&
869 5002362
            ((t->t_stateflags & TS_WRAPPED &&
870 2236
            t->t_cursor.tp_col + 1 == t->t_winsize.tp_col) ||
871 5000126
            t->t_cursor.tp_col + width > t->t_winsize.tp_col)) {
872
                teken_pos_t tp;
873
874
                /*
875
                 * Perform line wrapping, if:
876
                 * - Autowrapping is enabled, and
877
                 *   - We're in the wrapped state at the last column, or
878
                 *   - The character to be printed does not fit anymore.
879
                 */
880 2236
                if (t->t_cursor.tp_row == t->t_scrollreg.ts_end - 1) {
881
                        /* Perform scrolling. */
882 76
                        teken_subr_do_scroll(t, 1);
883 76
                        tp.tp_row = t->t_scrollreg.ts_end - 1;
884 76
                } else {
885
                        /* No scrolling needed. */
886 2160
                        tp.tp_row = t->t_cursor.tp_row + 1;
887 2160
                        if (tp.tp_row == t->t_winsize.tp_row) {
888
                                /*
889
                                 * Corner case: regular character
890
                                 * outside scrolling region, but at the
891
                                 * bottom of the screen.
892
                                 */
893 0
                                teken_subr_do_putchar(t, &t->t_cursor,
894 0
                                    c, width);
895 0
                                return;
896
                        }
897
                }
898
899 2236
                tp.tp_col = 0;
900 2236
                teken_subr_do_putchar(t, &tp, c, width);
901
902 2236
                t->t_cursor.tp_row = tp.tp_row;
903 2236
                t->t_cursor.tp_col = width;
904 2236
                t->t_stateflags &= ~TS_WRAPPED;
905 2236
        } else {
906
                /* No line wrapping needed. */
907 5012530
                teken_subr_do_putchar(t, &t->t_cursor, c, width);
908 5012530
                t->t_cursor.tp_col += width;
909
910 5012530
                if (t->t_cursor.tp_col >= t->t_winsize.tp_col) {
911 30577
                        t->t_stateflags |= TS_WRAPPED;
912 30577
                        t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
913 30577
                } else {
914 4981953
                        t->t_stateflags &= ~TS_WRAPPED;
915
                }
916
        }
917
918 5015006
        teken_funcs_cursor(t);
919 5015246
}
920
921
static void
922 4160
teken_subr_reset_dec_mode(teken_t *t, unsigned int cmd)
923
{
924
925 4160
        switch (cmd) {
926
        case 1: /* Cursor keys mode. */
927 720
                t->t_stateflags &= ~TS_CURSORKEYS;
928 720
                break;
929
        case 2: /* DECANM: ANSI/VT52 mode. */
930
                teken_printf("DECRST VT52\n");
931 0
                break;
932
        case 3: /* 132 column mode. */
933 960
                teken_funcs_param(t, TP_132COLS, 0);
934 960
                teken_subr_reset_to_initial_state(t);
935 960
                break;
936
        case 5: /* Inverse video. */
937
                teken_printf("DECRST inverse video\n");
938 400
                break;
939
        case 6: /* Origin mode. */
940 560
                t->t_stateflags &= ~TS_ORIGIN;
941 560
                t->t_originreg.ts_begin = 0;
942 560
                t->t_originreg.ts_end = t->t_winsize.tp_row;
943 560
                t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
944 560
                t->t_stateflags &= ~TS_WRAPPED;
945 560
                teken_funcs_cursor(t);
946 560
                break;
947
        case 7: /* Autowrap mode. */
948 80
                t->t_stateflags &= ~TS_AUTOWRAP;
949 80
                break;
950
        case 8: /* Autorepeat mode. */
951 80
                teken_funcs_param(t, TP_AUTOREPEAT, 0);
952 80
                break;
953
        case 25: /* Hide cursor. */
954 560
                teken_funcs_param(t, TP_SHOWCURSOR, 0);
955 560
                break;
956
        case 40: /* Disallow 132 columns. */
957
                teken_printf("DECRST allow 132\n");
958 0
                break;
959
        case 45: /* Disable reverse wraparound. */
960
                teken_printf("DECRST reverse wraparound\n");
961 80
                break;
962
        case 47: /* Switch to alternate buffer. */
963
                teken_printf("Switch to alternate buffer\n");
964 0
                break;
965
        case 1000: /* Mouse input. */
966 0
                teken_funcs_param(t, TP_MOUSE, 0);
967 0
                break;
968
        default:
969
                teken_printf("Unknown DECRST: %u\n", cmd);
970 720
        }
971 4160
}
972
973
static void
974 800
teken_subr_reset_mode(teken_t *t, unsigned int cmd)
975
{
976
977 800
        switch (cmd) {
978
        case 4:
979 720
                t->t_stateflags &= ~TS_INSERT;
980 720
                break;
981
        default:
982
                teken_printf("Unknown reset mode: %u\n", cmd);
983 80
        }
984 800
}
985
986
static void
987 0
teken_subr_do_resize(teken_t *t)
988
{
989
990 0
        t->t_scrollreg.ts_begin = 0;
991 0
        t->t_scrollreg.ts_end = t->t_winsize.tp_row;
992 0
        t->t_originreg = t->t_scrollreg;
993 0
}
994
995
static void
996 9920
teken_subr_do_reset(teken_t *t)
997
{
998
999 9920
        t->t_curattr = t->t_defattr;
1000 9920
        t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
1001 9920
        t->t_scrollreg.ts_begin = 0;
1002 9920
        t->t_scrollreg.ts_end = t->t_winsize.tp_row;
1003 9920
        t->t_originreg = t->t_scrollreg;
1004 9920
        t->t_stateflags &= TS_8BIT|TS_CONS25;
1005 9920
        t->t_stateflags |= TS_AUTOWRAP;
1006
1007 9920
        t->t_scs[0] = teken_scs_us_ascii;
1008 9920
        t->t_scs[1] = teken_scs_us_ascii;
1009 9920
        t->t_curscs = 0;
1010
1011 9920
        teken_subr_save_cursor(t);
1012 9920
        teken_tab_default(t);
1013 9920
}
1014
1015
static void
1016 1440
teken_subr_reset_to_initial_state(teken_t *t)
1017
{
1018
1019 1440
        teken_subr_do_reset(t);
1020 1440
        teken_subr_erase_display(t, 2);
1021 1440
        teken_funcs_param(t, TP_SHOWCURSOR, 1);
1022 1440
        teken_funcs_cursor(t);
1023 1440
}
1024
1025
static void
1026 1600
teken_subr_restore_cursor(teken_t *t)
1027
{
1028
1029 1600
        t->t_cursor = t->t_saved_cursor;
1030 1600
        t->t_curattr = t->t_saved_curattr;
1031 1600
        t->t_scs[t->t_curscs] = t->t_saved_curscs;
1032 1600
        t->t_stateflags &= ~TS_WRAPPED;
1033
1034
        /* Get out of origin mode when the cursor is moved outside. */
1035 1600
        if (t->t_cursor.tp_row < t->t_originreg.ts_begin ||
1036 1600
            t->t_cursor.tp_row >= t->t_originreg.ts_end) {
1037 0
                t->t_stateflags &= ~TS_ORIGIN;
1038 0
                t->t_originreg.ts_begin = 0;
1039 0
                t->t_originreg.ts_end = t->t_winsize.tp_row;
1040 0
        }
1041
1042 1600
        teken_funcs_cursor(t);
1043 1600
}
1044
1045
static void
1046 23360
teken_subr_reverse_index(teken_t *t)
1047
{
1048
1049 23360
        if (t->t_cursor.tp_row > t->t_scrollreg.ts_begin) {
1050 13120
                t->t_cursor.tp_row--;
1051 13120
                t->t_stateflags &= ~TS_WRAPPED;
1052 13120
                teken_funcs_cursor(t);
1053 13120
        } else {
1054 10240
                teken_subr_do_scroll(t, -1);
1055
        }
1056 23360
}
1057
1058
static void
1059 11680
teken_subr_save_cursor(teken_t *t)
1060
{
1061
1062 11680
        t->t_saved_cursor = t->t_cursor;
1063 11680
        t->t_saved_curattr = t->t_curattr;
1064 11680
        t->t_saved_curscs = t->t_scs[t->t_curscs];
1065 11680
}
1066
1067
static void
1068 80
teken_subr_secondary_device_attributes(const teken_t *t, unsigned int request)
1069
{
1070
1071 80
        if (request == 0) {
1072 80
                const char response[] = "\x1B[>0;10;0c";
1073 80
                teken_funcs_respond(t, response, sizeof response - 1);
1074 80
        } else {
1075
                teken_printf("Unknown DA2\n");
1076
        }
1077 80
}
1078
1079
static void
1080 2440
teken_subr_set_dec_mode(teken_t *t, unsigned int cmd)
1081
{
1082
1083 2440
        switch (cmd) {
1084
        case 1: /* Cursor keys mode. */
1085 280
                t->t_stateflags |= TS_CURSORKEYS;
1086 280
                break;
1087
        case 2: /* DECANM: ANSI/VT52 mode. */
1088
                teken_printf("DECSET VT52\n");
1089 0
                break;
1090
        case 3: /* 132 column mode. */
1091 480
                teken_funcs_param(t, TP_132COLS, 1);
1092 480
                teken_subr_reset_to_initial_state(t);
1093 480
                break;
1094
        case 5: /* Inverse video. */
1095
                teken_printf("DECSET inverse video\n");
1096 160
                break;
1097
        case 6: /* Origin mode. */
1098 400
                t->t_stateflags |= TS_ORIGIN;
1099 400
                t->t_originreg = t->t_scrollreg;
1100 400
                t->t_cursor.tp_row = t->t_scrollreg.ts_begin;
1101 400
                t->t_cursor.tp_col = 0;
1102 400
                t->t_stateflags &= ~TS_WRAPPED;
1103 400
                teken_funcs_cursor(t);
1104 400
                break;
1105
        case 7: /* Autowrap mode. */
1106 320
                t->t_stateflags |= TS_AUTOWRAP;
1107 320
                break;
1108
        case 8: /* Autorepeat mode. */
1109 80
                teken_funcs_param(t, TP_AUTOREPEAT, 1);
1110 80
                break;
1111
        case 25: /* Display cursor. */
1112 560
                teken_funcs_param(t, TP_SHOWCURSOR, 1);
1113 560
                break;
1114
        case 40: /* Allow 132 columns. */
1115
                teken_printf("DECSET allow 132\n");
1116 80
                break;
1117
        case 45: /* Enable reverse wraparound. */
1118
                teken_printf("DECSET reverse wraparound\n");
1119 0
                break;
1120
        case 47: /* Switch to alternate buffer. */
1121
                teken_printf("Switch away from alternate buffer\n");
1122 0
                break;
1123
        case 1000: /* Mouse input. */
1124 0
                teken_funcs_param(t, TP_MOUSE, 1);
1125 0
                break;
1126
        default:
1127
                teken_printf("Unknown DECSET: %u\n", cmd);
1128 80
        }
1129 2440
}
1130
1131
static void
1132 160
teken_subr_set_mode(teken_t *t, unsigned int cmd)
1133
{
1134
1135 160
        switch (cmd) {
1136
        case 4:
1137
                teken_printf("Insert mode\n");
1138 160
                t->t_stateflags |= TS_INSERT;
1139 160
                break;
1140
        default:
1141
                teken_printf("Unknown set mode: %u\n", cmd);
1142 0
        }
1143 160
}
1144
1145
static void
1146 16903
teken_subr_set_graphic_rendition(teken_t *t, unsigned int ncmds,
1147
    const unsigned int cmds[])
1148
{
1149
        unsigned int i, n;
1150
1151
        /* No attributes means reset. */
1152 16903
        if (ncmds == 0) {
1153 7812
                t->t_curattr = t->t_defattr;
1154 7812
                return;
1155
        }
1156
1157 23302
        for (i = 0; i < ncmds; i++) {
1158 14211
                n = cmds[i];
1159
1160 14211
                switch (n) {
1161
                case 0: /* Reset. */
1162 3520
                        t->t_curattr = t->t_defattr;
1163 3520
                        break;
1164
                case 1: /* Bold. */
1165 4720
                        t->t_curattr.ta_format |= TF_BOLD;
1166 4720
                        break;
1167
                case 4: /* Underline. */
1168 1120
                        t->t_curattr.ta_format |= TF_UNDERLINE;
1169 1120
                        break;
1170
                case 5: /* Blink. */
1171 1120
                        t->t_curattr.ta_format |= TF_BLINK;
1172 1120
                        break;
1173
                case 7: /* Reverse. */
1174 3011
                        t->t_curattr.ta_format |= TF_REVERSE;
1175 3011
                        break;
1176
                case 22: /* Remove bold. */
1177 80
                        t->t_curattr.ta_format &= ~TF_BOLD;
1178 80
                        break;
1179
                case 24: /* Remove underline. */
1180 80
                        t->t_curattr.ta_format &= ~TF_UNDERLINE;
1181 80
                        break;
1182
                case 25: /* Remove blink. */
1183 80
                        t->t_curattr.ta_format &= ~TF_BLINK;
1184 80
                        break;
1185
                case 27: /* Remove reverse. */
1186 80
                        t->t_curattr.ta_format &= ~TF_REVERSE;
1187 80
                        break;
1188
                case 30: /* Set foreground color: black */
1189
                case 31: /* Set foreground color: red */
1190
                case 32: /* Set foreground color: green */
1191
                case 33: /* Set foreground color: brown */
1192
                case 34: /* Set foreground color: blue */
1193
                case 35: /* Set foreground color: magenta */
1194
                case 36: /* Set foreground color: cyan */
1195
                case 37: /* Set foreground color: white */
1196 80
                        t->t_curattr.ta_fgcolor = n - 30;
1197 80
                        break;
1198
                case 38: /* Set foreground color: 256 color mode */
1199 0
                        if (i + 2 >= ncmds || cmds[i + 1] != 5)
1200 0
                                continue;
1201 0
                        t->t_curattr.ta_fgcolor = cmds[i + 2];
1202 0
                        i += 2;
1203 0
                        break;
1204
                case 39: /* Set default foreground color. */
1205 0
                        t->t_curattr.ta_fgcolor = t->t_defattr.ta_fgcolor;
1206 0
                        break;
1207
                case 40: /* Set background color: black */
1208
                case 41: /* Set background color: red */
1209
                case 42: /* Set background color: green */
1210
                case 43: /* Set background color: brown */
1211
                case 44: /* Set background color: blue */
1212
                case 45: /* Set background color: magenta */
1213
                case 46: /* Set background color: cyan */
1214
                case 47: /* Set background color: white */
1215 80
                        t->t_curattr.ta_bgcolor = n - 40;
1216 80
                        break;
1217
                case 48: /* Set background color: 256 color mode */
1218 0
                        if (i + 2 >= ncmds || cmds[i + 1] != 5)
1219 0
                                continue;
1220 0
                        t->t_curattr.ta_bgcolor = cmds[i + 2];
1221 0
                        i += 2;
1222 0
                        break;
1223
                case 49: /* Set default background color. */
1224 80
                        t->t_curattr.ta_bgcolor = t->t_defattr.ta_bgcolor;
1225 80
                        break;
1226
                case 90: /* Set bright foreground color: black */
1227
                case 91: /* Set bright foreground color: red */
1228
                case 92: /* Set bright foreground color: green */
1229
                case 93: /* Set bright foreground color: brown */
1230
                case 94: /* Set bright foreground color: blue */
1231
                case 95: /* Set bright foreground color: magenta */
1232
                case 96: /* Set bright foreground color: cyan */
1233
                case 97: /* Set bright foreground color: white */
1234 80
                        t->t_curattr.ta_fgcolor = (n - 90) + 8;
1235 80
                        break;
1236
                case 100: /* Set bright background color: black */
1237
                case 101: /* Set bright background color: red */
1238
                case 102: /* Set bright background color: green */
1239
                case 103: /* Set bright background color: brown */
1240
                case 104: /* Set bright background color: blue */
1241
                case 105: /* Set bright background color: magenta */
1242
                case 106: /* Set bright background color: cyan */
1243
                case 107: /* Set bright background color: white */
1244 80
                        t->t_curattr.ta_bgcolor = (n - 100) + 8;
1245 80
                        break;
1246
                default:
1247
                        teken_printf("unsupported attribute %u\n", n);
1248 0
                }
1249 14211
        }
1250 16903
}
1251
1252
static void
1253 2240
teken_subr_set_top_and_bottom_margins(teken_t *t, unsigned int top,
1254
    unsigned int bottom)
1255
{
1256
1257
        /* Adjust top row number. */
1258 2240
        if (top > 0)
1259 1520
                top--;
1260
        /* Adjust bottom row number. */
1261 2240
        if (bottom == 0 || bottom > t->t_winsize.tp_row)
1262 720
                bottom = t->t_winsize.tp_row;
1263
1264
        /* Invalid arguments. */
1265 2240
        if (top >= bottom - 1) {
1266 0
                top = 0;
1267 0
                bottom = t->t_winsize.tp_row;
1268 0
        }
1269
1270
        /* Apply scrolling region. */
1271 2240
        t->t_scrollreg.ts_begin = top;
1272 2240
        t->t_scrollreg.ts_end = bottom;
1273 2240
        if (t->t_stateflags & TS_ORIGIN)
1274 400
                t->t_originreg = t->t_scrollreg;
1275
1276
        /* Home cursor to the top left of the scrolling region. */
1277 2240
        t->t_cursor.tp_row = t->t_originreg.ts_begin;
1278 2240
        t->t_cursor.tp_col = 0;
1279 2240
        t->t_stateflags &= ~TS_WRAPPED;
1280 2240
        teken_funcs_cursor(t);
1281 2240
}
1282
1283
static void
1284 4960
teken_subr_single_height_double_width_line(const teken_t *t)
1285
{
1286
1287 4960
        (void)t;
1288
        teken_printf("single height double width???\n");
1289 4960
}
1290
1291
static void
1292 1120
teken_subr_single_height_single_width_line(const teken_t *t)
1293
{
1294
1295 1120
        (void)t;
1296
        teken_printf("single height single width???\n");
1297 1120
}
1298
1299
static void
1300 0
teken_subr_string_terminator(const teken_t *t)
1301
{
1302
1303 0
        (void)t;
1304
        /*
1305
         * Strings are already terminated in teken_input_char() when ^[
1306
         * is inserted.
1307
         */
1308 0
}
1309
1310
static void
1311 1520
teken_subr_tab_clear(teken_t *t, unsigned int cmd)
1312
{
1313
1314 1520
        switch (cmd) {
1315
        case 0:
1316 1040
                teken_tab_clear(t, t->t_cursor.tp_col);
1317 1040
                break;
1318
        case 3:
1319 320
                memset(t->t_tabstops, 0, T_NUMCOL / 8);
1320 320
                break;
1321
        default:
1322 160
                break;
1323
        }
1324 1520
}
1325
1326
static void
1327 0
teken_subr_vertical_position_absolute(teken_t *t, unsigned int row)
1328
{
1329
1330 0
        row = (row - 1) + t->t_originreg.ts_begin;
1331 0
        t->t_cursor.tp_row = row < t->t_originreg.ts_end ?
1332 0
            row : t->t_originreg.ts_end - 1;
1333
1334 0
        t->t_stateflags &= ~TS_WRAPPED;
1335 0
        teken_funcs_cursor(t);
1336 0
}
1337
1338
static void
1339 4160
teken_subr_repeat_last_graphic_char(teken_t *t, unsigned int rpts)
1340
{
1341
1342 16480
        for (; t->t_last != 0 && rpts > 0; rpts--)
1343 12320
                teken_subr_regular_character(t, t->t_last);
1344 4160
}
1345