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