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