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