The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/teken/teken_subr.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 6db67a6070ae898bd371d0bc632736e8


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.