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