1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1988 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California
33 * All Rights Reserved
34 *
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
38 */
39
40 #pragma ident "%Z%%M% %I% %E% SMI"
41
42 /*LINTLIBRARY*/
43
44 #include <sys/types.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include "curses_inc.h"
48
49 /*
50 * Make the screen look like "win" over the area covered by win.
51 * This routine may use insert/delete char/line and scrolling-region.
52 * win : the window being updated
53 */
54
55 extern int outchcount;
56
57 static void _updateln(int), _turn_off_background(void),
58 _setmark1(int, int, chtype *),
59 _setmark2(int, int, chtype *), _rmargin(int),
60 _useceod(int, int);
61 static int _useidch(chtype *, chtype *, int, int, int *),
62 _prefix(chtype *, chtype *, int, int, int *),
63 _getceod(int, int);
64
65 static short cy, cx, /* current cursor coord */
66 scrli, /* actual screen lines */
67 scrco; /* actual screen columns */
68 static char **marks; /* the mark table for cookie terminals */
69 static char **color_marks; /* color mark table for cookie terminals */
70
71 #define _ISMARK1(y, x) (marks[y][x / BITSPERBYTE] & (1 << (x % BITSPERBYTE)))
72 #define _ISMARK2(y, x) (color_marks ? (color_marks[y][x / BITSPERBYTE] & \
73 (1 << (x % BITSPERBYTE))) : FALSE)
74
75 #define _VIDEO(c) ((c) & A_ATTRIBUTES & ~A_COLOR)
76 #define _COLOR(c) ((c) & A_COLOR)
77
78 #ifdef _VR2_COMPAT_CODE
79 extern char _endwin;
80 #endif /* _VR2_COMPAT_CODE */
81
82 int
wrefresh(WINDOW * win)83 wrefresh(WINDOW *win)
84 {
85
86 short *bnsch, *ensch;
87 SLK_MAP *slk;
88 int wx, wy, nc, boty, clby, idby, *hs, curwin;
89
90 curwin = (win == curscr);
91
92 /* don't allow curscr refresh if the screen was just created */
93
94 if (curwin && curscr->_sync)
95 return (OK);
96
97 /* go thru _stdbody */
98 if (!curwin && (win != _virtscr))
99 (void) wnoutrefresh(win);
100
101 /* if there is typeahead */
102 if ((_INPUTPENDING = _chkinput()) == TRUE) {
103 if (curwin)
104 curscr->_clear = TRUE;
105 return (OK);
106 }
107
108 if (curwin || curscr->_clear)
109 _virtscr->_clear = TRUE;
110
111 /* save curscr cursor coordinates */
112 cy = curscr->_cury;
113 cx = curscr->_curx;
114
115 /* to simplify code in some cases */
116 marks = _MARKS;
117 color_marks = _COLOR_MARKS;
118 scrli = curscr->_maxy;
119 scrco = curscr->_maxx;
120 slk = SP->slk;
121
122 outchcount = 0;
123
124 /* make sure we're in program mode */
125 if (SP->fl_endwin) {
126 /* If endwin is equal to 2 it means we just did a newscreen. */
127 if (SP->fl_endwin == TRUE) {
128 (void) reset_prog_mode();
129 if (SP->kp_state)
130 (void) tputs(keypad_xmit, 1, _outch);
131 if (slk)
132 (*_do_slk_tch)();
133 if (SP->fl_meta)
134 (void) tputs(meta_on, 1, _outch);
135 if (cur_term->_cursorstate != 1)
136 _PUTS(cur_term->cursor_seq[cur_term->
137 _cursorstate], 0);
138 }
139 _PUTS(enter_ca_mode, 1);
140 (void) tputs(ena_acs, 1, _outch);
141
142 if (exit_attribute_mode)
143 _PUTS(tparm_p0(exit_attribute_mode), 1);
144 else
145 /*
146 * If there is no exit_attribute mode, then vidupdate
147 * could only possibly turn off one of the below three
148 * so that's all we ask it turn off.
149 */
150 vidupdate(A_NORMAL, (A_ALTCHARSET | A_STANDOUT |
151 A_UNDERLINE), _outch);
152
153 SP->fl_endwin = FALSE;
154
155 #ifdef _VR2_COMPAT_CODE
156 _endwin = (char) FALSE;
157 #endif /* _VR2_COMPAT_CODE */
158 }
159
160 /* clear the screen if required */
161 if (_virtscr->_clear) {
162 /* SS: colors */
163 if (back_color_erase)
164 _turn_off_background();
165
166 _PUTS(clear_screen, scrli);
167 cy = cx = curscr->_curx = curscr->_cury = 0;
168
169 /* _sync indicates that this a new screen */
170 if (!curscr->_sync)
171 (void) werase(curscr);
172 else {
173 nc = scrco / BITSPERBYTE - (scrco %
174 BITSPERBYTE ? 0 : 1);
175 wy = scrli - 1;
176 bnsch = _BEGNS; ensch = _ENDNS;
177 hs = _CURHASH;
178 for (; wy >= 0; --wy) {
179 *bnsch++ = scrco;
180 *ensch++ = -1;
181 *hs++ = 0;
182 if (marks)
183 for (wx = nc; wx >= 0; --wx)
184 marks[wy][wx] = 0;
185 }
186 }
187
188 _virtscr->_clear = curscr->_sync = curscr->_clear = FALSE;
189 if (slk)
190 (*_do_slk_tch)();
191
192 /* pretend _virtscr has been totally changed */
193 (void) wtouchln(_virtscr, 0, scrli, -1);
194 _VIRTTOP = 0;
195 _VIRTBOT = scrli - 1;
196
197 /* will not do clear-eod or ins/del lines */
198 clby = idby = scrli;
199 } else
200 clby = idby = -1;
201
202 /* Software soft labels; if _changed == 2, slk's are in clear mode. */
203 if (slk && slk->_win && (slk->_changed == TRUE))
204 (*_do_slk_noref)();
205
206 /* do line updating */
207 _virtscr->_clear = FALSE;
208 wy = _VIRTTOP;
209 boty = _VIRTBOT + 1;
210 bnsch = _virtscr->_firstch + wy;
211 ensch = _virtscr->_lastch + wy;
212
213 for (; wy < boty; ++wy, ++bnsch, ++ensch) {
214 /* this line is up-to-date */
215 if (*bnsch >= scrco)
216 goto next;
217
218 /* there is type-ahead */
219 if (!curwin && (_INPUTPENDING = _chkinput()) == TRUE) {
220 /* LINTED */
221 _VIRTTOP = (short) wy;
222 goto done;
223 }
224
225 if (clby < 0) {
226 /* now we have to work, check for ceod */
227 clby = _getceod(wy, boty);
228
229 /* check for insert/delete lines */
230 if (_virtscr->_use_idl)
231 idby = (*_setidln)();
232 }
233
234 /* try clear-to-eod */
235 if (wy == clby)
236 _useceod(wy, boty);
237
238 /* try ins/del lines */
239 if (wy == idby) {
240 curscr->_cury = cy;
241 curscr->_curx = cx;
242 (*_useidln)();
243 cy = curscr->_cury;
244 cx = curscr->_curx;
245 }
246
247 if (*bnsch < scrco)
248 _updateln(wy);
249
250 next:
251 *bnsch = _INFINITY;
252 *ensch = -1;
253 }
254
255 /* do hardware soft labels; if _changed == 2, */
256 /* slk's are in clear mode. */
257 if (slk && (slk->_changed == TRUE) && !(slk->_win))
258 (*_do_slk_ref)();
259
260 /* move cursor */
261 wy = _virtscr->_cury;
262 wx = _virtscr->_curx;
263 if (wy != cy || wx != cx) {
264 (void) mvcur(cy, cx, wy, wx);
265 /* LINTED */
266 cy = (short) wy;
267 /* LINTED */
268 cx = (short) wx;
269 }
270
271 /* reset the flags */
272 curscr->_clear = FALSE;
273 _virtscr->_use_idl = FALSE;
274 _virtscr->_use_idc = TRUE;
275 _INPUTPENDING = FALSE;
276
277 /* virtual image is now up-to-date */
278 _VIRTTOP = scrli;
279 _VIRTBOT = -1;
280
281 done :
282 curscr->_cury = cy;
283 curscr->_curx = cx;
284 (void) fflush(SP->term_file);
285 return (outchcount);
286 }
287
288 /* Shift appropriate portions of a line to leave space for cookies. */
289
290 static chtype *
_shove(int wy)291 _shove(int wy)
292 {
293 chtype *wcp, *cp, prev;
294 short curx;
295 int x, cury, didshift;
296 static chtype *line;
297 static int length;
298
299 /* allocate space for shifted line */
300 if (length < scrco) {
301 if (line)
302 free((char *) line);
303 line = (chtype *) malloc(scrco * sizeof (chtype));
304 length = line ? scrco : 0;
305 }
306
307 /* no space to do it */
308 if (!line)
309 return (_virtscr->_y[wy]);
310
311 prev = A_NORMAL;
312 cp = line;
313 wcp = _virtscr->_y[wy];
314 curx = _virtscr->_curx;
315 cury = _virtscr->_cury;
316 didshift = FALSE;
317
318 for (x = 0; x < scrco; ++x, ++wcp, ++cp) {
319 if (_ATTR(*wcp) != prev) {
320 /* use existing blank */
321 if (_CHAR(*wcp) == ' ')
322 *cp = ' ' | _ATTR(*(wcp + 1));
323 /* use previous blank */
324 else
325 if ((x > 0) && _CHAR(*(cp - 1)) == ' ') {
326 *(cp - 1) = ' ' | _ATTR(*wcp);
327 *cp = *wcp;
328 } else {
329 if ((curx >= x) && (cury == wy))
330 ++curx;
331 *cp = ' ' | _ATTR(*wcp);
332 --wcp;
333 didshift = TRUE;
334 }
335 prev = _ATTR(*cp);
336 } else
337 *cp = *wcp;
338 }
339
340 /* make sure that the end of the line is normal */
341 cp = line + scrco - 1;
342 if (didshift || (_ATTR(*cp) != A_NORMAL) ||
343 ((wy == scrli - 1) && (_ATTR(*(cp - 1)) != A_NORMAL))) {
344 *cp = didshift ? ' ' : _CHAR(*cp);
345 if (wy == scrli - 1)
346 *(cp - 1) = didshift ? ' ' : _CHAR(*(cp - 1));
347 }
348
349 if (wy == cury)
350 _virtscr->_curx = curx >= scrco ? scrco - 1 : curx;
351
352 return (line);
353 }
354
355 /*
356 * Update a line.
357 * Three schemes of coloring are allowed. The first is the usual
358 * pen-up/pen-down model. The second is the HP26*-like model.
359 * In this case, colorings are specified by intervals, the left
360 * side of the interval has the coloring mark, the right side
361 * has the end-coloring mark. We assume that clear sequences will
362 * clear ALL marks in the affected regions. The second case is
363 * signified by the boolean flag ceol_standout_glitch.
364 * The third case is for terminals that leave visible cookies on
365 * the screen. This last case is at most an approximation of what
366 * can be done right.
367 */
368
369 static void
_updateln(int wy)370 _updateln(int wy)
371 {
372 chtype *wcp, *scp, *wp, *sp, wc, sc;
373 int wx, lastx, x, mtch, idch, blnkx, idcx, video_attrx,
374 color_attrx, maxi, endns, begns, wx_sav, multi_col;
375 bool redraw, changed, didcolor, didvideo;
376
377 redraw = (_virtscr->_firstch[wy] == _REDRAW);
378 endns = _ENDNS[wy];
379 begns = _BEGNS[wy];
380
381 /* easy case */
382 if (!redraw && (_virtscr->_lastch[wy] == _BLANK) && (begns >= scrco))
383 return;
384
385 /* line images */
386 wcp = magic_cookie_glitch <= 0 ? _virtscr->_y[wy] : _shove(wy);
387 scp = curscr->_y[wy];
388
389 /* the interval to be updated */
390 if (redraw || magic_cookie_glitch >= 0) {
391 wx = 0;
392 lastx = scrco;
393 } else {
394 wx = _virtscr->_firstch[wy];
395 lastx = _virtscr->_lastch[wy] == _BLANK ? scrco :
396 _virtscr->_lastch[wy] + 1;
397 }
398
399 /* skip equal parts */
400 if (!redraw) {
401 /* skip the starting equal part */
402 wp = wcp + wx;
403 sp = scp + wx;
404 for (; wx < lastx; ++wx)
405 if (*wp++ != *sp++)
406 break;
407 if (wx >= lastx)
408 return;
409
410 /* start update at an entire character */
411 for (sp = scp+wx, wp = wcp+wx; wp > wcp; --wp, --sp, --wx)
412 if (!ISCBIT(*wp) && !ISCBIT(*sp))
413 break;
414
415 /* skip the ending equal part */
416 wp = wcp + lastx - 1;
417 sp = scp + lastx - 1;
418 for (; lastx > wx; --lastx)
419 if (*wp-- != *sp--)
420 break;
421 ++wp;
422 ++wp;
423 ++sp;
424 ++sp;
425 for (; lastx < scrco; ++wp, ++sp, ++lastx)
426 if (!ISCBIT(*wp) && !ISCBIT(*sp))
427 break;
428 }
429
430 /* place to do clear-eol */
431 if (!clr_eol || endns >= lastx)
432 blnkx = scrco;
433 else
434 if (_virtscr->_lastch[wy] == _BLANK)
435 blnkx = -1;
436 else {
437 for (blnkx = lastx - 1, wp = wcp + blnkx;
438 blnkx >= wx; --blnkx, --wp)
439 if (_DARKCHAR(*wp))
440 break;
441 for (sp = scp + blnkx + 1; blnkx < scrco - 1;
442 ++sp, ++blnkx)
443 if (!ISCBIT(*sp))
444 break;
445 if (blnkx + _COST(Clr_eol) >= lastx)
446 blnkx = scrco;
447 }
448
449 /* on cookie terminals, we may need to do more work */
450 if (marks) {
451 /* video_attrx = color_attrx = scrco; */
452 video_attrx = color_attrx = (lastx >= scrco) ? lastx - 1 :
453 lastx;
454
455 /* find the last video attribute on the line */
456
457 wp = wcp + video_attrx;
458 for (; video_attrx >= wx; --video_attrx, --wp)
459 if (_VIDEO(*wp) != A_NORMAL)
460 break;
461
462 /* find the last color attribute on the line */
463
464 if (color_marks) {
465 wp = wcp + color_attrx;
466 for (; color_attrx >= wx; --color_attrx, --wp)
467 if (_COLOR(*wp) != A_NORMAL)
468 break;
469 if (color_attrx < lastx)
470 color_attrx++;
471 }
472 if (video_attrx < lastx)
473 video_attrx++;
474
475 if (video_attrx >= scrco)
476 --video_attrx;
477 if (color_marks && color_attrx >= scrco)
478 --color_attrx;
479 if (magic_cookie_glitch > 0 && wy == scrli - 1 &&
480 video_attrx == scrco - 1)
481 --video_attrx;
482 if (color_marks && magic_cookie_glitch > 0 &&
483 wy == scrli - 1 && color_attrx == scrco - 1)
484 --color_attrx;
485 for (wp = wcp+video_attrx; wp >= wcp+wx; --wp)
486 if (!ISCBIT(*wp))
487 break;
488 }
489
490 /* place for insert/delete chars */
491 #define SLACK 4
492 if (redraw || (!SP->dchok && !SP->ichok) || !(_virtscr->_use_idc) ||
493 endns < wx || (endns >= lastx && (scrco - lastx) > SLACK)) {
494 idcx = scrco;
495 } else
496 if (!marks)
497 idcx = -1;
498 else {
499 /* on cookie term, only do idch where no attrs */
500 /* are used */
501 for (idcx = scrco - 1, wp = wcp + idcx; idcx >= wx;
502 --idcx, --wp)
503 if (_ATTR(*wp) || _ISMARK1(wy, idcx) ||
504 _ISMARK2(wy, idcx))
505 break;
506 if (idcx >= scrco - SLACK)
507 idcx = scrco;
508 }
509
510 if (idcx < lastx && endns >= lastx)
511 lastx = scrco;
512
513 /* max amount of insert allow */
514 if (idcx == scrco || !SP->ichok)
515 maxi = 0;
516 else
517 if (lastx == scrco)
518 maxi = scrco;
519 else
520 maxi = lastx - (endns + 1);
521
522 /* go */
523 wcp += wx;
524 scp += wx;
525 didvideo = changed = FALSE;
526 didcolor = (color_marks) ? FALSE : TRUE;
527
528 while (wx < lastx) {
529 /* skip things that are already right */
530 if (!redraw) {
531 multi_col = 0;
532 wx_sav = wx;
533 for (; wx < lastx; ++wx, ++wcp, ++scp)
534 if (*wcp != *scp)
535 break;
536 if (wx >= lastx)
537 goto done;
538 for (; wx > wx_sav; --wx, --wcp, --scp) {
539 if (!ISCBIT(*wcp) && !ISCBIT(*scp))
540 break;
541 multi_col = 1;
542 }
543 }
544
545 /* try clear-bol, we'll assume exclusive clr_bol */
546 if (!changed && !marks && clr_bol && blnkx > wx &&
547 begns >= wx) {
548 for (x = wx, wp = wcp; x < lastx; ++x, ++wp)
549 if (_DARKCHAR(*wp))
550 break;
551 /* clearing only whole screen characters */
552 for (sp = scp+(x-wx); x >= wx; --x, --sp)
553 if (!ISCBIT(*sp))
554 break;
555 x -= 1;
556
557 if ((x - (redraw ? 0 : begns)) > _COST(Clr_bol)) {
558 (void) mvcur(cy, cx, wy, x);
559 /* MORE?: colors - mvcur will shuts of */
560 /* colors when msgr is not defined */
561
562 /* SS: colors */
563 if (back_color_erase)
564 _turn_off_background();
565
566 _PUTS(clr_bol, 1);
567 /* LINTED */
568 cy = (short) wy;
569 /* LINTED */
570 cx = (short) x;
571
572 mtch = x - wx;
573 (void) memcpy((char *) scp, (char *) wcp,
574 (mtch * sizeof (chtype)));
575 wcp += mtch;
576 scp += mtch;
577 wx = x;
578 }
579 }
580
581 /* screen image is changing */
582 changed = TRUE;
583
584 /* move to the point to start refresh */
585 if (cy != wy || cx != wx)
586 (void) mvcur(cy, cx, wy, wx);
587 /* LINTED */
588 cy = (short) wy;
589 /* LINTED */
590 cx = (short) wx;
591
592 /* update screen image */
593 while (wx < lastx) {
594 wc = *wcp;
595 sc = *scp;
596
597 if (!redraw && !multi_col && wc == sc)
598 break;
599
600 /* real video attributes */
601 if (marks)
602 curscr->_attrs = _ATTR(sc);
603
604 /* blanks only */
605 if (wx > blnkx) {
606 /* SS: colors */
607 if (back_color_erase)
608 _turn_off_background();
609
610 _PUTS(clr_eol, 1);
611 /* LINTED */
612 curscr->_curx = (short) wx;
613 /* LINTED */
614 curscr->_cury = (short) wy;
615 (void) wclrtoeol(curscr);
616
617 if (marks && wx > 0 && _ATTR(*(scp - 1)) !=
618 A_NORMAL) {
619 _VIDS(A_NORMAL, _ATTR(*(scp - 1)));
620 if (_VIDEO(*scp - 1))
621 _setmark1(wy, wx, NULL);
622 if (_COLOR(*scp - 1))
623 _setmark2(wy, wx, NULL);
624 }
625 goto done;
626 }
627
628 /* try insert/delete chars */
629 if (wx > idcx && !ISCBIT(*scp) &&
630 (mtch = _useidch(wcp, scp, lastx - wx,
631 maxi, &idch))) {
632 maxi -= idch;
633 wx += mtch;
634 scp += mtch;
635 wcp += mtch;
636 break;
637 }
638
639 /* about to output chars, make sure insert */
640 /* mode is off */
641 if (SP->phys_irm)
642 _OFFINSERT();
643
644 /* color and video attributes */
645 if (_ATTR(wc) != curscr->_attrs) {
646 bool color_change = FALSE;
647 bool video_change = FALSE;
648
649 if (marks)
650 if (_VIDEO(wc) != _VIDEO(curscr->_attrs))
651 video_change = TRUE;
652 if (color_marks)
653 if (_COLOR(wc) != _COLOR(curscr->_attrs))
654 color_change = TRUE;
655
656 /* the following may occurs when, for */
657 /* example the application */
658 /* is written for color terminal and then */
659 /* run on a monocrome */
660
661 if (marks && !video_change && !color_change)
662 goto no_change;
663
664 /* prevent spilling out of line */
665 if (marks && !(didcolor && didvideo)) {
666 if ((video_change && !_ISMARK1(wy,
667 video_attrx)) || (color_change &&
668 !_ISMARK2(wy, color_attrx))) {
669 int tempx;
670 chtype sa = curscr->_attrs;
671 bool first = FALSE;
672 bool second = FALSE;
673
674 if (!didvideo && video_change &&
675 !_ISMARK1(wy, video_attrx)) {
676 didvideo = TRUE;
677 (void) mvcur(wy, wx,
678 wy, video_attrx);
679 _VIDS(_VIDEO(_virtscr->_y[wy]
680 [video_attrx]),
681 _VIDEO(_virtscr->_y[wy]
682 [video_attrx-1]));
683 _setmark1(wy, video_attrx,
684 NULL);
685 first = TRUE;
686 }
687
688 if (!didcolor && color_change &&
689 !_ISMARK2(wy, color_attrx)) {
690 didcolor = TRUE;
691 tempx = first ? video_attrx : wx;
692 if (tempx != color_attrx)
693 (void) mvcur(wy, tempx, wy,
694 color_attrx);
695 /*
696 * sc = _COLOR(curscr->_y[wy][color_attrx]);
697 *_VIDS(sc, (~sc & A_COLOR));
698 */
699 _VIDS(_COLOR(_virtscr->_y[wy]
700 [color_attrx]),
701 _COLOR(_virtscr->_y[wy]
702 [color_attrx-1]));
703 _setmark2(wy, color_attrx, NULL);
704 second = TRUE;
705 }
706 (void) mvcur(wy, (second ? color_attrx :
707 video_attrx), wy, wx);
708 curscr->_attrs = sa;
709 }
710 }
711
712 _VIDS(_ATTR(wc), curscr->_attrs);
713
714 /* on cookie terminals mark the interval */
715 if (video_change)
716 _setmark1(wy, wx, scp);
717 if (color_change)
718 _setmark2(wy, wx, scp);
719 }
720
721 /* end-of-line */
722 no_change:
723 x = 1;
724 if (_scrmax > 1)
725 x = _curs_scrwidth[TYPE(RBYTE(wc))];
726 if (wx == scrco - x) {
727 _rmargin(wx);
728 goto done;
729 }
730
731 if (transparent_underline && erase_overstrike &&
732 _CHAR(wc) == '_') {
733 (void) _outch(' ');
734 (void) mvcur(wy, wx + 1, wy, wx);
735 }
736
737 /* put out the character */
738 (void) _outwch(tilde_glitch && _CHAR(wc) == '~' ? '`' : wc);
739
740 *scp++ = wc;
741 wcp++;
742 wx++;
743 cx++;
744 /* output entire multi-byte chars */
745 while (wx < lastx && ISCBIT(*wcp)) {
746 (void) _outwch(*wcp);
747 *scp++ = *wcp++;
748 wx++;
749 cx++;
750
751
752
753
754 }
755 }
756 }
757
758 done:
759 if (changed) {
760 /* update the blank structure */
761 for (wx = 0, scp = curscr->_y[wy]; wx < scrco; ++wx, ++scp)
762 if (_DARKCHAR(*scp))
763 break;
764 /* LINTED */
765 _BEGNS[wy] = (short) wx;
766 if (wx == scrco)
767 _ENDNS[wy] = -1;
768 else {
769 wx = scrco - 1;
770 scp = curscr->_y[wy] + wx;
771 for (; wx >= 0; --wx, --scp)
772 if (_DARKCHAR(*scp))
773 break;
774 /* LINTED */
775 _ENDNS[wy] = (short) wx;
776 }
777
778 /* update the hash structure */
779 _CURHASH[wy] = _BEGNS[wy] < scrco ? _NOHASH : 0;
780 }
781 }
782
783 /*
784 * See if a left or right shift is apppropriate
785 * This routine is called only if !cookie_glitch or no video attributes
786 * are used in the affected part.
787 * The main idea is to find a longest common substring which is a
788 * prefix of one of 'wcp' or 'scp', then either delete or
789 * insert depending on where the prefix is.
790 *
791 * wcp : what we want the screen to look like
792 * scp : what the screen looks like now
793 * length: the length to be updated
794 * maxi: maximum possible insert amount
795 * id; *id returns the amount of insert/delete
796 *
797 * Return the number of chars matched after the shift.
798 */
799
800 static int
_useidch(chtype * wcp,chtype * scp,int length,int maxi,int * id)801 _useidch(chtype *wcp, chtype *scp, int length, int maxi, int *id)
802 {
803 int x1, x2, blnk, idch, cost, cost_ich1, match;
804 chtype wc;
805
806 /* try deletion */
807 if (SP->dchok && _CHAR(*wcp) != ' ') {
808 if ((match = _prefix(wcp, scp, length, length / 2, &idch)) > 0)
809 cost = _COST(dcfixed) + (parm_dch ? _COST(Parm_dch) :
810 _COST(Delete_character) * idch);
811 else
812 cost = _INFINITY;
813
814 if (match >= cost) {
815 /* SS: colors */
816 if (back_color_erase)
817 _turn_off_background();
818
819 if (SP->dmode) {
820 if (SP->sid_equal) {
821 if (!(SP->phys_irm))
822 _ONINSERT();
823 } else {
824 if (SP->phys_irm)
825 _OFFINSERT();
826 _PUTS(enter_delete_mode, 1);
827 }
828 }
829
830 if (parm_dch)
831 _PUTS(tparm_p1(parm_dch, idch), 1);
832 else
833 for (x1 = 0; x1 < idch; ++x1)
834 _PUTS(delete_character, 1);
835
836 if (SP->dmode) {
837 if (SP->eid_equal)
838 SP->phys_irm = FALSE;
839 _PUTS(exit_delete_mode, 1);
840 }
841
842 /* update screen image */
843 for (x1 = 0, x2 = idch; x2 < length; ++x1, ++x2)
844 scp[x1] = scp[x2];
845 for (; x1 < length; ++x1)
846 scp[x1] = ' ';
847
848 *id = -idch;
849 return (match);
850 }
851 }
852
853 /* no insertion wanted or possible */
854 if (!(SP->ichok) || _CHAR(*scp) == ' ')
855 return (0);
856
857 /* see if insertion is worth it */
858 maxi = (idch = length / 2) < maxi ? idch : maxi;
859 if ((match = _prefix(scp, wcp, length, maxi, &idch)) <= 0)
860 return (0);
861
862 /* see if inserting blanks only */
863 for (blnk = 0; blnk < idch; ++blnk)
864 if (wcp[blnk] != ' ') {
865 blnk = 0;
866 break;
867 }
868
869 /* see if doing insertion is worth it */
870 cost_ich1 = idch * _COST(Insert_character);
871 if (SP->imode) {
872 cost = SP->phys_irm ? 0 : _COST(icfixed);
873 if (blnk > _COST(Parm_ich) && _COST(Parm_ich) < cost_ich1)
874 cost += _COST(Parm_ich);
875 else
876 if (insert_character)
877 cost += cost_ich1;
878 } else {
879 if (parm_ich && _COST(Parm_ich) < cost_ich1)
880 cost = _COST(Parm_ich);
881 else
882 cost = cost_ich1;
883 }
884 if ((cost - blnk) > match)
885 return (0);
886
887 /* perform the insertions */
888
889 /* SS: colors */
890 if (back_color_erase)
891 _turn_off_background();
892
893 if (SP->imode) {
894 if (!SP->phys_irm)
895 _ONINSERT();
896 if (blnk > _COST(Parm_ich) && _COST(Parm_ich) < cost_ich1)
897 _PUTS(tparm_p1(parm_ich, idch), 1);
898 else
899 if (insert_character)
900 goto do_insert_char;
901 else
902 /* so that we'll do real char insertions */
903 blnk = 0;
904 } else {
905 if (parm_ich && _COST(Parm_ich) < cost_ich1)
906 _PUTS(tparm_p1(parm_ich, idch), 1);
907 else {
908 do_insert_char:
909 for (x1 = 0; x1 < idch; ++x1)
910 _PUTS(insert_character, 1);
911 }
912 }
913
914 /* inserting desired characters */
915 if (!blnk)
916 for (x1 = 0; x1 < idch; ++x1) {
917 wc = wcp[x1];
918 if (_ATTR(wc) != curscr->_attrs)
919 _VIDS(_ATTR(wc), curscr->_attrs);
920 (void) _outwch(_CHAR(wc) == '~' &&
921 tilde_glitch ? '`' : wc);
922 ++cx;
923 }
924
925 /* update the screen image */
926 for (x1 = length - 1, x2 = length - idch - 1; x2 >= 0; --x1, --x2)
927 scp[x1] = scp[x2];
928 (void) memcpy((char *) scp, (char *) wcp, idch * sizeof (chtype));
929
930 *id = idch;
931 return (match + idch);
932 }
933
934 /*
935 * Find a substring of s2 that match a prefix of s1.
936 * The substring is such that:
937 * 1. it does not start with an element
938 * that is in perfect alignment with one in s1 and
939 * 2: it is at least as long as the displacement.
940 *
941 * length: the length of s1, s2.
942 * maxs: only search for match in [1,maxs] of s2.
943 * begm: *begm returns where the match begins.
944 *
945 * Return the number of matches.
946 */
947
948 static int
_prefix(chtype * s1,chtype * s2,int length,int maxs,int * begm)949 _prefix(chtype *s1, chtype *s2, int length, int maxs, int *begm)
950 {
951 int m, n, k;
952
953 n = 0;
954 for (m = 1; m <= maxs; ++m)
955 /* testing for s1[m] != s2[m] is condition 1 */
956 if (s1[0] == s2[m] && s1[m] != s2[m]) {
957 /* see if it's long enough (condition 2) */
958 for (k = 2 * m - 1; k > m; --k)
959 if (s1[k - m] != s2[k])
960 break;
961 /* found a match with a good length */
962 if (k == m) {
963 *begm = m;
964
965 /* count the # of matches */
966 s2 += m;
967 length -= m;
968 for (n = m; n < length; ++n)
969 if (s1[n] != s2[n])
970 break;
971 goto done;
972 }
973 }
974
975 done:
976 return (n);
977 }
978
979 /* Set video markers for cookie terminal. */
980
981 static void
_setmark1(int y,int x,chtype * s)982 _setmark1(int y, int x, chtype *s)
983 {
984 long a;
985
986 /* set the mark map */
987 marks[y][x / BITSPERBYTE] |= (1 << (x % BITSPERBYTE));
988
989 if (s) {
990 a = _VIDEO(curscr->_attrs);
991
992 /* set the video attr of the first char here */
993 /* LINTED */
994 *s = _CHAR(*s) | _COLOR(*s) | a;
995
996 /* now the video attr of the rest of the affected interval */
997 for (x += 1, s += 1; x < scrco; ++x, ++s)
998 if (_ISMARK1(y, x))
999 break;
1000 else
1001 /* LINTED */
1002 *s = _CHAR(*s) | _COLOR(*s) | a;
1003 }
1004 }
1005
1006 /* Set color markers for cookie terminal. */
1007
1008 static void
_setmark2(int y,int x,chtype * s)1009 _setmark2(int y, int x, chtype *s)
1010 {
1011 long a;
1012
1013 /* set the mark map */
1014 color_marks[y][x / BITSPERBYTE] |= (1 << (x % BITSPERBYTE));
1015
1016 if (s) {
1017 a = _COLOR(curscr->_attrs);
1018
1019 /* set the video attr of the first char here */
1020 /* LINTED */
1021 *s = _CHAR(*s) | _VIDEO(*s) | a;
1022
1023 /* now the video attr of the rest of the affected interval */
1024 for (x += 1, s += 1; x < scrco; ++x, ++s)
1025 if (_ISMARK2(y, x))
1026 break;
1027 else
1028 /* LINTED */
1029 *s = _CHAR(*s) | _VIDEO(*s) | a;
1030 }
1031 }
1032
1033
1034 /* At the right margin various weird things can happen. We treat them here. */
1035
1036 /* At the right margin various weird things can happen. We treat them here. */
1037
1038 static void
_rmargin(int wx)1039 _rmargin(int wx)
1040 {
1041 int x, w, ix;
1042 chtype sc;
1043 chtype *wcp = _virtscr->_y[cy];
1044
1045 /* screen may scroll */
1046 if (cy == scrli - 1) {
1047 /* can't do anything */
1048 if (!SP->ichok)
1049 return;
1050
1051 /* the width of the new character */
1052 w = _curs_scrwidth[TYPE(RBYTE(wcp[wx]))];
1053 /* the place to put it without causing scrolling */
1054 for (x = wx - 1; x > 0; --x)
1055 if (!ISCBIT(wcp[x]))
1056 break;
1057 sc = curscr->_y[cy][x];
1058
1059 (void) mvcur(cy, cx, cy, x);
1060 if (_ATTR(wcp[wx]) != curscr->_attrs)
1061 _VIDS(_ATTR(wcp[wx]), curscr->_attrs);
1062 (void) _outwch(tilde_glitch &&
1063 _CHAR(wcp[wx]) == '~' ? '`' : wcp[wx]);
1064
1065 for (ix = wx + 1; ix < scrco; ++ix) {
1066 (void) _outwch(wcp[ix]);
1067 }
1068
1069 /* insert sc back in and push wcp[wx] right */
1070 (void) mvcur(cy, x+w, cy, x);
1071
1072 /* SS: colors */
1073 if (back_color_erase)
1074 _turn_off_background();
1075
1076 if (SP->imode && !SP->phys_irm)
1077 _ONINSERT();
1078 /* width of the old character that was overwritten */
1079 w = _curs_scrwidth[TYPE(RBYTE(curscr->_y[cy][x]))];
1080
1081 if (insert_character)
1082 for (ix = 0; ix < w; ++ix)
1083 _PUTS(insert_character, 1);
1084 else
1085 if (parm_ich && !SP->imode)
1086 _PUTS(tparm_p1(parm_ich, w), 1);
1087
1088 if (_ATTR(sc) != curscr->_attrs)
1089 _VIDS(_ATTR(sc), curscr->_attrs);
1090 for (ix = x; w > 0; --w, ++ix)
1091 (void) _outwch(curscr->_y[cy][ix]);
1092
1093 /* make sure the video attrs are ok */
1094 if (marks && (_ATTR(sc) || _ATTR(wcp[wx])))
1095 _VIDS(_ATTR(wcp[wx]), ~_ATTR(sc));
1096
1097 /* update screen image */
1098 /* LINTED */
1099 cx = (short) wx;
1100 curscr->_y[cy][wx] = wcp[wx];
1101 for (x = wx + 1; x < scrco; ++x) {
1102 (void) _outwch(wcp[x]);
1103 curscr->_y[cy][x] = wcp[x];
1104 }
1105 return;
1106 }
1107
1108 /* put char out and update screen image */
1109 (void) _outwch(tilde_glitch && _CHAR(wcp[wx]) == '~' ? '`' : wcp[wx]);
1110
1111
1112
1113
1114
1115
1116
1117
1118 curscr->_y[cy][wx] = wcp[wx];
1119
1120 for (x = wx + 1; x < scrco; ++x) {
1121 (void) _outwch(wcp[x]);
1122 curscr->_y[cy][x] = wcp[x];
1123 }
1124
1125 /* make sure that wrap-around happens */
1126 if (!auto_right_margin || eat_newline_glitch) {
1127 (void) _outch('\r');
1128 (void) _outch('\n');
1129 }
1130 cx = 0;
1131 ++cy;
1132 }
1133
1134 /*
1135 * Find the top-most line to do clear-to-eod.
1136 *
1137 * topy, boty: the region to consider
1138 */
1139
1140 static int
_getceod(int topy,int boty)1141 _getceod(int topy, int boty)
1142 {
1143 chtype *wcp, *ecp;
1144 int wy;
1145 short *begch, *endch, *begns;
1146
1147 /* do nothing */
1148 if ((topy + 1) >= boty)
1149 return (boty);
1150
1151 wy = boty - 1;
1152 begch = _virtscr->_firstch + wy;
1153 endch = _virtscr->_lastch + wy;
1154 begns = _BEGNS + wy;
1155
1156 for (; wy >= topy; --wy, --begch, --endch, --begns) {
1157 if (*endch == _BLANK || (*begch >= scrco && *begns >= scrco))
1158 continue;
1159
1160 wcp = _virtscr->_y[wy];
1161 ecp = wcp + scrco;
1162 for (; wcp < ecp; ++wcp)
1163 if (_DARKCHAR(*wcp))
1164 break;
1165 if (wcp != ecp)
1166 break;
1167
1168 *endch = _BLANK;
1169 }
1170
1171 return (wy + 1);
1172 }
1173
1174 /* Use hardware clear-to-bottom. */
1175
1176 static void
_useceod(int topy,int boty)1177 _useceod(int topy, int boty)
1178 {
1179 short *begns, *begch;
1180
1181 /* skip lines already blanked */
1182 begch = _virtscr->_firstch + topy;
1183 begns = _BEGNS + topy;
1184 for (; topy < boty; ++topy, ++begns, ++begch)
1185 if (*begns < scrco || *begch == _REDRAW)
1186 break;
1187 else
1188 *begch = _INFINITY;
1189
1190 /* nothing to do */
1191 if (topy + 1 >= boty)
1192 return;
1193
1194 /* see if bottom is clear */
1195 for (begns = _BEGNS + boty; boty < scrli; ++boty, ++begns)
1196 if (*begns < scrco)
1197 return;
1198
1199 /* use clear-screen if appropriate */
1200 if (topy == 0) {
1201 /* SS: colors */
1202 if (back_color_erase)
1203 _turn_off_background();
1204
1205 _PUTS(clear_screen, scrli);
1206 cy = 0; cx = 0;
1207 (void) werase(curscr);
1208 } else
1209
1210 /* use clear-to-end-of-display or delete lines */
1211 if (clr_eos || (parm_delete_line && !memory_below)) {
1212 (void) mvcur(cy, cx, topy, 0);
1213 /* LINTED */
1214 cy = (short) topy;
1215 cx = 0;
1216 /* SS: colors */
1217 if (back_color_erase)
1218 _turn_off_background();
1219 _PUTS(clr_eos ? clr_eos : tparm_p1(parm_delete_line,
1220 scrli - topy), scrli - topy);
1221
1222 /* update curscr */
1223 /* LINTED */
1224 curscr->_cury = (short) topy;
1225 curscr->_curx = 0;
1226 (void) wclrtobot(curscr);
1227 } else
1228 /* no hardware support */
1229 return;
1230
1231 /* correct the update structure */
1232 (void) wtouchln(_virtscr, topy, scrli, FALSE);
1233 }
1234
1235
1236 static void
_turn_off_background(void)1237 _turn_off_background(void)
1238 {
1239 /* this routine turn the background color to zero. This need to be */
1240 /* done only in forllowing cases: */
1241 /* 1) We are using Tek type terminal (which has bce terminfo */
1242 /* variable) */
1243 /* 2) The current background is not already zero */
1244
1245 if (set_background && cur_term->_cur_pair.background > 0) {
1246 _PUTS(orig_pair, 1);
1247 cur_term->_cur_pair.foreground = -1;
1248 cur_term->_cur_pair.background = -1;
1249 curscr->_attrs &= ~A_COLOR;
1250 }
1251 }
1252