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