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