Print this page
    
5396 gcc 4.8.2 longjmp errors for cscope-fast
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/libxcurses/src/libc/xcurses/doupdate.c
          +++ new/usr/src/lib/libxcurses/src/libc/xcurses/doupdate.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License, Version 1.0 only
   6    6   * (the "License").  You may not use this file except in compliance
   7    7   * with the License.
   8    8   *
   9    9   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10   10   * or http://www.opensolaris.org/os/licensing.
  11   11   * See the License for the specific language governing permissions
  12   12   * and limitations under the License.
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
  13   13   *
  14   14   * When distributing Covered Code, include this CDDL HEADER in each
  15   15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16   16   * If applicable, add the following below this CDDL HEADER, with the
  17   17   * fields enclosed by brackets "[]" replaced with your own identifying
  18   18   * information: Portions Copyright [yyyy] [name of copyright owner]
  19   19   *
  20   20   * CDDL HEADER END
  21   21   */
  22   22  /*
       23 + * Copyright 2015 Gary Mills
  23   24   * Copyright (c) 1995, by Sun Microsystems, Inc.
  24   25   * All rights reserved.
  25   26   */
  26   27  
  27      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  28      -
  29   28  /*
  30   29   * doupdate.c
  31   30   *
  32   31   * XCurses Library
  33   32   *
  34   33   * Copyright 1990, 1995 by Mortice Kern Systems Inc.  All rights reserved.
  35   34   *
  36   35   */
  37   36  
  38   37  #ifdef M_RCSID
  39   38  #ifndef lint
  40   39  static char const rcsID[] = "$Header: /rd/src/libc/xcurses/rcs/doupdate.c 1.9 1995/07/26 17:45:06 ant Exp $";
  41   40  #endif
  42   41  #endif
  43   42  
  44   43  #include <private.h>
  45   44  #include <string.h>
  46   45  #include <setjmp.h>
  47   46  #include <signal.h>
  48   47  
  49   48  #undef SIGTSTP
  50   49  
  51   50  /*
  52   51   * Disable typeahead trapping because it slow down updated dramatically
  53   52   * on MPE/iX.
  54   53   */
  55   54  #ifdef MPE_STUB
  56   55  #undef M_CURSES_TYPEAHEAD
  57   56  #endif
  58   57  
  59   58  /*
  60   59   * This value is the ideal length for the cursor addressing sequence 
  61   60   * being four bytes long, ie. "<escape><cursor addressing code><row><col>".
  62   61   * eg. VT52 - "\EYrc" or ADM3A - "\E=rc"
  63   62   */
  64   63  #define JUMP_SIZE       4
  65   64  
  66   65  /*
  67   66   * This value is the ideal length for the clear-to-eol sequence
  68   67   * being two bytes long, ie "<escape><clear eol code>".
  69   68   */
  70   69  #define CEOL_SIZE       2
  71   70  
  72   71  #define GOTO(r,c)       (__m_mvcur(curscr->_cury, curscr->_curx,r,c,__m_outc),\
  73   72                          curscr->_cury = r, curscr->_curx = c)
  74   73  
  75   74  typedef struct cost_op {
  76   75          short cost;
  77   76          short op;
  78   77  } lcost;
  79   78  
  80   79  typedef void (*t_action)(int, int);
  81   80  
  82   81  static jmp_buf breakout;
  83   82  
  84   83  #define LC(i,j)         (lc[(i) * (LINES + 1) + (j)])
  85   84  
  86   85  static lcost *lc = (lcost *) 0;
  87   86  static unsigned long *nhash = (unsigned long *) 0;
  88   87  static t_action *del = (t_action *) 0;
  89   88  static t_action *ins_rep = (t_action *) 0;
  90   89  
  91   90  static WINDOW *newscr;
  92   91  
  93   92  STATIC void erase_bottom(int);
  94   93  STATIC void clear_bottom(int);
  95   94  STATIC void complex(void);
  96   95  STATIC int cost(int, int);
  97   96  STATIC void lines_delete(int, int);
  98   97  STATIC void lines_insert(int, int);
  99   98  STATIC void lines_replace(int, int);
 100   99  STATIC void script(int, int);
 101  100  STATIC int scroll_dn(int);
 102  101  STATIC int scroll_up(int);
 103  102  STATIC void simple(void);
 104  103  STATIC void text_replace(int);
 105  104  STATIC void block_over(int, int, int);
 106  105  
 107  106  /*f
 108  107   * Wrapper that streams Curses output.
 109  108   * 
 110  109   * All escape sequences going to the screen come through here.
 111  110   * All ordinary characters go to the screen via the putc in doupdate.c
 112  111   */
 113  112  int
 114  113  __m_outc(ch)
 115  114  int ch;
 116  115  {
 117  116          return putc(ch, __m_screen->_of);
 118  117  }
 119  118  
 120  119  /*
 121  120   * Allocate or grow doupdate() structures.
 122  121   */
 123  122  int
 124  123  __m_doupdate_init() 
 125  124  {
 126  125          void *new;
 127  126          static short nlines = 0;
 128  127  
 129  128          if (lines <= 0)
 130  129                  return -1;
 131  130  
 132  131          if (lines <= nlines)
 133  132                  return 0;
 134  133  
 135  134          new = m_malloc((lines+1) * (lines+1) * sizeof *lc);
 136  135          if (new == (void *) 0)
 137  136                  return -1;
 138  137          if (lc != (lcost *) 0)
 139  138                  free(lc);
 140  139          lc = (lcost *) new;
 141  140  
 142  141          new = m_malloc((lines + lines) * sizeof *del);
 143  142          if (new == (void *) 0)
 144  143                  return -1;
 145  144          if (del != (t_action *) 0)
 146  145                  free(del);
 147  146          del = (t_action *) new;
 148  147          ins_rep = del + lines;
 149  148  
 150  149          new = m_malloc(lines * sizeof *nhash);
 151  150          if (new == (void *) 0)
 152  151                  return -1;
 153  152          if (nhash != (unsigned long *) 0)
 154  153                  free(nhash);
 155  154          nhash = (unsigned long *) new;
 156  155  
 157  156          nlines = lines;
 158  157  
 159  158          return 0;
 160  159  }
 161  160  
 162  161  STATIC void
 163  162  erase_bottom(y)
 164  163  int y;
 165  164  {
 166  165          int i;
 167  166  
 168  167          for (i = y; i < LINES; ++i) {
 169  168                  (void) __m_cc_erase(curscr, i, 0, i, curscr->_maxx-1);
 170  169                  __m_cc_hash(curscr, __m_screen->_hash, i);
 171  170          }
 172  171  }
 173  172  
 174  173  /*f
 175  174   *  Clear from the start of the current row to bottom of screen.
 176  175   */
 177  176  STATIC void
 178  177  clear_bottom(y)
 179  178  int y;
 180  179  {
 181  180          erase_bottom(y);
 182  181  
 183  182          /* Restore default color pair before doing area clears. */
 184  183          if (back_color_erase)
 185  184                  (void) vid_puts(WA_NORMAL, 0, (void *) 0, __m_outc);
 186  185  
 187  186          if (y == 0 && clear_screen != (char *) 0) {
 188  187                  (void) tputs(clear_screen, 1, __m_outc);
 189  188          } else {
 190  189                  (void) __m_mvcur(-1, -1, y, 0, __m_outc);
 191  190                  if (clr_eos != (char *) 0) {
 192  191                          (void) tputs(clr_eos, 1, __m_outc);
 193  192                  } else if (clr_eol != (char *) 0) {
 194  193                          for (;;) {
 195  194                                  (void) tputs(clr_eol, 1, __m_outc);
 196  195                                  if (LINES <= y)
 197  196                                          break;
 198  197                                  (void) __m_mvcur(y, 0, y+1, 0, __m_outc);
 199  198                                  ++y;
 200  199                          }
 201  200                  }
 202  201          }
 203  202  
 204  203          curscr->_cury = y;
 205  204          curscr->_curx = 0;
 206  205  }
 207  206  
 208  207  /*f
 209  208   * Replace a line of text.  
 210  209   *
 211  210   * The principal scheme is to overwrite the region of a line between
 212  211   * the first and last differing characters.  A clear-eol is used to
 213  212   * optimise an update region that consist largely of blanks.  This can
 214  213   * happen fairly often in the case of scrolled lines or full redraws.
 215  214   *
 216  215   * Miller's line redraw algorithm, used in the 'S' editor [Mil87], 
 217  216   * should be re-investigated to see if it is simple and fast enough for 
 218  217   * our needs, and if it can be adapted to handle the ceol_standout_glitch 
 219  218   * (HP 2392A terminals) and multibyte character sequences.
 220  219   *
 221  220   * Very early versions of this code applied a Gosling algorithm column
 222  221   * wise in addition to the row-wise used in complex().  It was removed
 223  222   * in favour of both computation and transmission speed.  The assumption
 224  223   * being that overwrites of a line region occured far more frequently
 225  224   * than the need to insert/delete several isolated characters. 
 226  225   *
 227  226   * References:
 228  227   * [Mil87]      W. Miller, A Software Tools Sampler, Prentice-Hall, 1987
 229  228   */
 230  229  STATIC void
 231  230  text_replace(row)
 232  231  int row;
 233  232  {
 234  233          short npair;
 235  234          attr_t cookie, nattr; 
 236  235          cchar_t *optr, *nptr;
 237  236          int col, last, tail, jump, count;
 238  237          
 239  238  #ifdef M_CURSES_TYPEAHEAD
 240  239          /* Before replacing a line of text, check for type-ahead. */
 241  240          if (__m_screen->_flags & S_ISATTY) {
 242  241                  unsigned char cc;
 243  242  
 244  243                  if (read(__m_screen->_kfd, &cc, sizeof cc) == sizeof cc) {
 245  244                          (void) ungetch(cc);
 246  245                          longjmp(breakout, 1);
 247  246                  }
 248  247          }
 249  248  #endif /* M_CURSES_TYPEAHEAD */
 250  249  
 251  250          col = newscr->_first[row];
 252  251          if (col < 0)
 253  252                  col = 0;
 254  253  
 255  254          last = newscr->_last[row];
 256  255          if (COLS < last)
 257  256                  last = COLS;
 258  257  
 259  258          if (clr_eol != (char *) 0) {
 260  259                  /* Find start of blank tail region. */
 261  260                  nptr = &newscr->_line[row][COLS];
 262  261                  for (tail = COLS; 0 < tail; --tail) {
 263  262                          if (!__m_cc_compare(--nptr, &newscr->_bg, 1))
 264  263                                  break;
 265  264                  }
 266  265  
 267  266                  /* Only consider clear-to-end-of-line optimization if the
 268  267                   * blank tail falls within the end of the dirty region by
 269  268                   * more than ideal length of clear-to-end-of-line sequence.
 270  269                   * Else disable the check by forcing tail to be at the
 271  270                   * end-of-line.
 272  271                   */
 273  272                  if (last < tail + CEOL_SIZE)
 274  273                          tail = COLS;
 275  274          }
 276  275  
 277  276          optr = &curscr->_line[row][col];
 278  277          nptr = &newscr->_line[row][col];
 279  278  
 280  279          for (jump = -1; col < last; ) {
 281  280                  /* Skip common regions. */
 282  281                  for (count = 0; __m_cc_compare(optr, nptr, 1); ++count) {
 283  282                          /* Advance before possible goto. */
 284  283                          ++optr;
 285  284                          ++nptr;
 286  285  
 287  286                          if (last <= ++col)
 288  287                                  goto done;
 289  288                  }
 290  289  
 291  290                  /* Move the cursor by redrawing characters or using
 292  291                   * cursor motion commands.  The first time that we
 293  292                   * address this row, jump equals -1, so that the cursor
 294  293                   * will be forced to the correct screen line.  Once
 295  294                   * there, we should be able to track the cursor motion
 296  295                   * along the line and jump only when the cost of redrawing
 297  296                   * to column N is more expensive than a jump to column N.
 298  297                   */
 299  298                  if (jump < count) {
 300  299                          /* First time addressing this row or cost of
 301  300                           * jumping cheaper than redrawing.
 302  301                           */
 303  302                          jump = JUMP_SIZE;
 304  303                          GOTO(row, col);
 305  304                          count = 0;
 306  305  
 307  306                          /* If attributes at start of field are different
 308  307                           * force an attribute cookie to be dropped.
 309  308                           */
 310  309                          if (ceol_standout_glitch 
 311  310                          && (optr->_at != nptr->_at || optr->_co != nptr->_co))
 312  311                                  ATTR_STATE |= WA_COOKIE;
 313  312                  } else {
 314  313                          /* Redraw to move short distance. */
 315  314                          optr -= count;
 316  315                          nptr -= count;
 317  316                          col -= count;
 318  317                  }
 319  318  
 320  319                  /* Write difference region. */
 321  320                  while (col < last 
 322  321                  && (!__m_cc_compare(optr, nptr, 1) || 0 < count--)) {
 323  322  write_loop:
 324  323                          /* Check for clear-to-end-of-line optimization. */
 325  324                          if (clr_eol != (char *) 0 && tail <= col) {
 326  325                                  /* For HP terminals, only clear-to-end-of-line
 327  326                                   * once the attributes have been turned off.
 328  327                                   * Other terminals, we can proceed normally.
 329  328                                   */
 330  329                                  if (!ceol_standout_glitch
 331  330                                  || ATTR_STATE == WA_NORMAL) {
 332  331                                          curscr->_curx = col;
 333  332                                          goto done;
 334  333                                  }
 335  334                          }
 336  335  
 337  336                          ++col;
 338  337  
 339  338                          /* Make sure we don't scroll the screen by writing
 340  339                           * to the bottom right corner.  
 341  340                           */
 342  341                          if (COLS <= col && LINES-1 <= row
 343  342                          && auto_right_margin && !eat_newline_glitch) {
 344  343                                  /*** TODO
 345  344                                   *** Insert character/auto_right_margin
 346  345                                   *** hacks for writting into the last
 347  346                                   *** column of the last line so as not
 348  347                                   *** to scroll.
 349  348                                   ***/ 
 350  349                                  curscr->_curx = col;
 351  350                                  goto done;
 352  351                          }
 353  352  
 354  353                          /* Remember any existing attribute cookie. */
 355  354                          cookie = optr->_at & WA_COOKIE;
 356  355  
 357  356                          nattr = nptr->_at;
 358  357                          npair = nptr->_co;
 359  358  
 360  359                          /* Change attribute state.  On HP terminals we also
 361  360                           * have to check for attribute cookies that may need
 362  361                           * to be changed.
 363  362                           */
 364  363                          if (ATTR_STATE != nattr 
 365  364                          || optr->_at != nattr || optr->_co != npair) {
 366  365                                  (void) vid_puts(
 367  366                                          nattr, npair, (void *) 0, __m_outc
 368  367                                  );
 369  368  
 370  369                                  /* Remember new or existing cookie. */
 371  370                                  cookie = WA_COOKIE;
 372  371                          }
 373  372  
 374  373                          /* Don't display internal characters. */
 375  374                          if (nptr->_f) 
 376  375                                  (void) __m_cc_write(nptr);
 377  376  
 378  377                          /* Update copy of screen image. */
 379  378                          *optr++ = *nptr++;
 380  379                          optr->_at |= cookie;
 381  380                  }
 382  381  
 383  382                  curscr->_curx = col;
 384  383  
 385  384                  /* Check the attributes at the end of the field with
 386  385                   * those of start of the next common region.  If they
 387  386                   * differ, force another iteration of the write-loop
 388  387                   * that will change the attribute state.
 389  388                   */ 
 390  389                  if (ceol_standout_glitch && col < COLS 
 391  390                  && ATTR_STATE != (optr->_at & ~WA_COOKIE))
 392  391                          goto write_loop;
 393  392          }
 394  393  done:
 395  394          /* Before leaving this line, check if we have to turn off 
 396  395           * attributes and record a cookie.
 397  396           */
 398  397          if (!move_standout_mode && ATTR_STATE != WA_NORMAL) {
 399  398                  /* ceol_standout_glitch, which affects HP terminals,
 400  399                   * drops hidden cookies on the screen where ever the
 401  400                   * cursor is, so disabling attributes before a cursor
 402  401                   * motion operation could disturb existing highlights.
 403  402                   */
 404  403                  if (ceol_standout_glitch)
 405  404                          /* Attributes on an HP terminal do not cross lines. */
 406  405                          ATTR_STATE = A_NORMAL;
 407  406                  else
 408  407                          (void) vid_puts(WA_NORMAL, 0, (void *) 0, __m_outc);
 409  408          }
 410  409  
 411  410          /* Re-check for clear to end-of-line optimization. */
 412  411          if (clr_eol != (char *) 0 && tail <= col && col < last) {
 413  412                  /* Is the tail of the current screen image non-blank? */
 414  413                  for (tail = col; tail < COLS; ++tail, ++optr)
 415  414                          if (!__m_cc_compare(optr, &newscr->_bg, 1))
 416  415                                  break;
 417  416  
 418  417                  /* If tail didn't reach the right margin of
 419  418                   * the current screen image, then we will
 420  419                   * make it look like the new image with a
 421  420                   * clear to end-of-line.
 422  421                   */
 423  422                  if (tail < COLS) {
 424  423                          /* Restore default color pair before area clear. */
 425  424                          if (back_color_erase)
 426  425                                  (void) vid_puts(
 427  426                                          WA_NORMAL, 0, (void *) 0, __m_outc
 428  427                                  );
 429  428  
 430  429                          (void) tputs(clr_eol, 1, __m_outc);
 431  430                          __m_cc_erase(curscr, row, tail, row, COLS-1);
 432  431                  }
 433  432          } 
 434  433  
 435  434          /* Line wrapping checks. */
 436  435          if (COLS <= curscr->_curx) {
 437  436                  --curscr->_curx;
 438  437                  if (auto_right_margin && row < LINES-1) {
 439  438                          if (eat_newline_glitch) {
 440  439                                  __m_outc('\r');
 441  440                                  __m_outc('\n');
 442  441                          }
 443  442                          ++curscr->_cury;
 444  443                          curscr->_curx = 0;
 445  444                  }
 446  445          } 
 447  446  }
 448  447  
 449  448  /*f
 450  449   * Replace a block of lines.
 451  450   * Only ever used for complex().
 452  451   */
 453  452  STATIC void 
 454  453  lines_replace(from, to_1)
 455  454  int from, to_1;
 456  455  {
 457  456          for (; from < to_1; ++from)
 458  457                  text_replace(from);
 459  458  }
 460  459  
 461  460  /*f
 462  461   * Delete a block of lines.
 463  462   * Only ever used for complex().
 464  463   */
 465  464  STATIC void 
 466  465  lines_delete(from, to_1)
 467  466  int from, to_1;
 468  467  {
 469  468          int count = to_1 - from;
 470  469  
 471  470          if (LINES <= to_1) {
 472  471                  clear_bottom(from);
 473  472          } else {
 474  473                  GOTO(from, 0);
 475  474                  (void) winsdelln(curscr, -count);
 476  475  
 477  476                  if (parm_delete_line != (char *) 0) {
 478  477                          /* Assume that the sequence to delete more than one 
 479  478                           * line is faster than repeated single delete_lines. 
 480  479                           */
 481  480                          (void) tputs(
 482  481                                  tparm(
 483  482                                          parm_delete_line, (long) count,
 484  483                                          0, 0, 0, 0, 0, 0, 0, 0
 485  484                                  ), count, __m_outc
 486  485                          );
 487  486                  } else if (delete_line != (char *) 0) {
 488  487                          while (from++ < to_1)
 489  488                                  (void) tputs(delete_line, 1, __m_outc);
 490  489                  } else  {
 491  490                          /* Error -- what to do. */
 492  491                          return;
 493  492                  }
 494  493          }
 495  494  }
 496  495  
 497  496  /*f
 498  497   * Insert a block of lines.
 499  498   * Only ever used for complex().
 500  499   *
 501  500   * We must assume that insert_line and parm_insert_line reset the 
 502  501   * cursor column to zero.  Therefore it is text_replace() responsiblity
 503  502   * to move the cursor to the correct column to begin the update.
 504  503   */
 505  504  STATIC void 
 506  505  lines_insert(from, to_1)
 507  506  int from, to_1;
 508  507  {
 509  508          int row, count = to_1 - from;
 510  509  
 511  510          /* Position the cursor and insert a block of lines into the screen
 512  511           * image now, insert lines into the physical screen, then draw the
 513  512           * new screen lines.  
 514  513           */ 
 515  514          GOTO(from, 0);
 516  515          (void) winsdelln(curscr, count);
 517  516  
 518  517          if (parm_insert_line != (char *) 0) {
 519  518                  /* Assume that the sequence to insert more than one line is
 520  519                   * faster than repeated single insert_lines. 
 521  520                   */
 522  521                  (void) tputs(
 523  522                          tparm(
 524  523                                  parm_insert_line, (long) count,
 525  524                                  0, 0, 0, 0, 0, 0, 0, 0
 526  525                          ), count, __m_outc
 527  526                  );
 528  527          } else if (insert_line != (char *) 0) {
 529  528                  /* For the single line insert we use to iterate moving
 530  529                   * the cursor, inserting, and then drawing a line.  That
 531  530                   * would appear to be slow but visually appealing.  However,
 532  531                   * people on slow terminals want speed and those on fast
 533  532                   * terminal won't see it.
 534  533                   */
 535  534                  for (row = from; row < to_1; ++row)
 536  535                          (void) tputs(insert_line, 1, __m_outc);
 537  536          } else {
 538  537                  /* Error -- what to do. */
 539  538                  return;
 540  539          }
 541  540  
 542  541          for (row = from; row < to_1; ++row)
 543  542                  text_replace(row);
 544  543  }
 545  544  
 546  545  STATIC int
 547  546  scroll_up(n)
 548  547  int n;
 549  548  {
 550  549          int count = n;
 551  550          int start, finish, to, row;
 552  551  
 553  552          if (scroll_forward != (char *) 0) {
 554  553                  GOTO(LINES-1, 0);
 555  554                  while (0 < n--)
 556  555                          (void) tputs(scroll_forward, 1, __m_outc);
 557  556          } else if (parm_delete_line != (char *) 0 && 1 < n) {
 558  557                  GOTO(0, 0);
 559  558                  (void) tputs(
 560  559                          tparm(
 561  560                                  parm_delete_line, (long) n, 
 562  561                                  0, 0, 0, 0, 0, 0, 0, 0
 563  562                          ), n, __m_outc
 564  563                  );
 565  564          } else if (delete_line != (char *) 0) {
 566  565                  GOTO(0, 0);
 567  566                  while (0 < n--)
 568  567                          (void) tputs(delete_line, 1, __m_outc);
 569  568          } else {
 570  569                  return 0;
 571  570          }
 572  571  
 573  572          /* Scroll recorded image. */
 574  573          start = 0;
 575  574          finish = count-1;
 576  575          to = lines;
 577  576  
 578  577          (void) __m_cc_erase(curscr, start, 0, finish, curscr->_maxx-1);
 579  578          (void) __m_ptr_move(
 580  579                  (void **) curscr->_line, curscr->_maxy, start, finish, to
 581  580          ); 
 582  581  
 583  582          simple();
 584  583  
 585  584          return 1;
 586  585  }
 587  586  
 588  587  STATIC int 
 589  588  scroll_dn(n)
 590  589  int n;
 591  590  {
 592  591          int count = n;
 593  592          int start, finish, to, row;
 594  593  
 595  594          if (LINES < n)
 596  595                  return 0;
 597  596  
 598  597          if (scroll_reverse != (char *) 0) {
 599  598                  GOTO(0, 0);
 600  599                  while (0 < n--)
 601  600                          (void) tputs(scroll_reverse, 1, __m_outc);
 602  601          } else if (parm_insert_line != (char *) 0 && 1 < n) {
 603  602                  GOTO(0, 0);
 604  603                  (void) tputs(
 605  604                          tparm(
 606  605                                  parm_insert_line, (long) n, 
 607  606                                  0, 0, 0, 0, 0, 0, 0, 0
 608  607                          ), n, __m_outc
 609  608                  );
 610  609          } else if (insert_line != (char *) 0) {
 611  610                  GOTO(0, 0);
 612  611                  while (0 < n--)
 613  612                          (void) tputs(insert_line, 1, __m_outc);
 614  613          } else {
 615  614                  return 0;
 616  615          }
 617  616  
 618  617          /* Scroll recorded image. */
 619  618          start = lines - count;
 620  619          finish = lines - 1;
 621  620          to = 0;
 622  621  
 623  622          (void) __m_cc_erase(curscr, start, 0, finish, curscr->_maxx-1);
 624  623          (void) __m_ptr_move(
 625  624                  (void **) curscr->_line, curscr->_maxy, start, finish, to
 626  625          ); 
 627  626  
 628  627          simple();
 629  628  
 630  629          return 1;
 631  630  }
 632  631  
 633  632  #ifdef NEVER
 634  633  STATIC int
 635  634  is_same_line(old, new, count)
 636  635  cchar_t *old, *new;
 637  636  int count;
 638  637  {
 639  638          while (0 < count--)
 640  639                  if (!__m_cc_compare(old, new, 1))
 641  640                          return 0;
 642  641  
 643  642          return 1;
 644  643  }
 645  644  #endif /* NEVER */
 646  645  
 647  646  /*f
 648  647   * Dynamic programming algorithm for the string edit problem.
 649  648   *
 650  649   * This is a modified Gosling cost algorithm that takes into account
 651  650   * null/move operations. 
 652  651   *
 653  652   * Costs for move, delete, replace, and insert are 0, 1, 2, and 3
 654  653   * repectively. 
 655  654   */
 656  655  STATIC int
 657  656  cost(fr, lr)
 658  657  int fr, lr;
 659  658  {
 660  659          register lcost *lcp;
 661  660          register int or, nr, cc;
 662  661          register unsigned long *ohash = __m_screen->_hash;
 663  662          cchar_t **oline = curscr->_line;
 664  663          cchar_t **nline = newscr->_line;
 665  664          int linesz = COLS * sizeof **oline;
 666  665  
 667  666          /* Prepare initial row and column of cost matrix. 
 668  667           *
 669  668           *      0 3 6 9 ...
 670  669           *      1
 671  670           *      2
 672  671           *      3
 673  672           *      :
 674  673           */
 675  674          LC(fr,fr).cost = 0;
 676  675          for (cc = 1, ++lr, nr = fr+1; nr <= lr; ++nr, ++cc) {
 677  676                  /* Top row is 3, 6, 9, ... */
 678  677                  LC(fr,nr).cost = cc * 3;
 679  678                  LC(fr,nr).op = 'i';
 680  679  
 681  680                  /* Left column is 1, 2, 3, ... */
 682  681                  LC(nr,fr).cost = cc; 
 683  682                  LC(nr,fr).op = 'd'; 
 684  683          }
 685  684  
 686  685          for (--lr, or = fr; or <= lr; ++or) {
 687  686                  for (nr = fr; nr <= lr; ++nr) {
 688  687                          lcp = &LC(or+1,nr+1);
 689  688  
 690  689                          /* Assume move op. */
 691  690                          lcp->cost = LC(or,nr).cost; 
 692  691                          lcp->op = 'm';
 693  692  
 694  693                          if (ohash[or] != nhash[nr]
 695  694  #ifdef NEVER
 696  695  /* Should no longer require this code.  Using the POSIX 32-bit CRC to
 697  696   * generate a hash value should be sufficient now, since text_replace() 
 698  697   * will compare the contents of a line and output only the dirty regions.
 699  698   */
 700  699                          || !is_same_line(oline[or], nline[nr], linesz)
 701  700  #endif
 702  701                          ) {
 703  702                                  /* Lines are different, assume replace op. */
 704  703                                  lcp->cost += 2;
 705  704                                  lcp->op = 'r';
 706  705                          }
 707  706  
 708  707                          /* Compare insert op. */
 709  708                          if ((cc = LC(or+1,nr).cost + 3) < lcp->cost) {
 710  709                                  lcp->cost = cc;
 711  710                                  lcp->op = 'i';
 712  711                          }
 713  712  
 714  713                          /* Compare delete op. */
 715  714                          if ((cc = LC(or,nr+1).cost + 1) < lcp->cost) {
 716  715                                  lcp->cost = cc;
 717  716                                  lcp->op = 'd';
 718  717                          }
 719  718                  }
 720  719          }
 721  720  
 722  721          return LC(lr+1,lr+1).cost;
 723  722  }
 724  723  
 725  724  /*f
 726  725   * Build edit script.
 727  726   *
 728  727   * Normally this would be a recursve routine doing the deletes, inserts,
 729  728   * and replaces on individual lines. Instead we build the script so that
 730  729   * we can later do the operations on a block basis.  For terminals with
 731  730   * parm_delete or parm_insert strings this will be better in terms of the
 732  731   * number of characters sent to delete and insert a block of lines.
 733  732   *
 734  733   * Also we can optimize the script so that tail inserts become replaces.
 735  734   * This saves unnecessary inserts operations when the tail can just be
 736  735   * overwritten.
 737  736   */
 738  737  STATIC void
 739  738  script(fr, lr)
 740  739  int fr, lr;
 741  740  {
 742  741          int i, j;
 743  742          cchar_t *cp;
 744  743  
 745  744          i = j = lr + 1; 
 746  745  
 747  746          memset(del, 0, sizeof *del * LINES);
 748  747          memset(ins_rep, 0, sizeof *ins_rep * LINES);
 749  748  
 750  749          do {
 751  750                  /* We don't have to bounds check i or j becuase row fr and 
 752  751                   * column fr of lc have been preset in order to guarantee the 
 753  752                   * correct motion.
 754  753                   */
 755  754                  switch (LC(i,j).op) {
 756  755                  case 'i':
 757  756                          --j;
 758  757                          ins_rep[j] = lines_insert;
 759  758                          break;
 760  759                  case 'd':
 761  760                          --i;
 762  761                          del[i] = lines_delete;
 763  762                          break;
 764  763                  case 'm':
 765  764                          --i;
 766  765                          --j;
 767  766                          break;
 768  767                  case 'r':
 769  768                          --i;
 770  769                          --j;
 771  770                          ins_rep[j] = lines_replace;
 772  771                          break;
 773  772                  }
 774  773          } while (fr < i || fr < j);
 775  774  
 776  775          /* Optimize Tail Inserts */
 777  776          for (i = LINES-1; 0 <= i && ins_rep[i] == lines_insert; --i) {
 778  777                  /* Make each character in the screen line image invalid. */
 779  778                  for (cp = curscr->_line[i], j = 0; j < COLS; ++j, ++cp)
 780  779                          cp->_n = -1;
 781  780                  ins_rep[i] = lines_replace;
 782  781          }
 783  782  }
 784  783   
 785  784  /*f
 786  785   * Complex update algorithm using insert/delete line operations.
 787  786   *
 788  787   * References:
 789  788   * [MyM86]      E.W. Myers & W. Miller, Row Replacement Algorithms for 
 790  789   *              Screen Editors, TR 86-19, Dept. Computer Science, U. of Arizona
 791  790   * [MyM87]      E.W. Myers & W. Miller, A Simple Row Replacement Method,
 792  791   *              TR 86-28, Dept. Computer Science, U. of Arizona
 793  792   * [Mil87]      W. Miller, A Software Tools Sampler, Prentice-Hall, 1987
 794  793   * [Gos81]      James Gosling, A redisplay algorithm, Proceedings of the 
 795  794   *              ACM Symposium on Text Manipulation, SIGPLAN Notices, 
 796  795   *              16(6) June 1981, pg 123-129
 797  796   *
 798  797   * All the above were reviewed and experimented with.  Due to the nature of
 799  798   * Curses' having to handling overlapping WINDOWs, the only suitable
 800  799   * algorithum is [Gos81].  The others are better suited to editor type
 801  800   * applications that have one window being the entire terminal screen.
 802  801   *
 803  802   */
 804  803  STATIC void
 805  804  complex()
 806  805  {
 807  806          int fr = -1;
 808  807          int i, j, lr;
 809  808          t_action func;
 810  809  
 811  810          /* Find block of lines to change */
 812  811          for (i = 0; i < LINES; ++i) {
 813  812                  if (newscr->_first[i] < newscr->_last[i]) {
 814  813                          /* Compute new hash. */
 815  814                          __m_cc_hash(newscr, nhash, i);
 816  815                          if (fr == -1)
 817  816                                  fr = i;
 818  817                          lr = i;
 819  818                  } else {
 820  819                          /* Line not dirty so hash same as before. */
 821  820                          nhash[i] = __m_screen->_hash[i];
 822  821                  }
 823  822          }
 824  823  
 825  824          if (fr != -1) {
 826  825                  /* Gosling */
 827  826                  cost(fr, lr);
 828  827                  script(fr, lr);
 829  828  
 830  829                  /* Do deletes first in reverse order. */
 831  830                  for (j = lr; fr <= j; --j) {
 832  831                          if (del[j] != (t_action) 0) {
 833  832                                  for (i = j-1; fr <= i; --i)
 834  833                                          if (del[i] == (t_action) 0)
 835  834                                                  break;
 836  835  
 837  836                                  lines_delete(i+1, j+1);
 838  837                                  j = i;
 839  838                          }
 840  839                  }
 841  840  
 842  841                  /* Do insert/replace in forward order. */
 843  842                  for (i = fr; i <= lr; ++i) {
 844  843                          if ((func = ins_rep[i]) != (t_action) 0) {
 845  844                                  /* Find size of block */
 846  845                                  for (j = i; j <= lr && ins_rep[j] == func; ++j)
 847  846                                          ;
 848  847                                  (*func)(i, j);
 849  848                                  i = j-1;
 850  849                          }
 851  850                  }
 852  851  record:
 853  852                  /* _line[], which contains pointers to screen lines, 
 854  853                   * may be shuffled.
 855  854                   */
 856  855                  for (i = fr; i <= lr; ++i) {
 857  856                          /* Save new hash for next update. */
 858  857                          __m_screen->_hash[i] = nhash[i];
 859  858  
 860  859                          /* Mark line as untouched. */
 861  860                          newscr->_first[i] = newscr->_maxx;
 862  861                          newscr->_last[i] = -1;
 863  862                  }
 864  863          }
 865  864  }
 866  865  
 867  866  /*f
 868  867   * Simple screen update algorithm
 869  868   *
 870  869   * We perform a simple incremental update of the terminal screen. 
 871  870   * Only the segment of a line that was touched is replaced on the 
 872  871   * line.
 873  872   */
 874  873  STATIC void
 875  874  simple()
 876  875  {
 877  876          int row;
 878  877  
 879  878          for (row = 0; row < LINES; ++row) {
 880  879                  if (newscr->_first[row] < newscr->_last[row]) {
 881  880                          text_replace(row);
 882  881  
 883  882                          /* Mark line as untouched. */
 884  883                          newscr->_first[row] = newscr->_maxx;
 885  884                          newscr->_last[row] = -1;
 886  885  
 887  886                          if (__m_screen->_flags & S_INS_DEL_LINE)
 888  887                                  __m_cc_hash(newscr, nhash, row);
 889  888                  }
 890  889          }
 891  890  
 892  891          newscr->_flags &= ~W_REDRAW_WINDOW;
 893  892  }
 894  893  
 895  894  /*f
 896  895   * Send all changes made to _newscr to the physical terminal.
 897  896   *
 898  897   * If idlok() is set TRUE then doupdate will try and use hardware insert
 899  898   * and delete line sequences in an effort to optimize output.  idlok()
 900  899   * should really only be used in applications that want a proper scrolling
 901  900   * effect.
 902  901   * 
 903  902   * Added scroll heuristic to handle special case where a full size window
 904  903   * with full size scroll region, will scroll the window and replace dirty
 905  904   * lines instead of performing usual cost/script operations.
  
    | 
      ↓ open down ↓ | 
    867 lines elided | 
    
      ↑ open up ↑ | 
  
 906  905   */
 907  906  int 
 908  907  doupdate()
 909  908  {
 910  909  #ifdef SIGTSTP
 911  910          int (*oldsig)(int) = signal(SIGTSTP, SIG_IGN);
 912  911  #endif
 913  912  
 914  913  #ifdef M_CURSES_TYPEAHEAD
 915  914          unsigned char cc;
 916      -        int min, time, icanon;
      915 +        volatile int min, time, icanon;
 917  916  
 918  917          if (__m_screen->_flags & S_ISATTY) {
 919  918                  /* Set up non-blocking input for typeahead trapping. */
 920  919                  min = cur_term->_prog.c_cc[VMIN];
 921  920                  time = cur_term->_prog.c_cc[VTIME];
 922  921                  icanon = cur_term->_prog.c_lflag & ICANON;
 923  922  
 924  923                  cur_term->_prog.c_cc[VMIN] = 0;
 925  924                  cur_term->_prog.c_cc[VTIME] = 0;
 926  925                  cur_term->_prog.c_lflag &= ~ICANON;
 927  926  
 928  927                  (void) tcsetattr(__m_screen->_kfd, TCSANOW, &cur_term->_prog);
 929  928          }
 930  929  #endif /* M_CURSES_TYPEAHEAD */
 931  930  
 932  931  #ifdef M_CURSES_TRACE
 933  932          __m_trace(
 934  933                  "doupdate(void) using %s algorithm.", 
 935  934                  (__m_screen->_flags & S_INS_DEL_LINE) ? "complex" : "simple"
 936  935          );
 937  936  #endif
 938  937  
 939  938          newscr = __m_screen->_newscr;
 940  939  
 941  940          if (__m_screen->_flags & S_ENDWIN) {
 942  941                  /* Return from temporary escape done with endwin(). */
 943  942                  __m_screen->_flags &= ~S_ENDWIN;
 944  943  
 945  944                  (void) reset_prog_mode();
 946  945                  if (enter_ca_mode != (char *) 0)
 947  946                          (void) tputs(enter_ca_mode, 1, __m_outc);
 948  947                  if (keypad_xmit != (char *) 0)
 949  948                          (void) tputs(keypad_xmit, 1, __m_outc);
 950  949                  if (ena_acs != (char *) 0)
 951  950                          (void) tputs(ena_acs, 1, __m_outc);
 952  951  
 953  952                  /* Force redraw of screen. */
 954  953                  newscr->_flags |= W_CLEAR_WINDOW;
 955  954          }
 956  955  
 957  956  #ifdef M_CURSES_TYPEAHEAD
 958  957          if (setjmp(breakout) == 0) {
 959  958                  if ((__m_screen->_flags & S_ISATTY)
 960  959                  && read(__m_screen->_kfd, &cc, sizeof cc) == sizeof cc) {
 961  960                          (void) ungetch(cc);
 962  961                          longjmp(breakout, 1);
 963  962                  }
 964  963  #endif /* M_CURSES_TYPEAHEAD */
 965  964  
 966  965                  /* When redrawwing a window, we not only assume that line 
 967  966                   * noise may have lost characters, but line noise may have
 968  967                   * generated bogus characters on the screen outside the
 969  968                   * the window in question, in which case redraw the entire
 970  969                   * screen to be sure.
 971  970                   */
 972  971                  if (newscr->_flags & (W_CLEAR_WINDOW | W_REDRAW_WINDOW)) {
 973  972                          clear_bottom(0);
 974  973                          newscr->_flags &= ~W_CLEAR_WINDOW;
 975  974                          (void) wtouchln(newscr, 0, newscr->_maxy, 1);
 976  975                  }
 977  976  
 978  977                  if (newscr->_flags & W_REDRAW_WINDOW)
 979  978                          simple();
 980  979  #if 0           /* This first expression, of undefined section, is useless
 981  980                   * since newscr->_scroll is unsigned and never LT zero.
 982  981                   */
 983  982                  else if (newscr->_scroll < 0 && scroll_dn(-newscr->_scroll))
 984  983  #else
 985  984                  else if (scroll_dn(-newscr->_scroll))
 986  985  #endif
 987  986                          ;
 988  987                  else if (0 < newscr->_scroll && scroll_up(newscr->_scroll))
 989  988                          ;
 990  989                  else if (__m_screen->_flags & S_INS_DEL_LINE)
 991  990                          complex();
 992  991                  else
 993  992                          simple();
 994  993  
 995  994                  if (!(newscr->_flags & W_LEAVE_CURSOR))
 996  995                          GOTO(newscr->_cury, newscr->_curx);
 997  996  
 998  997                  if (!(curscr->_flags & W_FLUSH))
 999  998                          (void) fflush(__m_screen->_of);
1000  999  #ifdef M_CURSES_TYPEAHEAD
1001 1000          }
1002 1001  
1003 1002          if (__m_screen->_flags & S_ISATTY) {
1004 1003                  /* Restore previous input mode. */
1005 1004                  cur_term->_prog.c_cc[VMIN] = min;
1006 1005                  cur_term->_prog.c_cc[VTIME] = time;
1007 1006                  cur_term->_prog.c_lflag |= icanon;
1008 1007  
1009 1008                  (void) tcsetattr(__m_screen->_kfd,TCSANOW,&cur_term->_prog);
1010 1009          }
1011 1010  #endif /* M_CURSES_TYPEAHEAD */
1012 1011  
1013 1012          newscr->_scroll = curscr->_scroll = 0;
1014 1013  #ifdef SIGTSTP
1015 1014          signal(SIGTSTP, oldsig);
1016 1015  #endif
1017 1016  
1018 1017          return __m_return_code("doupdate", OK);
1019 1018  }
1020 1019  
1021 1020  /*
1022 1021   * If true, the implementation may use hardware insert and delete,
1023 1022   * character features of the terminal.  The window parameter
1024 1023   * is ignored.
1025 1024   */
1026 1025  void
1027 1026  idcok(WINDOW *w, bool bf)
1028 1027  {
1029 1028  #ifdef M_CURSES_TRACE
1030 1029          __m_trace("idcok(%p, %d)", w, bf);
1031 1030  #endif
1032 1031   
1033 1032          __m_screen->_flags &= ~S_INS_DEL_CHAR;
1034 1033          if (bf)
1035 1034                  __m_screen->_flags |= S_INS_DEL_CHAR;
1036 1035  
1037 1036          __m_return_void("idcok");
1038 1037  }
1039 1038   
1040 1039  /*
1041 1040   * If true, the implementation may use hardware insert, delete,
1042 1041   * and scroll line features of the terminal.  The window parameter
1043 1042   * is ignored.
1044 1043   */
1045 1044  int
1046 1045  idlok(WINDOW *w, bool bf)
1047 1046  {
1048 1047  #ifdef M_CURSES_TRACE
1049 1048          __m_trace("idlok(%p, %d)", w, bf);
1050 1049  #endif
1051 1050  
1052 1051          __m_screen->_flags &= ~S_INS_DEL_LINE;
1053 1052          if (bf && has_il())
1054 1053                  __m_screen->_flags |= S_INS_DEL_LINE;
1055 1054  
1056 1055          return __m_return_code("idlok", OK);
1057 1056  }
1058 1057  
1059 1058  /*
1060 1059   * Use the POSIX 32-bit CRC function to compute a hash value 
1061 1060   * for the window line.
1062 1061   */
1063 1062  void
1064 1063  __m_cc_hash(w, array, y)
1065 1064  WINDOW *w;
1066 1065  unsigned long *array;
1067 1066  int y;
1068 1067  {
1069 1068          array[y] = 0;
1070 1069          m_crcposix(
1071 1070                  &array[y], (unsigned char *) w->_line[y], 
1072 1071                  (size_t) (w->_maxx * sizeof **w->_line)
1073 1072          );
1074 1073  }
1075 1074  
1076 1075  
  
    | 
      ↓ open down ↓ | 
    150 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX