teken_subr.h revision 186687
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 186687 2009-01-01 23:22:01Z 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 if (t->t_cursor.tp_col == 0) 202 return; 203 204 t->t_cursor.tp_col--; 205 t->t_stateflags &= ~TS_WRAPPED; 206 207 teken_funcs_cursor(t); 208} 209 210static void 211teken_subr_bell(teken_t *t) 212{ 213 214 teken_funcs_bell(t); 215} 216 217static void 218teken_subr_carriage_return(teken_t *t) 219{ 220 221 t->t_cursor.tp_col = 0; 222 t->t_stateflags &= ~TS_WRAPPED; 223 teken_funcs_cursor(t); 224} 225 226static void 227teken_subr_cursor_backward(teken_t *t, unsigned int ncols) 228{ 229 230 if (ncols > t->t_cursor.tp_col) 231 t->t_cursor.tp_col = 0; 232 else 233 t->t_cursor.tp_col -= ncols; 234 t->t_stateflags &= ~TS_WRAPPED; 235 teken_funcs_cursor(t); 236} 237 238static void 239teken_subr_cursor_backward_tabulation(teken_t *t, unsigned int ntabs) 240{ 241 242 do { 243 /* Stop when we've reached the beginning of the line. */ 244 if (t->t_cursor.tp_col == 0) 245 break; 246 247 t->t_cursor.tp_col--; 248 249 /* Tab marker set. */ 250 if (teken_tab_isset(t, t->t_cursor.tp_col)) 251 ntabs--; 252 } while (ntabs > 0); 253} 254 255static void 256teken_subr_cursor_down(teken_t *t, unsigned int nrows) 257{ 258 259 if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) 260 t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1; 261 else 262 t->t_cursor.tp_row += nrows; 263 t->t_stateflags &= ~TS_WRAPPED; 264 teken_funcs_cursor(t); 265} 266 267static void 268teken_subr_cursor_forward(teken_t *t, unsigned int ncols) 269{ 270 271 if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) 272 t->t_cursor.tp_col = t->t_winsize.tp_col - 1; 273 else 274 t->t_cursor.tp_col += ncols; 275 t->t_stateflags &= ~TS_WRAPPED; 276 teken_funcs_cursor(t); 277} 278 279static void 280teken_subr_cursor_forward_tabulation(teken_t *t, unsigned int ntabs) 281{ 282 283 do { 284 /* Stop when we've reached the end of the line. */ 285 if (t->t_cursor.tp_col == t->t_winsize.tp_col - 1) 286 break; 287 288 t->t_cursor.tp_col++; 289 290 /* Tab marker set. */ 291 if (teken_tab_isset(t, t->t_cursor.tp_col)) 292 ntabs--; 293 } while (ntabs > 0); 294} 295 296static void 297teken_subr_cursor_next_line(teken_t *t, unsigned int ncols) 298{ 299 300 t->t_cursor.tp_col = 0; 301 teken_subr_cursor_down(t, ncols); 302} 303 304static void 305teken_subr_cursor_position(teken_t *t, unsigned int row, unsigned int col) 306{ 307 308 t->t_cursor.tp_row = t->t_originreg.ts_begin + row - 1; 309 if (row >= t->t_originreg.ts_end) 310 t->t_cursor.tp_row = t->t_originreg.ts_end - 1; 311 312 t->t_cursor.tp_col = col - 1; 313 if (t->t_cursor.tp_col >= t->t_winsize.tp_col) 314 t->t_cursor.tp_col = t->t_winsize.tp_col - 1; 315 316 t->t_stateflags &= ~TS_WRAPPED; 317 teken_funcs_cursor(t); 318} 319 320static void 321teken_subr_cursor_position_report(teken_t *t, unsigned int cmd) 322{ 323 char response[18] = "\x1B["; 324 ssize_t len; 325 326 len = teken_subr_do_cpr(t, cmd, response + 2); 327 if (len < 0) 328 return; 329 330 teken_funcs_respond(t, response, len + 2); 331} 332 333static void 334teken_subr_cursor_previous_line(teken_t *t, unsigned int ncols) 335{ 336 337 t->t_cursor.tp_col = 0; 338 teken_subr_cursor_up(t, ncols); 339} 340 341static void 342teken_subr_cursor_up(teken_t *t, unsigned int nrows) 343{ 344 345 if (t->t_scrollreg.ts_begin + nrows >= t->t_cursor.tp_row) 346 t->t_cursor.tp_row = t->t_scrollreg.ts_begin; 347 else 348 t->t_cursor.tp_row -= nrows; 349 t->t_stateflags &= ~TS_WRAPPED; 350 teken_funcs_cursor(t); 351} 352 353static void 354teken_subr_delete_character(teken_t *t, unsigned int ncols) 355{ 356 teken_rect_t tr; 357 358 tr.tr_begin.tp_row = t->t_cursor.tp_row; 359 tr.tr_end.tp_row = t->t_cursor.tp_row + 1; 360 tr.tr_end.tp_col = t->t_winsize.tp_col; 361 362 if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) { 363 tr.tr_begin.tp_col = t->t_cursor.tp_col; 364 } else { 365 /* Copy characters to the left. */ 366 tr.tr_begin.tp_col = t->t_cursor.tp_col + ncols; 367 teken_funcs_copy(t, &tr, &t->t_cursor); 368 369 tr.tr_begin.tp_col = t->t_winsize.tp_col - ncols; 370 } 371 372 /* Blank trailing columns. */ 373 teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 374} 375 376static void 377teken_subr_delete_line(teken_t *t, unsigned int nrows) 378{ 379 teken_rect_t tr; 380 381 tr.tr_begin.tp_col = 0; 382 tr.tr_end.tp_row = t->t_scrollreg.ts_end; 383 tr.tr_end.tp_col = t->t_winsize.tp_col; 384 385 if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) { 386 tr.tr_begin.tp_row = t->t_cursor.tp_row; 387 } else { 388 teken_pos_t tp; 389 390 /* Copy rows up. */ 391 tr.tr_begin.tp_row = t->t_cursor.tp_row + nrows; 392 tp.tp_row = t->t_cursor.tp_row; 393 tp.tp_col = 0; 394 teken_funcs_copy(t, &tr, &tp); 395 396 tr.tr_begin.tp_row = t->t_scrollreg.ts_end - nrows; 397 } 398 399 /* Blank trailing rows. */ 400 teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 401} 402 403static void 404teken_subr_device_control_string(teken_t *t __unused) 405{ 406 407 teken_printf("device control string???\n"); 408} 409 410static void 411teken_subr_device_status_report(teken_t *t, unsigned int cmd) 412{ 413 char response[19] = "\x1B[?"; 414 ssize_t len; 415 416 len = teken_subr_do_cpr(t, cmd, response + 3); 417 if (len < 0) 418 return; 419 420 teken_funcs_respond(t, response, len + 3); 421} 422 423static void 424teken_subr_double_height_double_width_line_top(teken_t *t __unused) 425{ 426 427 teken_printf("double height double width top\n"); 428} 429 430static void 431teken_subr_double_height_double_width_line_bottom(teken_t *t __unused) 432{ 433 434 teken_printf("double height double width bottom\n"); 435} 436 437static void 438teken_subr_erase_character(teken_t *t, unsigned int ncols) 439{ 440 teken_rect_t tr; 441 442 tr.tr_begin = t->t_cursor; 443 tr.tr_end.tp_row = t->t_cursor.tp_row + 1; 444 445 if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) 446 tr.tr_end.tp_col = t->t_winsize.tp_col; 447 else 448 tr.tr_end.tp_col = t->t_cursor.tp_col + ncols; 449 450 teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 451} 452 453static void 454teken_subr_erase_display(teken_t *t, unsigned int mode) 455{ 456 teken_rect_t r; 457 458 r.tr_begin.tp_col = 0; 459 r.tr_end.tp_col = t->t_winsize.tp_col; 460 461 switch (mode) { 462 case 1: /* Erase from the top to the cursor. */ 463 teken_subr_erase_line(t, 1); 464 465 /* Erase lines above. */ 466 if (t->t_cursor.tp_row == 0) 467 return; 468 r.tr_begin.tp_row = 0; 469 r.tr_end.tp_row = t->t_cursor.tp_row; 470 break; 471 case 2: /* Erase entire display. */ 472 r.tr_begin.tp_row = 0; 473 r.tr_end.tp_row = t->t_winsize.tp_row; 474 break; 475 default: /* Erase from cursor to the bottom. */ 476 teken_subr_erase_line(t, 0); 477 478 /* Erase lines below. */ 479 if (t->t_cursor.tp_row == t->t_winsize.tp_row - 1) 480 return; 481 r.tr_begin.tp_row = t->t_cursor.tp_row + 1; 482 r.tr_end.tp_row = t->t_winsize.tp_row; 483 break; 484 } 485 486 teken_funcs_fill(t, &r, BLANK, &t->t_curattr); 487} 488 489static void 490teken_subr_erase_line(teken_t *t, unsigned int mode) 491{ 492 teken_rect_t r; 493 494 r.tr_begin.tp_row = t->t_cursor.tp_row; 495 r.tr_end.tp_row = t->t_cursor.tp_row + 1; 496 497 switch (mode) { 498 case 1: /* Erase from the beginning of the line to the cursor. */ 499 r.tr_begin.tp_col = 0; 500 r.tr_end.tp_col = t->t_cursor.tp_col + 1; 501 break; 502 case 2: /* Erase entire line. */ 503 r.tr_begin.tp_col = 0; 504 r.tr_end.tp_col = t->t_winsize.tp_col; 505 break; 506 default: /* Erase from cursor to the end of the line. */ 507 r.tr_begin.tp_col = t->t_cursor.tp_col; 508 r.tr_end.tp_col = t->t_winsize.tp_col; 509 break; 510 } 511 512 teken_funcs_fill(t, &r, BLANK, &t->t_curattr); 513} 514 515static void 516teken_subr_horizontal_position_absolute(teken_t *t, unsigned int col) 517{ 518 519 t->t_cursor.tp_col = col - 1; 520 if (t->t_cursor.tp_col >= t->t_winsize.tp_col) 521 t->t_cursor.tp_col = t->t_winsize.tp_col - 1; 522 523 t->t_stateflags &= ~TS_WRAPPED; 524 teken_funcs_cursor(t); 525} 526 527static void 528teken_subr_horizontal_tab(teken_t *t) 529{ 530 teken_rect_t tr; 531 532 tr.tr_begin = t->t_cursor; 533 teken_subr_cursor_forward_tabulation(t, 1); 534 tr.tr_end.tp_row = tr.tr_begin.tp_row + 1; 535 tr.tr_end.tp_col = t->t_cursor.tp_col; 536 537 /* Blank region that we skipped. */ 538 if (tr.tr_end.tp_col > tr.tr_begin.tp_col) 539 teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 540} 541 542static void 543teken_subr_horizontal_tab_set(teken_t *t) 544{ 545 546 teken_tab_set(t, t->t_cursor.tp_col); 547} 548 549static void 550teken_subr_index(teken_t *t) 551{ 552 553 if (t->t_cursor.tp_row < t->t_scrollreg.ts_end - 1) { 554 t->t_cursor.tp_row++; 555 t->t_stateflags &= ~TS_WRAPPED; 556 teken_funcs_cursor(t); 557 } else { 558 teken_subr_do_scroll(t, 1); 559 } 560} 561 562static void 563teken_subr_insert_character(teken_t *t, unsigned int ncols) 564{ 565 teken_rect_t tr; 566 567 tr.tr_begin = t->t_cursor; 568 tr.tr_end.tp_row = t->t_cursor.tp_row + 1; 569 570 if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) { 571 tr.tr_end.tp_col = t->t_winsize.tp_col; 572 } else { 573 teken_pos_t tp; 574 575 /* Copy characters to the right. */ 576 tr.tr_end.tp_col = t->t_winsize.tp_col - ncols; 577 tp.tp_row = t->t_cursor.tp_row; 578 tp.tp_col = t->t_cursor.tp_col + ncols; 579 teken_funcs_copy(t, &tr, &tp); 580 581 tr.tr_end.tp_col = t->t_cursor.tp_col + ncols; 582 } 583 584 /* Blank current location. */ 585 teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 586} 587 588static void 589teken_subr_insert_line(teken_t *t, unsigned int nrows) 590{ 591 teken_rect_t tr; 592 593 tr.tr_begin.tp_row = t->t_cursor.tp_row; 594 tr.tr_begin.tp_col = 0; 595 tr.tr_end.tp_col = t->t_winsize.tp_col; 596 597 if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) { 598 tr.tr_end.tp_row = t->t_scrollreg.ts_end; 599 } else { 600 teken_pos_t tp; 601 602 /* Copy lines down. */ 603 tr.tr_end.tp_row = t->t_scrollreg.ts_end - nrows; 604 tp.tp_row = t->t_cursor.tp_row + nrows; 605 tp.tp_col = 0; 606 teken_funcs_copy(t, &tr, &tp); 607 608 tr.tr_end.tp_row = t->t_cursor.tp_row + nrows; 609 } 610 611 /* Blank current location. */ 612 teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 613} 614 615static void 616teken_subr_keypad_application_mode(teken_t *t) 617{ 618 619 teken_funcs_param(t, TP_KEYPADAPP, 1); 620} 621 622static void 623teken_subr_keypad_numeric_mode(teken_t *t) 624{ 625 626 teken_funcs_param(t, TP_KEYPADAPP, 0); 627} 628 629static void 630teken_subr_newline(teken_t *t) 631{ 632 633 t->t_cursor.tp_row++; 634 635 if (t->t_cursor.tp_row >= t->t_scrollreg.ts_end) { 636 teken_subr_do_scroll(t, 1); 637 t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1; 638 } 639 640 t->t_stateflags &= ~TS_WRAPPED; 641 teken_funcs_cursor(t); 642} 643 644static void 645teken_subr_next_line(teken_t *t) 646{ 647 648 t->t_cursor.tp_col = 0; 649 teken_subr_newline(t); 650} 651 652static void 653teken_subr_pan_down(teken_t *t, unsigned int nrows) 654{ 655 656 teken_subr_do_scroll(t, (int)nrows); 657} 658 659static void 660teken_subr_pan_up(teken_t *t, unsigned int nrows) 661{ 662 663 teken_subr_do_scroll(t, -(int)nrows); 664} 665 666static void 667teken_subr_primary_device_attributes(teken_t *t, unsigned int request) 668{ 669 670 if (request == 0) { 671 const char response[] = "\x1B[?1;2c"; 672 673 teken_funcs_respond(t, response, sizeof response - 1); 674 } else { 675 teken_printf("Unknown DA1\n"); 676 } 677} 678 679static void 680teken_subr_do_putchar(teken_t *t, const teken_pos_t *tp, teken_char_t c, 681 int width) 682{ 683 684 if (t->t_stateflags & TS_INSERT && 685 tp->tp_col < t->t_winsize.tp_col - width) { 686 teken_rect_t ctr; 687 teken_pos_t ctp; 688 689 /* Insert mode. Move existing characters to the right. */ 690 ctr.tr_begin = *tp; 691 ctr.tr_end.tp_row = tp->tp_row + 1; 692 ctr.tr_end.tp_col = t->t_winsize.tp_col - width; 693 ctp.tp_row = tp->tp_row; 694 ctp.tp_col = tp->tp_col + width; 695 teken_funcs_copy(t, &ctr, &ctp); 696 } 697 698 teken_funcs_putchar(t, tp, c, &t->t_curattr); 699} 700 701static void 702teken_subr_regular_character(teken_t *t, teken_char_t c) 703{ 704 int width; 705 706 /* XXX: Don't process zero-width characters yet. */ 707 width = teken_wcwidth(c); 708 if (width <= 0) 709 return; 710 711 if (t->t_cursor.tp_col == t->t_winsize.tp_col - 1 && 712 (t->t_stateflags & (TS_WRAPPED|TS_AUTOWRAP)) == 713 (TS_WRAPPED|TS_AUTOWRAP)) { 714 teken_pos_t tp; 715 716 /* Perform line wrapping. */ 717 718 if (t->t_cursor.tp_row == t->t_scrollreg.ts_end - 1) { 719 /* Perform scrolling. */ 720 teken_subr_do_scroll(t, 1); 721 tp.tp_row = t->t_scrollreg.ts_end - 1; 722 } else { 723 /* No scrolling needed. */ 724 tp.tp_row = t->t_cursor.tp_row + 1; 725 if (tp.tp_row == t->t_winsize.tp_row) { 726 /* 727 * Corner case: regular character 728 * outside scrolling region, but at the 729 * bottom of the screen. 730 */ 731 teken_subr_do_putchar(t, &t->t_cursor, 732 c, width); 733 return; 734 } 735 } 736 737 tp.tp_col = 0; 738 teken_subr_do_putchar(t, &tp, c, width); 739 740 t->t_cursor.tp_row = tp.tp_row; 741 t->t_cursor.tp_col = width; 742 t->t_stateflags &= ~TS_WRAPPED; 743 } else { 744 /* No line wrapping needed. */ 745 teken_subr_do_putchar(t, &t->t_cursor, c, width); 746 t->t_cursor.tp_col += width; 747 748 if (t->t_cursor.tp_col >= t->t_winsize.tp_col) { 749 t->t_stateflags |= TS_WRAPPED; 750 t->t_cursor.tp_col = t->t_winsize.tp_col - 1; 751 } else { 752 t->t_stateflags &= ~TS_WRAPPED; 753 } 754 } 755 756 teken_funcs_cursor(t); 757} 758 759static void 760teken_subr_reset_dec_mode(teken_t *t, unsigned int cmd) 761{ 762 763 switch (cmd) { 764 case 1: /* Cursor keys mode. */ 765 teken_funcs_param(t, TP_CURSORKEYS, 0); 766 break; 767 case 2: /* DECANM: ANSI/VT52 mode. */ 768 teken_printf("DECRST VT52\n"); 769 break; 770 case 3: /* 132 column mode. */ 771 teken_funcs_param(t, TP_132COLS, 0); 772 teken_subr_reset_to_initial_state(t); 773 break; 774 case 5: /* Inverse video. */ 775 teken_printf("DECRST inverse video\n"); 776 break; 777 case 6: /* Origin mode. */ 778 t->t_stateflags &= ~TS_ORIGIN; 779 t->t_originreg.ts_begin = 0; 780 t->t_originreg.ts_end = t->t_winsize.tp_row; 781 t->t_cursor.tp_row = t->t_cursor.tp_col = 0; 782 t->t_stateflags &= ~TS_WRAPPED; 783 teken_funcs_cursor(t); 784 break; 785 case 7: /* Autowrap mode. */ 786 t->t_stateflags &= ~TS_AUTOWRAP; 787 break; 788 case 8: /* Autorepeat mode. */ 789 teken_funcs_param(t, TP_AUTOREPEAT, 0); 790 break; 791 case 25: /* Hide cursor. */ 792 teken_funcs_param(t, TP_SHOWCURSOR, 0); 793 break; 794 case 40: /* Disallow 132 columns. */ 795 teken_printf("DECRST allow 132\n"); 796 break; 797 case 45: /* Disable reverse wraparound. */ 798 teken_printf("DECRST reverse wraparound\n"); 799 break; 800 case 47: /* Switch to alternate buffer. */ 801 teken_printf("Switch to alternate buffer\n"); 802 break; 803 default: 804 teken_printf("Unknown DECRST: %u\n", cmd); 805 } 806} 807 808static void 809teken_subr_reset_mode(teken_t *t, unsigned int cmd) 810{ 811 812 switch (cmd) { 813 case 4: 814 t->t_stateflags &= ~TS_INSERT; 815 break; 816 default: 817 teken_printf("Unknown reset mode: %u\n", cmd); 818 } 819} 820 821static void 822teken_subr_do_reset(teken_t *t) 823{ 824 825 t->t_curattr = t->t_saved_curattr = t->t_defattr; 826 t->t_cursor.tp_row = t->t_cursor.tp_col = 0; 827 t->t_saved_cursor = t->t_cursor; 828 t->t_stateflags = TS_AUTOWRAP; 829 830 teken_tab_default(t); 831} 832 833static void 834teken_subr_reset_to_initial_state(teken_t *t) 835{ 836 837 teken_subr_do_reset(t); 838 teken_subr_erase_display(t, 2); 839 teken_funcs_cursor(t); 840} 841 842static void 843teken_subr_restore_cursor(teken_t *t) 844{ 845 846 t->t_cursor = t->t_saved_cursor; 847 t->t_curattr = t->t_saved_curattr; 848 t->t_stateflags &= ~TS_WRAPPED; 849 teken_funcs_cursor(t); 850} 851 852static void 853teken_subr_reverse_index(teken_t *t) 854{ 855 856 if (t->t_cursor.tp_row > t->t_scrollreg.ts_begin) { 857 t->t_cursor.tp_row--; 858 t->t_stateflags &= ~TS_WRAPPED; 859 teken_funcs_cursor(t); 860 } else { 861 teken_subr_do_scroll(t, -1); 862 } 863} 864 865static void 866teken_subr_save_cursor(teken_t *t) 867{ 868 869 t->t_saved_cursor = t->t_cursor; 870 t->t_saved_curattr = t->t_curattr; 871} 872 873static void 874teken_subr_scs(teken_t *t __unused) 875{ 876 877 teken_printf("scs???\n"); 878} 879 880static void 881teken_subr_secondary_device_attributes(teken_t *t, unsigned int request) 882{ 883 884 if (request == 0) { 885 const char response[] = "\x1B[>0;10;0c"; 886 teken_funcs_respond(t, response, sizeof response - 1); 887 } else { 888 teken_printf("Unknown DA2\n"); 889 } 890} 891 892static void 893teken_subr_set_dec_mode(teken_t *t, unsigned int cmd) 894{ 895 896 switch (cmd) { 897 case 1: /* Cursor keys mode. */ 898 teken_funcs_param(t, TP_CURSORKEYS, 1); 899 break; 900 case 2: /* DECANM: ANSI/VT52 mode. */ 901 teken_printf("DECSET VT52\n"); 902 break; 903 case 3: /* 132 column mode. */ 904 teken_funcs_param(t, TP_132COLS, 1); 905 teken_subr_reset_to_initial_state(t); 906 break; 907 case 5: /* Inverse video. */ 908 teken_printf("DECSET inverse video\n"); 909 break; 910 case 6: /* Origin mode. */ 911 t->t_stateflags |= TS_ORIGIN; 912 t->t_originreg = t->t_scrollreg; 913 t->t_cursor.tp_row = t->t_scrollreg.ts_begin; 914 t->t_cursor.tp_col = 0; 915 t->t_stateflags &= ~TS_WRAPPED; 916 teken_funcs_cursor(t); 917 break; 918 case 7: /* Autowrap mode. */ 919 t->t_stateflags |= TS_AUTOWRAP; 920 break; 921 case 8: /* Autorepeat mode. */ 922 teken_funcs_param(t, TP_AUTOREPEAT, 1); 923 break; 924 case 25: /* Display cursor. */ 925 teken_funcs_param(t, TP_SHOWCURSOR, 1); 926 break; 927 case 40: /* Allow 132 columns. */ 928 teken_printf("DECSET allow 132\n"); 929 break; 930 case 45: /* Enable reverse wraparound. */ 931 teken_printf("DECSET reverse wraparound\n"); 932 break; 933 case 47: /* Switch to alternate buffer. */ 934 teken_printf("Switch away from alternate buffer\n"); 935 break; 936 default: 937 teken_printf("Unknown DECSET: %u\n", cmd); 938 } 939} 940 941static void 942teken_subr_set_mode(teken_t *t, unsigned int cmd) 943{ 944 945 switch (cmd) { 946 case 4: 947 teken_printf("Insert mode\n"); 948 t->t_stateflags |= TS_INSERT; 949 break; 950 default: 951 teken_printf("Unknown set mode: %u\n", cmd); 952 } 953} 954 955static void 956teken_subr_set_graphic_rendition(teken_t *t, unsigned int ncmds, 957 unsigned int cmds[]) 958{ 959 unsigned int i, n; 960 961 /* No attributes means reset. */ 962 if (ncmds == 0) { 963 t->t_curattr = t->t_defattr; 964 return; 965 } 966 967 for (i = 0; i < ncmds; i++) { 968 n = cmds[i]; 969 970 switch (n) { 971 case 0: /* Reset. */ 972 t->t_curattr = t->t_defattr; 973 break; 974 case 1: /* Bold. */ 975 t->t_curattr.ta_format |= TF_BOLD; 976 break; 977 case 4: /* Underline. */ 978 t->t_curattr.ta_format |= TF_UNDERLINE; 979 break; 980 case 5: /* Blink. */ 981 t->t_curattr.ta_format |= TF_BLINK; 982 break; 983 case 7: /* Reverse. */ 984 t->t_curattr.ta_format |= TF_REVERSE; 985 break; 986 case 22: /* Remove bold. */ 987 t->t_curattr.ta_format &= ~TF_BOLD; 988 break; 989 case 24: /* Remove underline. */ 990 t->t_curattr.ta_format &= ~TF_UNDERLINE; 991 break; 992 case 25: /* Remove blink. */ 993 t->t_curattr.ta_format &= ~TF_BLINK; 994 break; 995 case 27: /* Remove reverse. */ 996 t->t_curattr.ta_format &= ~TF_REVERSE; 997 break; 998 case 30: /* Set foreground color: black */ 999 case 31: /* Set foreground color: red */ 1000 case 32: /* Set foreground color: green */ 1001 case 33: /* Set foreground color: brown */ 1002 case 34: /* Set foreground color: blue */ 1003 case 35: /* Set foreground color: magenta */ 1004 case 36: /* Set foreground color: cyan */ 1005 case 37: /* Set foreground color: white */ 1006 t->t_curattr.ta_fgcolor = n - 30; 1007 break; 1008 case 39: /* Set default foreground color. */ 1009 t->t_curattr.ta_fgcolor = t->t_defattr.ta_fgcolor; 1010 break; 1011 case 40: /* Set background color: black */ 1012 case 41: /* Set background color: red */ 1013 case 42: /* Set background color: green */ 1014 case 43: /* Set background color: brown */ 1015 case 44: /* Set background color: blue */ 1016 case 45: /* Set background color: magenta */ 1017 case 46: /* Set background color: cyan */ 1018 case 47: /* Set background color: white */ 1019 t->t_curattr.ta_bgcolor = n - 40; 1020 break; 1021 case 49: /* Set default background color. */ 1022 t->t_curattr.ta_bgcolor = t->t_defattr.ta_bgcolor; 1023 break; 1024 default: 1025 teken_printf("unsupported attribute %u\n", n); 1026 } 1027 } 1028} 1029 1030static void 1031teken_subr_set_top_and_bottom_margins(teken_t *t, unsigned int top, 1032 unsigned int bottom) 1033{ 1034 1035 /* Adjust top row number. */ 1036 if (top > 0) 1037 top--; 1038 /* Adjust bottom row number. */ 1039 if (bottom == 0 || bottom > t->t_winsize.tp_row) 1040 bottom = t->t_winsize.tp_row; 1041 1042 /* Invalid arguments. */ 1043 if (top >= bottom - 1) { 1044 top = 0; 1045 bottom = t->t_winsize.tp_row; 1046 } 1047 1048 t->t_scrollreg.ts_begin = top; 1049 t->t_scrollreg.ts_end = bottom; 1050 if (t->t_stateflags & TS_ORIGIN) { 1051 /* XXX: home cursor? */ 1052 t->t_originreg = t->t_scrollreg; 1053 t->t_cursor.tp_row = t->t_originreg.ts_begin; 1054 t->t_cursor.tp_col = 0; 1055 t->t_stateflags &= ~TS_WRAPPED; 1056 teken_funcs_cursor(t); 1057 } 1058} 1059 1060static void 1061teken_subr_single_height_double_width_line(teken_t *t __unused) 1062{ 1063 1064 teken_printf("single height double width???\n"); 1065} 1066 1067static void 1068teken_subr_single_height_single_width_line(teken_t *t __unused) 1069{ 1070 1071 teken_printf("single height single width???\n"); 1072} 1073 1074static void 1075teken_subr_string_terminator(teken_t *t __unused) 1076{ 1077 1078 teken_printf("string terminator???\n"); 1079} 1080 1081static void 1082teken_subr_tab_clear(teken_t *t, unsigned int cmd) 1083{ 1084 1085 switch (cmd) { 1086 case 0: 1087 teken_tab_clear(t, t->t_cursor.tp_col); 1088 break; 1089 case 3: 1090 memset(&t->t_tabstops, 0, T_NUMCOL / 8); 1091 break; 1092 } 1093} 1094 1095static void 1096teken_subr_vertical_position_absolute(teken_t *t, unsigned int row) 1097{ 1098 1099 t->t_cursor.tp_row = t->t_originreg.ts_begin + row - 1; 1100 if (row >= t->t_originreg.ts_end) 1101 t->t_cursor.tp_row = t->t_originreg.ts_end - 1; 1102 1103 1104 t->t_stateflags &= ~TS_WRAPPED; 1105 teken_funcs_cursor(t); 1106} 1107