1186681Sed/*- 2186681Sed * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org> 3186681Sed * All rights reserved. 4186681Sed * 5186681Sed * Redistribution and use in source and binary forms, with or without 6186681Sed * modification, are permitted provided that the following conditions 7186681Sed * are met: 8186681Sed * 1. Redistributions of source code must retain the above copyright 9186681Sed * notice, this list of conditions and the following disclaimer. 10186681Sed * 2. Redistributions in binary form must reproduce the above copyright 11186681Sed * notice, this list of conditions and the following disclaimer in the 12186681Sed * documentation and/or other materials provided with the distribution. 13186681Sed * 14186681Sed * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15186681Sed * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16186681Sed * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17186681Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18186681Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19186681Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20186681Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21186681Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22186681Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23186681Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24186681Sed * SUCH DAMAGE. 25186681Sed * 26186681Sed * $FreeBSD$ 27186681Sed */ 28186681Sed 29186681Sedstatic void teken_subr_cursor_up(teken_t *, unsigned int); 30186681Sedstatic void teken_subr_erase_line(teken_t *, unsigned int); 31186681Sedstatic void teken_subr_regular_character(teken_t *, teken_char_t); 32186681Sedstatic void teken_subr_reset_to_initial_state(teken_t *); 33187469Sedstatic void teken_subr_save_cursor(teken_t *); 34186681Sed 35186681Sedstatic inline int 36186681Sedteken_tab_isset(teken_t *t, unsigned int col) 37186681Sed{ 38186681Sed unsigned int b, o; 39186681Sed 40190157Sed if (col >= T_NUMCOL) 41190158Sed return ((col % 8) == 0); 42186681Sed 43186681Sed b = col / (sizeof(unsigned int) * 8); 44186681Sed o = col % (sizeof(unsigned int) * 8); 45186681Sed 46186681Sed return (t->t_tabstops[b] & (1 << o)); 47186681Sed} 48186681Sed 49186681Sedstatic inline void 50186681Sedteken_tab_clear(teken_t *t, unsigned int col) 51186681Sed{ 52186681Sed unsigned int b, o; 53186681Sed 54190157Sed if (col >= T_NUMCOL) 55190157Sed return; 56186681Sed 57186681Sed b = col / (sizeof(unsigned int) * 8); 58186681Sed o = col % (sizeof(unsigned int) * 8); 59186681Sed 60186681Sed t->t_tabstops[b] &= ~(1 << o); 61186681Sed} 62186681Sed 63186681Sedstatic inline void 64186681Sedteken_tab_set(teken_t *t, unsigned int col) 65186681Sed{ 66186681Sed unsigned int b, o; 67186681Sed 68190157Sed if (col >= T_NUMCOL) 69190157Sed return; 70186681Sed 71186681Sed b = col / (sizeof(unsigned int) * 8); 72186681Sed o = col % (sizeof(unsigned int) * 8); 73186681Sed 74186681Sed t->t_tabstops[b] |= 1 << o; 75186681Sed} 76186681Sed 77186681Sedstatic void 78186681Sedteken_tab_default(teken_t *t) 79186681Sed{ 80186681Sed unsigned int i; 81186681Sed 82186681Sed memset(&t->t_tabstops, 0, T_NUMCOL / 8); 83186681Sed 84186681Sed for (i = 8; i < T_NUMCOL; i += 8) 85186681Sed teken_tab_set(t, i); 86186681Sed} 87186681Sed 88186681Sedstatic void 89186681Sedteken_subr_do_scroll(teken_t *t, int amount) 90186681Sed{ 91186681Sed teken_rect_t tr; 92186681Sed teken_pos_t tp; 93186681Sed 94186681Sed teken_assert(t->t_cursor.tp_row <= t->t_winsize.tp_row); 95186681Sed teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row); 96186681Sed teken_assert(amount != 0); 97186681Sed 98186681Sed /* Copy existing data 1 line up. */ 99186681Sed if (amount > 0) { 100186681Sed /* Scroll down. */ 101186681Sed 102186681Sed /* Copy existing data up. */ 103186681Sed if (t->t_scrollreg.ts_begin + amount < t->t_scrollreg.ts_end) { 104186681Sed tr.tr_begin.tp_row = t->t_scrollreg.ts_begin + amount; 105186681Sed tr.tr_begin.tp_col = 0; 106186681Sed tr.tr_end.tp_row = t->t_scrollreg.ts_end; 107186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 108186681Sed tp.tp_row = t->t_scrollreg.ts_begin; 109186681Sed tp.tp_col = 0; 110186681Sed teken_funcs_copy(t, &tr, &tp); 111186681Sed 112186681Sed tr.tr_begin.tp_row = t->t_scrollreg.ts_end - amount; 113186681Sed } else { 114186681Sed tr.tr_begin.tp_row = t->t_scrollreg.ts_begin; 115186681Sed } 116186681Sed 117186681Sed /* Clear the last lines. */ 118186681Sed tr.tr_begin.tp_col = 0; 119186681Sed tr.tr_end.tp_row = t->t_scrollreg.ts_end; 120186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 121186681Sed teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 122186681Sed } else { 123186681Sed /* Scroll up. */ 124186681Sed amount = -amount; 125186681Sed 126186681Sed /* Copy existing data down. */ 127186681Sed if (t->t_scrollreg.ts_begin + amount < t->t_scrollreg.ts_end) { 128186681Sed tr.tr_begin.tp_row = t->t_scrollreg.ts_begin; 129186681Sed tr.tr_begin.tp_col = 0; 130186681Sed tr.tr_end.tp_row = t->t_scrollreg.ts_end - amount; 131186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 132186681Sed tp.tp_row = t->t_scrollreg.ts_begin + amount; 133186681Sed tp.tp_col = 0; 134186681Sed teken_funcs_copy(t, &tr, &tp); 135186681Sed 136186681Sed tr.tr_end.tp_row = t->t_scrollreg.ts_begin + amount; 137186681Sed } else { 138186681Sed tr.tr_end.tp_row = t->t_scrollreg.ts_end; 139186681Sed } 140186681Sed 141186681Sed /* Clear the first lines. */ 142186681Sed tr.tr_begin.tp_row = t->t_scrollreg.ts_begin; 143186681Sed tr.tr_begin.tp_col = 0; 144186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 145186681Sed teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 146186681Sed } 147186681Sed} 148186681Sed 149186681Sedstatic ssize_t 150186681Sedteken_subr_do_cpr(teken_t *t, unsigned int cmd, char response[16]) 151186681Sed{ 152186681Sed 153186681Sed switch (cmd) { 154186681Sed case 5: /* Operating status. */ 155186681Sed strcpy(response, "0n"); 156186681Sed return (2); 157186681Sed case 6: { /* Cursor position. */ 158186681Sed int len; 159186681Sed 160186681Sed len = snprintf(response, 16, "%u;%uR", 161186681Sed (t->t_cursor.tp_row - t->t_originreg.ts_begin) + 1, 162186681Sed t->t_cursor.tp_col + 1); 163186681Sed 164186681Sed if (len >= 16) 165186681Sed return (-1); 166186681Sed return (len); 167186681Sed } 168186681Sed case 15: /* Printer status. */ 169186681Sed strcpy(response, "13n"); 170186681Sed return (3); 171186681Sed case 25: /* UDK status. */ 172186681Sed strcpy(response, "20n"); 173186681Sed return (3); 174186681Sed case 26: /* Keyboard status. */ 175186681Sed strcpy(response, "27;1n"); 176186681Sed return (5); 177186681Sed default: 178186681Sed teken_printf("Unknown DSR\n"); 179186681Sed return (-1); 180186681Sed } 181186681Sed} 182186681Sed 183186681Sedstatic void 184186681Sedteken_subr_alignment_test(teken_t *t) 185186681Sed{ 186186681Sed teken_rect_t tr; 187186681Sed 188197521Sed t->t_cursor.tp_row = t->t_cursor.tp_col = 0; 189186681Sed t->t_scrollreg.ts_begin = 0; 190186681Sed t->t_scrollreg.ts_end = t->t_winsize.tp_row; 191197521Sed t->t_originreg = t->t_scrollreg; 192197521Sed t->t_stateflags &= ~(TS_WRAPPED|TS_ORIGIN); 193186681Sed teken_funcs_cursor(t); 194186681Sed 195186681Sed tr.tr_begin.tp_row = 0; 196186681Sed tr.tr_begin.tp_col = 0; 197186681Sed tr.tr_end = t->t_winsize; 198186681Sed teken_funcs_fill(t, &tr, 'E', &t->t_defattr); 199186681Sed} 200186681Sed 201186681Sedstatic void 202186681Sedteken_subr_backspace(teken_t *t) 203186681Sed{ 204186681Sed 205197117Sed if (t->t_stateflags & TS_CONS25) { 206197117Sed if (t->t_cursor.tp_col == 0) { 207197117Sed if (t->t_cursor.tp_row == t->t_originreg.ts_begin) 208197117Sed return; 209197117Sed t->t_cursor.tp_row--; 210197117Sed t->t_cursor.tp_col = t->t_winsize.tp_col - 1; 211197117Sed } else { 212197117Sed t->t_cursor.tp_col--; 213197117Sed } 214197117Sed } else { 215197117Sed if (t->t_cursor.tp_col == 0) 216197117Sed return; 217187367Sed 218186753Sed t->t_cursor.tp_col--; 219197117Sed t->t_stateflags &= ~TS_WRAPPED; 220186753Sed } 221186681Sed 222186681Sed teken_funcs_cursor(t); 223186681Sed} 224186681Sed 225186681Sedstatic void 226186681Sedteken_subr_bell(teken_t *t) 227186681Sed{ 228186681Sed 229186681Sed teken_funcs_bell(t); 230186681Sed} 231186681Sed 232186681Sedstatic void 233186681Sedteken_subr_carriage_return(teken_t *t) 234186681Sed{ 235186681Sed 236186681Sed t->t_cursor.tp_col = 0; 237186681Sed t->t_stateflags &= ~TS_WRAPPED; 238186681Sed teken_funcs_cursor(t); 239186681Sed} 240186681Sed 241186681Sedstatic void 242186681Sedteken_subr_cursor_backward(teken_t *t, unsigned int ncols) 243186681Sed{ 244186681Sed 245186681Sed if (ncols > t->t_cursor.tp_col) 246186681Sed t->t_cursor.tp_col = 0; 247186681Sed else 248186681Sed t->t_cursor.tp_col -= ncols; 249186681Sed t->t_stateflags &= ~TS_WRAPPED; 250186681Sed teken_funcs_cursor(t); 251186681Sed} 252186681Sed 253186681Sedstatic void 254186681Sedteken_subr_cursor_backward_tabulation(teken_t *t, unsigned int ntabs) 255186681Sed{ 256186681Sed 257186681Sed do { 258186681Sed /* Stop when we've reached the beginning of the line. */ 259186681Sed if (t->t_cursor.tp_col == 0) 260186681Sed break; 261186681Sed 262186681Sed t->t_cursor.tp_col--; 263223574Sed 264186681Sed /* Tab marker set. */ 265186681Sed if (teken_tab_isset(t, t->t_cursor.tp_col)) 266186681Sed ntabs--; 267186681Sed } while (ntabs > 0); 268186729Sed 269186729Sed teken_funcs_cursor(t); 270186681Sed} 271186681Sed 272186681Sedstatic void 273186681Sedteken_subr_cursor_down(teken_t *t, unsigned int nrows) 274186681Sed{ 275186681Sed 276186681Sed if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) 277186681Sed t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1; 278186681Sed else 279186681Sed t->t_cursor.tp_row += nrows; 280186681Sed t->t_stateflags &= ~TS_WRAPPED; 281186681Sed teken_funcs_cursor(t); 282186681Sed} 283186681Sed 284186681Sedstatic void 285186681Sedteken_subr_cursor_forward(teken_t *t, unsigned int ncols) 286186681Sed{ 287186681Sed 288186681Sed if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) 289186681Sed t->t_cursor.tp_col = t->t_winsize.tp_col - 1; 290186681Sed else 291186681Sed t->t_cursor.tp_col += ncols; 292186681Sed t->t_stateflags &= ~TS_WRAPPED; 293186681Sed teken_funcs_cursor(t); 294186681Sed} 295186681Sed 296186681Sedstatic void 297186681Sedteken_subr_cursor_forward_tabulation(teken_t *t, unsigned int ntabs) 298186681Sed{ 299186681Sed 300186681Sed do { 301186681Sed /* Stop when we've reached the end of the line. */ 302186681Sed if (t->t_cursor.tp_col == t->t_winsize.tp_col - 1) 303186681Sed break; 304186681Sed 305186681Sed t->t_cursor.tp_col++; 306223574Sed 307186681Sed /* Tab marker set. */ 308186681Sed if (teken_tab_isset(t, t->t_cursor.tp_col)) 309186681Sed ntabs--; 310186681Sed } while (ntabs > 0); 311186729Sed 312186729Sed teken_funcs_cursor(t); 313186681Sed} 314186681Sed 315186681Sedstatic void 316186681Sedteken_subr_cursor_next_line(teken_t *t, unsigned int ncols) 317186681Sed{ 318186681Sed 319186681Sed t->t_cursor.tp_col = 0; 320186681Sed teken_subr_cursor_down(t, ncols); 321186681Sed} 322186681Sed 323186681Sedstatic void 324186681Sedteken_subr_cursor_position(teken_t *t, unsigned int row, unsigned int col) 325186681Sed{ 326186681Sed 327286981Sed row = row - 1 + t->t_originreg.ts_begin; 328286981Sed t->t_cursor.tp_row = row < t->t_originreg.ts_end ? 329286981Sed row : t->t_originreg.ts_end - 1; 330186681Sed 331286981Sed col--; 332286981Sed t->t_cursor.tp_col = col < t->t_winsize.tp_col ? 333286981Sed col : t->t_winsize.tp_col - 1; 334186681Sed 335186681Sed t->t_stateflags &= ~TS_WRAPPED; 336186681Sed teken_funcs_cursor(t); 337186681Sed} 338186681Sed 339186681Sedstatic void 340186681Sedteken_subr_cursor_position_report(teken_t *t, unsigned int cmd) 341186681Sed{ 342186681Sed char response[18] = "\x1B["; 343186681Sed ssize_t len; 344186681Sed 345186681Sed len = teken_subr_do_cpr(t, cmd, response + 2); 346186681Sed if (len < 0) 347186681Sed return; 348186681Sed 349186681Sed teken_funcs_respond(t, response, len + 2); 350186681Sed} 351186681Sed 352186681Sedstatic void 353186681Sedteken_subr_cursor_previous_line(teken_t *t, unsigned int ncols) 354186681Sed{ 355186681Sed 356186681Sed t->t_cursor.tp_col = 0; 357186681Sed teken_subr_cursor_up(t, ncols); 358186681Sed} 359186681Sed 360186681Sedstatic void 361186681Sedteken_subr_cursor_up(teken_t *t, unsigned int nrows) 362186681Sed{ 363186681Sed 364186681Sed if (t->t_scrollreg.ts_begin + nrows >= t->t_cursor.tp_row) 365186681Sed t->t_cursor.tp_row = t->t_scrollreg.ts_begin; 366186681Sed else 367186681Sed t->t_cursor.tp_row -= nrows; 368186681Sed t->t_stateflags &= ~TS_WRAPPED; 369186681Sed teken_funcs_cursor(t); 370186681Sed} 371186681Sed 372186681Sedstatic void 373186681Sedteken_subr_delete_character(teken_t *t, unsigned int ncols) 374186681Sed{ 375186681Sed teken_rect_t tr; 376186681Sed 377186681Sed tr.tr_begin.tp_row = t->t_cursor.tp_row; 378186681Sed tr.tr_end.tp_row = t->t_cursor.tp_row + 1; 379186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 380186681Sed 381186681Sed if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) { 382186681Sed tr.tr_begin.tp_col = t->t_cursor.tp_col; 383186681Sed } else { 384186681Sed /* Copy characters to the left. */ 385186681Sed tr.tr_begin.tp_col = t->t_cursor.tp_col + ncols; 386186681Sed teken_funcs_copy(t, &tr, &t->t_cursor); 387186681Sed 388186681Sed tr.tr_begin.tp_col = t->t_winsize.tp_col - ncols; 389186681Sed } 390186681Sed 391186681Sed /* Blank trailing columns. */ 392186681Sed teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 393186681Sed} 394186681Sed 395186681Sedstatic void 396186681Sedteken_subr_delete_line(teken_t *t, unsigned int nrows) 397186681Sed{ 398186681Sed teken_rect_t tr; 399186681Sed 400197480Sed /* Ignore if outside scrolling region. */ 401197480Sed if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin || 402197480Sed t->t_cursor.tp_row >= t->t_scrollreg.ts_end) 403197480Sed return; 404197480Sed 405186681Sed tr.tr_begin.tp_col = 0; 406186681Sed tr.tr_end.tp_row = t->t_scrollreg.ts_end; 407186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 408186681Sed 409186681Sed if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) { 410186681Sed tr.tr_begin.tp_row = t->t_cursor.tp_row; 411186681Sed } else { 412186681Sed teken_pos_t tp; 413186681Sed 414186681Sed /* Copy rows up. */ 415186681Sed tr.tr_begin.tp_row = t->t_cursor.tp_row + nrows; 416186681Sed tp.tp_row = t->t_cursor.tp_row; 417186681Sed tp.tp_col = 0; 418186681Sed teken_funcs_copy(t, &tr, &tp); 419186681Sed 420186681Sed tr.tr_begin.tp_row = t->t_scrollreg.ts_end - nrows; 421186681Sed } 422186681Sed 423186681Sed /* Blank trailing rows. */ 424186681Sed teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 425186681Sed} 426186681Sed 427186681Sedstatic void 428197853Sedteken_subr_device_control_string(teken_t *t) 429186681Sed{ 430186681Sed 431197853Sed teken_printf("Unsupported device control string\n"); 432197853Sed t->t_stateflags |= TS_INSTRING; 433186681Sed} 434186681Sed 435186681Sedstatic void 436186681Sedteken_subr_device_status_report(teken_t *t, unsigned int cmd) 437186681Sed{ 438186681Sed char response[19] = "\x1B[?"; 439186681Sed ssize_t len; 440186681Sed 441186681Sed len = teken_subr_do_cpr(t, cmd, response + 3); 442186681Sed if (len < 0) 443186681Sed return; 444186681Sed 445186681Sed teken_funcs_respond(t, response, len + 3); 446186681Sed} 447186681Sed 448186681Sedstatic void 449186681Sedteken_subr_double_height_double_width_line_top(teken_t *t __unused) 450186681Sed{ 451186681Sed 452186681Sed teken_printf("double height double width top\n"); 453186681Sed} 454186681Sed 455186681Sedstatic void 456186681Sedteken_subr_double_height_double_width_line_bottom(teken_t *t __unused) 457186681Sed{ 458186681Sed 459186681Sed teken_printf("double height double width bottom\n"); 460186681Sed} 461186681Sed 462186681Sedstatic void 463186681Sedteken_subr_erase_character(teken_t *t, unsigned int ncols) 464186681Sed{ 465186681Sed teken_rect_t tr; 466186681Sed 467186681Sed tr.tr_begin = t->t_cursor; 468186681Sed tr.tr_end.tp_row = t->t_cursor.tp_row + 1; 469186681Sed 470186681Sed if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) 471186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 472186681Sed else 473186681Sed tr.tr_end.tp_col = t->t_cursor.tp_col + ncols; 474186681Sed 475186681Sed teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 476186681Sed} 477186681Sed 478186681Sedstatic void 479186681Sedteken_subr_erase_display(teken_t *t, unsigned int mode) 480186681Sed{ 481186681Sed teken_rect_t r; 482186681Sed 483186681Sed r.tr_begin.tp_col = 0; 484186681Sed r.tr_end.tp_col = t->t_winsize.tp_col; 485186681Sed 486186681Sed switch (mode) { 487186681Sed case 1: /* Erase from the top to the cursor. */ 488186681Sed teken_subr_erase_line(t, 1); 489186681Sed 490186681Sed /* Erase lines above. */ 491186681Sed if (t->t_cursor.tp_row == 0) 492186681Sed return; 493186681Sed r.tr_begin.tp_row = 0; 494186681Sed r.tr_end.tp_row = t->t_cursor.tp_row; 495186681Sed break; 496186681Sed case 2: /* Erase entire display. */ 497186681Sed r.tr_begin.tp_row = 0; 498186681Sed r.tr_end.tp_row = t->t_winsize.tp_row; 499186681Sed break; 500186681Sed default: /* Erase from cursor to the bottom. */ 501186681Sed teken_subr_erase_line(t, 0); 502186681Sed 503186681Sed /* Erase lines below. */ 504186681Sed if (t->t_cursor.tp_row == t->t_winsize.tp_row - 1) 505186681Sed return; 506186681Sed r.tr_begin.tp_row = t->t_cursor.tp_row + 1; 507186681Sed r.tr_end.tp_row = t->t_winsize.tp_row; 508186681Sed break; 509186681Sed } 510186681Sed 511186681Sed teken_funcs_fill(t, &r, BLANK, &t->t_curattr); 512186681Sed} 513186681Sed 514186681Sedstatic void 515186681Sedteken_subr_erase_line(teken_t *t, unsigned int mode) 516186681Sed{ 517186681Sed teken_rect_t r; 518186681Sed 519186681Sed r.tr_begin.tp_row = t->t_cursor.tp_row; 520186681Sed r.tr_end.tp_row = t->t_cursor.tp_row + 1; 521186681Sed 522186681Sed switch (mode) { 523186681Sed case 1: /* Erase from the beginning of the line to the cursor. */ 524186681Sed r.tr_begin.tp_col = 0; 525186681Sed r.tr_end.tp_col = t->t_cursor.tp_col + 1; 526186681Sed break; 527186681Sed case 2: /* Erase entire line. */ 528186681Sed r.tr_begin.tp_col = 0; 529186681Sed r.tr_end.tp_col = t->t_winsize.tp_col; 530186681Sed break; 531186681Sed default: /* Erase from cursor to the end of the line. */ 532186681Sed r.tr_begin.tp_col = t->t_cursor.tp_col; 533186681Sed r.tr_end.tp_col = t->t_winsize.tp_col; 534186681Sed break; 535186681Sed } 536186681Sed 537186681Sed teken_funcs_fill(t, &r, BLANK, &t->t_curattr); 538186681Sed} 539186681Sed 540186681Sedstatic void 541187469Sedteken_subr_g0_scs_special_graphics(teken_t *t __unused) 542187469Sed{ 543187469Sed 544197520Sed t->t_scs[0] = teken_scs_special_graphics; 545187469Sed} 546187469Sed 547187469Sedstatic void 548187469Sedteken_subr_g0_scs_uk_national(teken_t *t __unused) 549187469Sed{ 550187469Sed 551197520Sed t->t_scs[0] = teken_scs_uk_national; 552187469Sed} 553187469Sed 554187469Sedstatic void 555187469Sedteken_subr_g0_scs_us_ascii(teken_t *t __unused) 556187469Sed{ 557187469Sed 558197520Sed t->t_scs[0] = teken_scs_us_ascii; 559187469Sed} 560187469Sed 561187469Sedstatic void 562187469Sedteken_subr_g1_scs_special_graphics(teken_t *t __unused) 563187469Sed{ 564187469Sed 565197520Sed t->t_scs[1] = teken_scs_special_graphics; 566187469Sed} 567187469Sed 568187469Sedstatic void 569187469Sedteken_subr_g1_scs_uk_national(teken_t *t __unused) 570187469Sed{ 571187469Sed 572197520Sed t->t_scs[1] = teken_scs_uk_national; 573187469Sed} 574187469Sed 575187469Sedstatic void 576187469Sedteken_subr_g1_scs_us_ascii(teken_t *t __unused) 577187469Sed{ 578187469Sed 579197520Sed t->t_scs[1] = teken_scs_us_ascii; 580187469Sed} 581187469Sed 582187469Sedstatic void 583186681Sedteken_subr_horizontal_position_absolute(teken_t *t, unsigned int col) 584186681Sed{ 585186681Sed 586287098Sed col--; 587287098Sed t->t_cursor.tp_col = col < t->t_winsize.tp_col ? 588287098Sed col : t->t_winsize.tp_col - 1; 589186681Sed 590186681Sed t->t_stateflags &= ~TS_WRAPPED; 591186681Sed teken_funcs_cursor(t); 592186681Sed} 593186681Sed 594186681Sedstatic void 595186681Sedteken_subr_horizontal_tab(teken_t *t) 596186681Sed{ 597186681Sed 598226099Sed teken_subr_cursor_forward_tabulation(t, 1); 599186681Sed} 600186681Sed 601186681Sedstatic void 602186681Sedteken_subr_horizontal_tab_set(teken_t *t) 603186681Sed{ 604186681Sed 605186681Sed teken_tab_set(t, t->t_cursor.tp_col); 606186681Sed} 607186681Sed 608186681Sedstatic void 609186681Sedteken_subr_index(teken_t *t) 610186681Sed{ 611186681Sed 612186681Sed if (t->t_cursor.tp_row < t->t_scrollreg.ts_end - 1) { 613186681Sed t->t_cursor.tp_row++; 614186681Sed t->t_stateflags &= ~TS_WRAPPED; 615186681Sed teken_funcs_cursor(t); 616186681Sed } else { 617186681Sed teken_subr_do_scroll(t, 1); 618186681Sed } 619186681Sed} 620186681Sed 621186681Sedstatic void 622186681Sedteken_subr_insert_character(teken_t *t, unsigned int ncols) 623186681Sed{ 624186681Sed teken_rect_t tr; 625186681Sed 626186681Sed tr.tr_begin = t->t_cursor; 627186681Sed tr.tr_end.tp_row = t->t_cursor.tp_row + 1; 628186681Sed 629186681Sed if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) { 630186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 631186681Sed } else { 632186681Sed teken_pos_t tp; 633186681Sed 634186681Sed /* Copy characters to the right. */ 635186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col - ncols; 636186681Sed tp.tp_row = t->t_cursor.tp_row; 637186681Sed tp.tp_col = t->t_cursor.tp_col + ncols; 638186681Sed teken_funcs_copy(t, &tr, &tp); 639186681Sed 640186681Sed tr.tr_end.tp_col = t->t_cursor.tp_col + ncols; 641186681Sed } 642186681Sed 643186681Sed /* Blank current location. */ 644186681Sed teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 645186681Sed} 646186681Sed 647186681Sedstatic void 648186681Sedteken_subr_insert_line(teken_t *t, unsigned int nrows) 649186681Sed{ 650186681Sed teken_rect_t tr; 651186681Sed 652197480Sed /* Ignore if outside scrolling region. */ 653197480Sed if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin || 654197480Sed t->t_cursor.tp_row >= t->t_scrollreg.ts_end) 655197480Sed return; 656197480Sed 657186681Sed tr.tr_begin.tp_row = t->t_cursor.tp_row; 658186681Sed tr.tr_begin.tp_col = 0; 659186681Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 660186681Sed 661186681Sed if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) { 662186681Sed tr.tr_end.tp_row = t->t_scrollreg.ts_end; 663186681Sed } else { 664186681Sed teken_pos_t tp; 665186681Sed 666186681Sed /* Copy lines down. */ 667186681Sed tr.tr_end.tp_row = t->t_scrollreg.ts_end - nrows; 668186681Sed tp.tp_row = t->t_cursor.tp_row + nrows; 669186681Sed tp.tp_col = 0; 670186681Sed teken_funcs_copy(t, &tr, &tp); 671186681Sed 672186681Sed tr.tr_end.tp_row = t->t_cursor.tp_row + nrows; 673186681Sed } 674186681Sed 675186681Sed /* Blank current location. */ 676186681Sed teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 677186681Sed} 678186681Sed 679186681Sedstatic void 680186681Sedteken_subr_keypad_application_mode(teken_t *t) 681186681Sed{ 682186681Sed 683186681Sed teken_funcs_param(t, TP_KEYPADAPP, 1); 684186681Sed} 685186681Sed 686186681Sedstatic void 687186681Sedteken_subr_keypad_numeric_mode(teken_t *t) 688186681Sed{ 689186681Sed 690186681Sed teken_funcs_param(t, TP_KEYPADAPP, 0); 691186681Sed} 692186681Sed 693186681Sedstatic void 694186681Sedteken_subr_newline(teken_t *t) 695186681Sed{ 696186681Sed 697186681Sed t->t_cursor.tp_row++; 698186681Sed 699186681Sed if (t->t_cursor.tp_row >= t->t_scrollreg.ts_end) { 700186681Sed teken_subr_do_scroll(t, 1); 701186681Sed t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1; 702186681Sed } 703186681Sed 704186681Sed t->t_stateflags &= ~TS_WRAPPED; 705186681Sed teken_funcs_cursor(t); 706186681Sed} 707186681Sed 708186681Sedstatic void 709186798Sedteken_subr_newpage(teken_t *t) 710186798Sed{ 711187367Sed 712197117Sed if (t->t_stateflags & TS_CONS25) { 713197117Sed teken_rect_t tr; 714186798Sed 715211113Sed /* Clear screen. */ 716211113Sed tr.tr_begin.tp_row = t->t_originreg.ts_begin; 717211113Sed tr.tr_begin.tp_col = 0; 718211113Sed tr.tr_end.tp_row = t->t_originreg.ts_end; 719211113Sed tr.tr_end.tp_col = t->t_winsize.tp_col; 720197117Sed teken_funcs_fill(t, &tr, BLANK, &t->t_curattr); 721186798Sed 722211113Sed /* Cursor at top left. */ 723211113Sed t->t_cursor.tp_row = t->t_originreg.ts_begin; 724211113Sed t->t_cursor.tp_col = 0; 725211113Sed t->t_stateflags &= ~TS_WRAPPED; 726197117Sed teken_funcs_cursor(t); 727197117Sed } else { 728197117Sed teken_subr_newline(t); 729197117Sed } 730186798Sed} 731186798Sed 732186798Sedstatic void 733186681Sedteken_subr_next_line(teken_t *t) 734186681Sed{ 735186681Sed 736186681Sed t->t_cursor.tp_col = 0; 737186681Sed teken_subr_newline(t); 738186681Sed} 739186681Sed 740186681Sedstatic void 741197853Sedteken_subr_operating_system_command(teken_t *t) 742197853Sed{ 743197853Sed 744197853Sed teken_printf("Unsupported operating system command\n"); 745197853Sed t->t_stateflags |= TS_INSTRING; 746197853Sed} 747197853Sed 748197853Sedstatic void 749186681Sedteken_subr_pan_down(teken_t *t, unsigned int nrows) 750186681Sed{ 751186681Sed 752186681Sed teken_subr_do_scroll(t, (int)nrows); 753186681Sed} 754186681Sed 755186681Sedstatic void 756186681Sedteken_subr_pan_up(teken_t *t, unsigned int nrows) 757186681Sed{ 758186681Sed 759186681Sed teken_subr_do_scroll(t, -(int)nrows); 760186681Sed} 761186681Sed 762186681Sedstatic void 763186681Sedteken_subr_primary_device_attributes(teken_t *t, unsigned int request) 764186681Sed{ 765186681Sed 766186681Sed if (request == 0) { 767186681Sed const char response[] = "\x1B[?1;2c"; 768186681Sed 769186681Sed teken_funcs_respond(t, response, sizeof response - 1); 770186681Sed } else { 771186681Sed teken_printf("Unknown DA1\n"); 772186681Sed } 773186681Sed} 774186681Sed 775186681Sedstatic void 776186681Sedteken_subr_do_putchar(teken_t *t, const teken_pos_t *tp, teken_char_t c, 777186681Sed int width) 778186681Sed{ 779186681Sed 780186681Sed if (t->t_stateflags & TS_INSERT && 781186681Sed tp->tp_col < t->t_winsize.tp_col - width) { 782186681Sed teken_rect_t ctr; 783186681Sed teken_pos_t ctp; 784186681Sed 785186681Sed /* Insert mode. Move existing characters to the right. */ 786186681Sed ctr.tr_begin = *tp; 787186681Sed ctr.tr_end.tp_row = tp->tp_row + 1; 788186681Sed ctr.tr_end.tp_col = t->t_winsize.tp_col - width; 789186681Sed ctp.tp_row = tp->tp_row; 790186681Sed ctp.tp_col = tp->tp_col + width; 791186681Sed teken_funcs_copy(t, &ctr, &ctp); 792186681Sed } 793186681Sed 794259667Sed teken_funcs_putchar(t, tp, c, &t->t_curattr); 795259667Sed 796197117Sed if (width == 2 && tp->tp_col + 1 < t->t_winsize.tp_col) { 797197117Sed teken_pos_t tp2; 798259667Sed teken_attr_t attr; 799197117Sed 800259667Sed /* Print second half of CJK fullwidth character. */ 801197117Sed tp2.tp_row = tp->tp_row; 802197117Sed tp2.tp_col = tp->tp_col + 1; 803259667Sed attr = t->t_curattr; 804259667Sed attr.ta_format |= TF_CJK_RIGHT; 805259667Sed teken_funcs_putchar(t, &tp2, c, &attr); 806197117Sed } 807186681Sed} 808186681Sed 809186681Sedstatic void 810186681Sedteken_subr_regular_character(teken_t *t, teken_char_t c) 811186681Sed{ 812186681Sed int width; 813186681Sed 814197117Sed if (t->t_stateflags & TS_8BIT) { 815197470Sed if (!(t->t_stateflags & TS_CONS25) && (c <= 0x1b || c == 0x7f)) 816197115Sed return; 817197470Sed c = teken_scs_process(t, c); 818197115Sed width = 1; 819197115Sed } else { 820197115Sed c = teken_scs_process(t, c); 821197115Sed width = teken_wcwidth(c); 822197115Sed /* XXX: Don't process zero-width characters yet. */ 823197115Sed if (width <= 0) 824197115Sed return; 825197115Sed } 826186681Sed 827197117Sed if (t->t_stateflags & TS_CONS25) { 828197117Sed teken_subr_do_putchar(t, &t->t_cursor, c, width); 829197117Sed t->t_cursor.tp_col += width; 830197117Sed 831197117Sed if (t->t_cursor.tp_col >= t->t_winsize.tp_col) { 832197117Sed if (t->t_cursor.tp_row == t->t_scrollreg.ts_end - 1) { 833197117Sed /* Perform scrolling. */ 834197117Sed teken_subr_do_scroll(t, 1); 835197117Sed } else { 836197117Sed /* No scrolling needed. */ 837197117Sed if (t->t_cursor.tp_row < 838197117Sed t->t_winsize.tp_row - 1) 839197117Sed t->t_cursor.tp_row++; 840197117Sed } 841197117Sed t->t_cursor.tp_col = 0; 842197117Sed } 843259761Sed } else if (t->t_stateflags & TS_AUTOWRAP && 844259761Sed ((t->t_stateflags & TS_WRAPPED && 845259761Sed t->t_cursor.tp_col + 1 == t->t_winsize.tp_col) || 846259761Sed t->t_cursor.tp_col + width > t->t_winsize.tp_col)) { 847186681Sed teken_pos_t tp; 848186681Sed 849259761Sed /* 850259761Sed * Perform line wrapping, if: 851259761Sed * - Autowrapping is enabled, and 852259761Sed * - We're in the wrapped state at the last column, or 853259761Sed * - The character to be printed does not fit anymore. 854259761Sed */ 855186681Sed if (t->t_cursor.tp_row == t->t_scrollreg.ts_end - 1) { 856186681Sed /* Perform scrolling. */ 857186681Sed teken_subr_do_scroll(t, 1); 858186681Sed tp.tp_row = t->t_scrollreg.ts_end - 1; 859186681Sed } else { 860186681Sed /* No scrolling needed. */ 861186681Sed tp.tp_row = t->t_cursor.tp_row + 1; 862186681Sed if (tp.tp_row == t->t_winsize.tp_row) { 863186681Sed /* 864186681Sed * Corner case: regular character 865186681Sed * outside scrolling region, but at the 866186681Sed * bottom of the screen. 867186681Sed */ 868186681Sed teken_subr_do_putchar(t, &t->t_cursor, 869186681Sed c, width); 870186681Sed return; 871186681Sed } 872186681Sed } 873186681Sed 874186681Sed tp.tp_col = 0; 875186681Sed teken_subr_do_putchar(t, &tp, c, width); 876186681Sed 877186681Sed t->t_cursor.tp_row = tp.tp_row; 878186681Sed t->t_cursor.tp_col = width; 879186681Sed t->t_stateflags &= ~TS_WRAPPED; 880186681Sed } else { 881186681Sed /* No line wrapping needed. */ 882186681Sed teken_subr_do_putchar(t, &t->t_cursor, c, width); 883186681Sed t->t_cursor.tp_col += width; 884186681Sed 885186681Sed if (t->t_cursor.tp_col >= t->t_winsize.tp_col) { 886186681Sed t->t_stateflags |= TS_WRAPPED; 887186681Sed t->t_cursor.tp_col = t->t_winsize.tp_col - 1; 888186681Sed } else { 889186681Sed t->t_stateflags &= ~TS_WRAPPED; 890186681Sed } 891186681Sed } 892186681Sed 893186681Sed teken_funcs_cursor(t); 894186681Sed} 895186681Sed 896186681Sedstatic void 897186681Sedteken_subr_reset_dec_mode(teken_t *t, unsigned int cmd) 898186681Sed{ 899186681Sed 900186681Sed switch (cmd) { 901186681Sed case 1: /* Cursor keys mode. */ 902199171Sed t->t_stateflags &= ~TS_CURSORKEYS; 903186681Sed break; 904186681Sed case 2: /* DECANM: ANSI/VT52 mode. */ 905186681Sed teken_printf("DECRST VT52\n"); 906186681Sed break; 907186681Sed case 3: /* 132 column mode. */ 908186681Sed teken_funcs_param(t, TP_132COLS, 0); 909186681Sed teken_subr_reset_to_initial_state(t); 910186681Sed break; 911186681Sed case 5: /* Inverse video. */ 912186681Sed teken_printf("DECRST inverse video\n"); 913186681Sed break; 914186681Sed case 6: /* Origin mode. */ 915186681Sed t->t_stateflags &= ~TS_ORIGIN; 916186681Sed t->t_originreg.ts_begin = 0; 917186681Sed t->t_originreg.ts_end = t->t_winsize.tp_row; 918186681Sed t->t_cursor.tp_row = t->t_cursor.tp_col = 0; 919186681Sed t->t_stateflags &= ~TS_WRAPPED; 920186681Sed teken_funcs_cursor(t); 921186681Sed break; 922186681Sed case 7: /* Autowrap mode. */ 923186681Sed t->t_stateflags &= ~TS_AUTOWRAP; 924186681Sed break; 925186681Sed case 8: /* Autorepeat mode. */ 926186681Sed teken_funcs_param(t, TP_AUTOREPEAT, 0); 927186681Sed break; 928186681Sed case 25: /* Hide cursor. */ 929186681Sed teken_funcs_param(t, TP_SHOWCURSOR, 0); 930186681Sed break; 931186681Sed case 40: /* Disallow 132 columns. */ 932186681Sed teken_printf("DECRST allow 132\n"); 933186681Sed break; 934186681Sed case 45: /* Disable reverse wraparound. */ 935186681Sed teken_printf("DECRST reverse wraparound\n"); 936186681Sed break; 937186681Sed case 47: /* Switch to alternate buffer. */ 938186681Sed teken_printf("Switch to alternate buffer\n"); 939186681Sed break; 940197539Sed case 1000: /* Mouse input. */ 941197539Sed teken_funcs_param(t, TP_MOUSE, 0); 942197539Sed break; 943186681Sed default: 944186681Sed teken_printf("Unknown DECRST: %u\n", cmd); 945186681Sed } 946186681Sed} 947186681Sed 948186681Sedstatic void 949186681Sedteken_subr_reset_mode(teken_t *t, unsigned int cmd) 950186681Sed{ 951186681Sed 952186681Sed switch (cmd) { 953186681Sed case 4: 954186681Sed t->t_stateflags &= ~TS_INSERT; 955186681Sed break; 956186681Sed default: 957186681Sed teken_printf("Unknown reset mode: %u\n", cmd); 958186681Sed } 959186681Sed} 960186681Sed 961186681Sedstatic void 962259016Srayteken_subr_do_resize(teken_t *t) 963259016Sray{ 964259016Sray 965259016Sray t->t_scrollreg.ts_begin = 0; 966259016Sray t->t_scrollreg.ts_end = t->t_winsize.tp_row; 967259016Sray t->t_originreg = t->t_scrollreg; 968259016Sray} 969259016Sray 970259016Sraystatic void 971186681Sedteken_subr_do_reset(teken_t *t) 972186681Sed{ 973186681Sed 974187469Sed t->t_curattr = t->t_defattr; 975186681Sed t->t_cursor.tp_row = t->t_cursor.tp_col = 0; 976197114Sed t->t_scrollreg.ts_begin = 0; 977197114Sed t->t_scrollreg.ts_end = t->t_winsize.tp_row; 978197114Sed t->t_originreg = t->t_scrollreg; 979197117Sed t->t_stateflags &= TS_8BIT|TS_CONS25; 980197117Sed t->t_stateflags |= TS_AUTOWRAP; 981186681Sed 982197520Sed t->t_scs[0] = teken_scs_us_ascii; 983197520Sed t->t_scs[1] = teken_scs_us_ascii; 984197520Sed t->t_curscs = 0; 985187469Sed 986187469Sed teken_subr_save_cursor(t); 987186681Sed teken_tab_default(t); 988186681Sed} 989186681Sed 990186681Sedstatic void 991186681Sedteken_subr_reset_to_initial_state(teken_t *t) 992186681Sed{ 993186681Sed 994186681Sed teken_subr_do_reset(t); 995186681Sed teken_subr_erase_display(t, 2); 996186753Sed teken_funcs_param(t, TP_SHOWCURSOR, 1); 997186681Sed teken_funcs_cursor(t); 998186681Sed} 999186681Sed 1000186681Sedstatic void 1001186681Sedteken_subr_restore_cursor(teken_t *t) 1002186681Sed{ 1003186681Sed 1004186681Sed t->t_cursor = t->t_saved_cursor; 1005186681Sed t->t_curattr = t->t_saved_curattr; 1006197520Sed t->t_scs[t->t_curscs] = t->t_saved_curscs; 1007186681Sed t->t_stateflags &= ~TS_WRAPPED; 1008197521Sed 1009197521Sed /* Get out of origin mode when the cursor is moved outside. */ 1010197521Sed if (t->t_cursor.tp_row < t->t_originreg.ts_begin || 1011197521Sed t->t_cursor.tp_row >= t->t_originreg.ts_end) { 1012197521Sed t->t_stateflags &= ~TS_ORIGIN; 1013197521Sed t->t_originreg.ts_begin = 0; 1014197521Sed t->t_originreg.ts_end = t->t_winsize.tp_row; 1015197521Sed } 1016197521Sed 1017186681Sed teken_funcs_cursor(t); 1018186681Sed} 1019186681Sed 1020186681Sedstatic void 1021186681Sedteken_subr_reverse_index(teken_t *t) 1022186681Sed{ 1023186681Sed 1024186681Sed if (t->t_cursor.tp_row > t->t_scrollreg.ts_begin) { 1025186681Sed t->t_cursor.tp_row--; 1026186681Sed t->t_stateflags &= ~TS_WRAPPED; 1027186681Sed teken_funcs_cursor(t); 1028186681Sed } else { 1029186681Sed teken_subr_do_scroll(t, -1); 1030186681Sed } 1031186681Sed} 1032186681Sed 1033186681Sedstatic void 1034186681Sedteken_subr_save_cursor(teken_t *t) 1035186681Sed{ 1036186681Sed 1037186681Sed t->t_saved_cursor = t->t_cursor; 1038186681Sed t->t_saved_curattr = t->t_curattr; 1039197520Sed t->t_saved_curscs = t->t_scs[t->t_curscs]; 1040186681Sed} 1041186681Sed 1042186681Sedstatic void 1043186681Sedteken_subr_secondary_device_attributes(teken_t *t, unsigned int request) 1044186681Sed{ 1045186681Sed 1046186681Sed if (request == 0) { 1047186681Sed const char response[] = "\x1B[>0;10;0c"; 1048186681Sed teken_funcs_respond(t, response, sizeof response - 1); 1049186681Sed } else { 1050186681Sed teken_printf("Unknown DA2\n"); 1051186681Sed } 1052186681Sed} 1053186681Sed 1054186681Sedstatic void 1055186681Sedteken_subr_set_dec_mode(teken_t *t, unsigned int cmd) 1056186681Sed{ 1057186681Sed 1058186681Sed switch (cmd) { 1059186681Sed case 1: /* Cursor keys mode. */ 1060199171Sed t->t_stateflags |= TS_CURSORKEYS; 1061186681Sed break; 1062186681Sed case 2: /* DECANM: ANSI/VT52 mode. */ 1063186681Sed teken_printf("DECSET VT52\n"); 1064186681Sed break; 1065186681Sed case 3: /* 132 column mode. */ 1066186681Sed teken_funcs_param(t, TP_132COLS, 1); 1067186681Sed teken_subr_reset_to_initial_state(t); 1068186681Sed break; 1069186681Sed case 5: /* Inverse video. */ 1070186681Sed teken_printf("DECSET inverse video\n"); 1071186681Sed break; 1072186681Sed case 6: /* Origin mode. */ 1073186681Sed t->t_stateflags |= TS_ORIGIN; 1074186681Sed t->t_originreg = t->t_scrollreg; 1075186681Sed t->t_cursor.tp_row = t->t_scrollreg.ts_begin; 1076186681Sed t->t_cursor.tp_col = 0; 1077186681Sed t->t_stateflags &= ~TS_WRAPPED; 1078186681Sed teken_funcs_cursor(t); 1079186681Sed break; 1080186681Sed case 7: /* Autowrap mode. */ 1081186681Sed t->t_stateflags |= TS_AUTOWRAP; 1082186681Sed break; 1083186681Sed case 8: /* Autorepeat mode. */ 1084186681Sed teken_funcs_param(t, TP_AUTOREPEAT, 1); 1085186681Sed break; 1086186681Sed case 25: /* Display cursor. */ 1087186681Sed teken_funcs_param(t, TP_SHOWCURSOR, 1); 1088186681Sed break; 1089186681Sed case 40: /* Allow 132 columns. */ 1090186681Sed teken_printf("DECSET allow 132\n"); 1091186681Sed break; 1092186681Sed case 45: /* Enable reverse wraparound. */ 1093186681Sed teken_printf("DECSET reverse wraparound\n"); 1094186681Sed break; 1095186681Sed case 47: /* Switch to alternate buffer. */ 1096186681Sed teken_printf("Switch away from alternate buffer\n"); 1097186681Sed break; 1098197539Sed case 1000: /* Mouse input. */ 1099197539Sed teken_funcs_param(t, TP_MOUSE, 1); 1100197539Sed break; 1101186681Sed default: 1102186681Sed teken_printf("Unknown DECSET: %u\n", cmd); 1103186681Sed } 1104186681Sed} 1105186681Sed 1106186681Sedstatic void 1107186681Sedteken_subr_set_mode(teken_t *t, unsigned int cmd) 1108186681Sed{ 1109186681Sed 1110186681Sed switch (cmd) { 1111186681Sed case 4: 1112186681Sed teken_printf("Insert mode\n"); 1113186681Sed t->t_stateflags |= TS_INSERT; 1114186681Sed break; 1115186681Sed default: 1116186681Sed teken_printf("Unknown set mode: %u\n", cmd); 1117186681Sed } 1118186681Sed} 1119186681Sed 1120186681Sedstatic void 1121186681Sedteken_subr_set_graphic_rendition(teken_t *t, unsigned int ncmds, 1122186681Sed unsigned int cmds[]) 1123186681Sed{ 1124186681Sed unsigned int i, n; 1125186681Sed 1126186681Sed /* No attributes means reset. */ 1127186681Sed if (ncmds == 0) { 1128186681Sed t->t_curattr = t->t_defattr; 1129186681Sed return; 1130186681Sed } 1131186681Sed 1132186681Sed for (i = 0; i < ncmds; i++) { 1133186681Sed n = cmds[i]; 1134186681Sed 1135186681Sed switch (n) { 1136186681Sed case 0: /* Reset. */ 1137186681Sed t->t_curattr = t->t_defattr; 1138186681Sed break; 1139186681Sed case 1: /* Bold. */ 1140186681Sed t->t_curattr.ta_format |= TF_BOLD; 1141186681Sed break; 1142186681Sed case 4: /* Underline. */ 1143186681Sed t->t_curattr.ta_format |= TF_UNDERLINE; 1144186681Sed break; 1145186681Sed case 5: /* Blink. */ 1146186681Sed t->t_curattr.ta_format |= TF_BLINK; 1147186681Sed break; 1148186681Sed case 7: /* Reverse. */ 1149186681Sed t->t_curattr.ta_format |= TF_REVERSE; 1150186681Sed break; 1151186681Sed case 22: /* Remove bold. */ 1152186681Sed t->t_curattr.ta_format &= ~TF_BOLD; 1153186681Sed break; 1154186681Sed case 24: /* Remove underline. */ 1155186681Sed t->t_curattr.ta_format &= ~TF_UNDERLINE; 1156186681Sed break; 1157186681Sed case 25: /* Remove blink. */ 1158186681Sed t->t_curattr.ta_format &= ~TF_BLINK; 1159186681Sed break; 1160186681Sed case 27: /* Remove reverse. */ 1161186681Sed t->t_curattr.ta_format &= ~TF_REVERSE; 1162186681Sed break; 1163186681Sed case 30: /* Set foreground color: black */ 1164186681Sed case 31: /* Set foreground color: red */ 1165186681Sed case 32: /* Set foreground color: green */ 1166186681Sed case 33: /* Set foreground color: brown */ 1167186681Sed case 34: /* Set foreground color: blue */ 1168186681Sed case 35: /* Set foreground color: magenta */ 1169186681Sed case 36: /* Set foreground color: cyan */ 1170186681Sed case 37: /* Set foreground color: white */ 1171186681Sed t->t_curattr.ta_fgcolor = n - 30; 1172186681Sed break; 1173197522Sed case 38: /* Set foreground color: 256 color mode */ 1174197522Sed if (i + 2 >= ncmds || cmds[i + 1] != 5) 1175197522Sed continue; 1176197522Sed t->t_curattr.ta_fgcolor = cmds[i + 2]; 1177197522Sed i += 2; 1178197522Sed break; 1179186681Sed case 39: /* Set default foreground color. */ 1180186681Sed t->t_curattr.ta_fgcolor = t->t_defattr.ta_fgcolor; 1181186681Sed break; 1182186681Sed case 40: /* Set background color: black */ 1183186681Sed case 41: /* Set background color: red */ 1184186681Sed case 42: /* Set background color: green */ 1185186681Sed case 43: /* Set background color: brown */ 1186186681Sed case 44: /* Set background color: blue */ 1187186681Sed case 45: /* Set background color: magenta */ 1188186681Sed case 46: /* Set background color: cyan */ 1189186681Sed case 47: /* Set background color: white */ 1190186681Sed t->t_curattr.ta_bgcolor = n - 40; 1191186681Sed break; 1192197522Sed case 48: /* Set background color: 256 color mode */ 1193197522Sed if (i + 2 >= ncmds || cmds[i + 1] != 5) 1194197522Sed continue; 1195197522Sed t->t_curattr.ta_bgcolor = cmds[i + 2]; 1196197522Sed i += 2; 1197197522Sed break; 1198186681Sed case 49: /* Set default background color. */ 1199186681Sed t->t_curattr.ta_bgcolor = t->t_defattr.ta_bgcolor; 1200186681Sed break; 1201197522Sed case 90: /* Set bright foreground color: black */ 1202197522Sed case 91: /* Set bright foreground color: red */ 1203197522Sed case 92: /* Set bright foreground color: green */ 1204197522Sed case 93: /* Set bright foreground color: brown */ 1205197522Sed case 94: /* Set bright foreground color: blue */ 1206197522Sed case 95: /* Set bright foreground color: magenta */ 1207197522Sed case 96: /* Set bright foreground color: cyan */ 1208197522Sed case 97: /* Set bright foreground color: white */ 1209197522Sed t->t_curattr.ta_fgcolor = n - 90 + 8; 1210197522Sed break; 1211197522Sed case 100: /* Set bright background color: black */ 1212197522Sed case 101: /* Set bright background color: red */ 1213197522Sed case 102: /* Set bright background color: green */ 1214197522Sed case 103: /* Set bright background color: brown */ 1215197522Sed case 104: /* Set bright background color: blue */ 1216197522Sed case 105: /* Set bright background color: magenta */ 1217197522Sed case 106: /* Set bright background color: cyan */ 1218197522Sed case 107: /* Set bright background color: white */ 1219197522Sed t->t_curattr.ta_bgcolor = n - 100 + 8; 1220197522Sed break; 1221186681Sed default: 1222186681Sed teken_printf("unsupported attribute %u\n", n); 1223186681Sed } 1224186681Sed } 1225186681Sed} 1226186681Sed 1227186681Sedstatic void 1228186681Sedteken_subr_set_top_and_bottom_margins(teken_t *t, unsigned int top, 1229186681Sed unsigned int bottom) 1230186681Sed{ 1231186681Sed 1232186681Sed /* Adjust top row number. */ 1233186681Sed if (top > 0) 1234186681Sed top--; 1235186681Sed /* Adjust bottom row number. */ 1236186681Sed if (bottom == 0 || bottom > t->t_winsize.tp_row) 1237186681Sed bottom = t->t_winsize.tp_row; 1238186681Sed 1239186681Sed /* Invalid arguments. */ 1240186681Sed if (top >= bottom - 1) { 1241186681Sed top = 0; 1242186681Sed bottom = t->t_winsize.tp_row; 1243186681Sed } 1244186681Sed 1245199170Sed /* Apply scrolling region. */ 1246186681Sed t->t_scrollreg.ts_begin = top; 1247186681Sed t->t_scrollreg.ts_end = bottom; 1248199170Sed if (t->t_stateflags & TS_ORIGIN) 1249186681Sed t->t_originreg = t->t_scrollreg; 1250199170Sed 1251199170Sed /* Home cursor to the top left of the scrolling region. */ 1252199170Sed t->t_cursor.tp_row = t->t_originreg.ts_begin; 1253199170Sed t->t_cursor.tp_col = 0; 1254199170Sed t->t_stateflags &= ~TS_WRAPPED; 1255199170Sed teken_funcs_cursor(t); 1256186681Sed} 1257186681Sed 1258186681Sedstatic void 1259186681Sedteken_subr_single_height_double_width_line(teken_t *t __unused) 1260186681Sed{ 1261186681Sed 1262186681Sed teken_printf("single height double width???\n"); 1263186681Sed} 1264186681Sed 1265186681Sedstatic void 1266186681Sedteken_subr_single_height_single_width_line(teken_t *t __unused) 1267186681Sed{ 1268186681Sed 1269186681Sed teken_printf("single height single width???\n"); 1270186681Sed} 1271186681Sed 1272186681Sedstatic void 1273186681Sedteken_subr_string_terminator(teken_t *t __unused) 1274186681Sed{ 1275186681Sed 1276197853Sed /* 1277197853Sed * Strings are already terminated in teken_input_char() when ^[ 1278197853Sed * is inserted. 1279197853Sed */ 1280186681Sed} 1281186681Sed 1282186681Sedstatic void 1283186681Sedteken_subr_tab_clear(teken_t *t, unsigned int cmd) 1284186681Sed{ 1285186681Sed 1286186681Sed switch (cmd) { 1287186681Sed case 0: 1288186681Sed teken_tab_clear(t, t->t_cursor.tp_col); 1289186681Sed break; 1290186681Sed case 3: 1291186681Sed memset(&t->t_tabstops, 0, T_NUMCOL / 8); 1292186681Sed break; 1293186681Sed } 1294186681Sed} 1295186681Sed 1296186681Sedstatic void 1297186681Sedteken_subr_vertical_position_absolute(teken_t *t, unsigned int row) 1298186681Sed{ 1299186681Sed 1300287098Sed row = row - 1 + t->t_originreg.ts_begin; 1301287098Sed t->t_cursor.tp_row = row < t->t_originreg.ts_end ? 1302287098Sed row : t->t_originreg.ts_end - 1; 1303186681Sed 1304186681Sed t->t_stateflags &= ~TS_WRAPPED; 1305186681Sed teken_funcs_cursor(t); 1306186681Sed} 1307