Permalink
Cannot retrieve contributors at this time
/* | |
* CDDL HEADER START | |
* | |
* The contents of this file are subject to the terms of the | |
* Common Development and Distribution License, Version 1.0 only | |
* (the "License"). You may not use this file except in compliance | |
* with the License. | |
* | |
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE | |
* or http://www.opensolaris.org/os/licensing. | |
* See the License for the specific language governing permissions | |
* and limitations under the License. | |
* | |
* When distributing Covered Code, include this CDDL HEADER in each | |
* file and include the License file at usr/src/OPENSOLARIS.LICENSE. | |
* If applicable, add the following below this CDDL HEADER, with the | |
* fields enclosed by brackets "[]" replaced with your own identifying | |
* information: Portions Copyright [yyyy] [name of copyright owner] | |
* | |
* CDDL HEADER END | |
*/ | |
/* | |
* Copyright 2004 Sun Microsystems, Inc. All rights reserved. | |
* Use is subject to license terms. | |
*/ | |
/* Copyright (c) 1988 AT&T */ | |
/* All Rights Reserved */ | |
/* | |
* University Copyright- Copyright (c) 1982, 1986, 1988 | |
* The Regents of the University of California | |
* All Rights Reserved | |
* | |
* University Acknowledgment- Portions of this document are derived from | |
* software developed by the University of California, Berkeley, and its | |
* contributors. | |
*/ | |
/*LINTLIBRARY*/ | |
#include <sys/types.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include "curses_inc.h" | |
/* | |
* Make the screen look like "win" over the area covered by win. | |
* This routine may use insert/delete char/line and scrolling-region. | |
* win : the window being updated | |
*/ | |
extern int outchcount; | |
static void _updateln(int), _turn_off_background(void), | |
_setmark1(int, int, chtype *), | |
_setmark2(int, int, chtype *), _rmargin(int), | |
_useceod(int, int); | |
static int _useidch(chtype *, chtype *, int, int, int *), | |
_prefix(chtype *, chtype *, int, int, int *), | |
_getceod(int, int); | |
static short cy, cx, /* current cursor coord */ | |
scrli, /* actual screen lines */ | |
scrco; /* actual screen columns */ | |
static char **marks; /* the mark table for cookie terminals */ | |
static char **color_marks; /* color mark table for cookie terminals */ | |
#define _ISMARK1(y, x) (marks[y][x / BITSPERBYTE] & (1 << (x % BITSPERBYTE))) | |
#define _ISMARK2(y, x) (color_marks ? (color_marks[y][x / BITSPERBYTE] & \ | |
(1 << (x % BITSPERBYTE))) : FALSE) | |
#define _VIDEO(c) ((c) & A_ATTRIBUTES & ~A_COLOR) | |
#define _COLOR(c) ((c) & A_COLOR) | |
#ifdef _VR2_COMPAT_CODE | |
extern char _endwin; | |
#endif /* _VR2_COMPAT_CODE */ | |
int | |
wrefresh(WINDOW *win) | |
{ | |
short *bnsch, *ensch; | |
SLK_MAP *slk; | |
int wx, wy, nc, boty, clby, idby, *hs, curwin; | |
curwin = (win == curscr); | |
/* don't allow curscr refresh if the screen was just created */ | |
if (curwin && curscr->_sync) | |
return (OK); | |
/* go thru _stdbody */ | |
if (!curwin && (win != _virtscr)) | |
(void) wnoutrefresh(win); | |
/* if there is typeahead */ | |
if ((_INPUTPENDING = _chkinput()) == TRUE) { | |
if (curwin) | |
curscr->_clear = TRUE; | |
return (OK); | |
} | |
if (curwin || curscr->_clear) | |
_virtscr->_clear = TRUE; | |
/* save curscr cursor coordinates */ | |
cy = curscr->_cury; | |
cx = curscr->_curx; | |
/* to simplify code in some cases */ | |
marks = _MARKS; | |
color_marks = _COLOR_MARKS; | |
scrli = curscr->_maxy; | |
scrco = curscr->_maxx; | |
slk = SP->slk; | |
outchcount = 0; | |
/* make sure we're in program mode */ | |
if (SP->fl_endwin) { | |
/* If endwin is equal to 2 it means we just did a newscreen. */ | |
if (SP->fl_endwin == TRUE) { | |
(void) reset_prog_mode(); | |
if (SP->kp_state) | |
(void) tputs(keypad_xmit, 1, _outch); | |
if (slk) | |
(*_do_slk_tch)(); | |
if (SP->fl_meta) | |
(void) tputs(meta_on, 1, _outch); | |
if (cur_term->_cursorstate != 1) | |
_PUTS(cur_term->cursor_seq[cur_term-> | |
_cursorstate], 0); | |
} | |
_PUTS(enter_ca_mode, 1); | |
(void) tputs(ena_acs, 1, _outch); | |
if (exit_attribute_mode) | |
_PUTS(tparm_p0(exit_attribute_mode), 1); | |
else | |
/* | |
* If there is no exit_attribute mode, then vidupdate | |
* could only possibly turn off one of the below three | |
* so that's all we ask it turn off. | |
*/ | |
vidupdate(A_NORMAL, (A_ALTCHARSET | A_STANDOUT | | |
A_UNDERLINE), _outch); | |
SP->fl_endwin = FALSE; | |
#ifdef _VR2_COMPAT_CODE | |
_endwin = (char)FALSE; | |
#endif /* _VR2_COMPAT_CODE */ | |
} | |
/* clear the screen if required */ | |
if (_virtscr->_clear) { | |
/* SS: colors */ | |
if (back_color_erase) | |
_turn_off_background(); | |
_PUTS(clear_screen, scrli); | |
cy = cx = curscr->_curx = curscr->_cury = 0; | |
/* _sync indicates that this a new screen */ | |
if (!curscr->_sync) | |
(void) werase(curscr); | |
else { | |
nc = scrco / BITSPERBYTE - (scrco % | |
BITSPERBYTE ? 0 : 1); | |
wy = scrli - 1; | |
bnsch = _BEGNS; ensch = _ENDNS; | |
hs = _CURHASH; | |
for (; wy >= 0; --wy) { | |
*bnsch++ = scrco; | |
*ensch++ = -1; | |
*hs++ = 0; | |
if (marks) | |
for (wx = nc; wx >= 0; --wx) | |
marks[wy][wx] = 0; | |
} | |
} | |
_virtscr->_clear = curscr->_sync = curscr->_clear = FALSE; | |
if (slk) | |
(*_do_slk_tch)(); | |
/* pretend _virtscr has been totally changed */ | |
(void) wtouchln(_virtscr, 0, scrli, -1); | |
_VIRTTOP = 0; | |
_VIRTBOT = scrli - 1; | |
/* will not do clear-eod or ins/del lines */ | |
clby = idby = scrli; | |
} else | |
clby = idby = -1; | |
/* Software soft labels; if _changed == 2, slk's are in clear mode. */ | |
if (slk && slk->_win && (slk->_changed == TRUE)) | |
(*_do_slk_noref)(); | |
/* do line updating */ | |
_virtscr->_clear = FALSE; | |
wy = _VIRTTOP; | |
boty = _VIRTBOT + 1; | |
bnsch = _virtscr->_firstch + wy; | |
ensch = _virtscr->_lastch + wy; | |
for (; wy < boty; ++wy, ++bnsch, ++ensch) { | |
/* this line is up-to-date */ | |
if (*bnsch >= scrco) | |
goto next; | |
/* there is type-ahead */ | |
if (!curwin && (_INPUTPENDING = _chkinput()) == TRUE) { | |
/* LINTED */ | |
_VIRTTOP = (short)wy; | |
goto done; | |
} | |
if (clby < 0) { | |
/* now we have to work, check for ceod */ | |
clby = _getceod(wy, boty); | |
/* check for insert/delete lines */ | |
if (_virtscr->_use_idl) | |
idby = (*_setidln)(); | |
} | |
/* try clear-to-eod */ | |
if (wy == clby) | |
_useceod(wy, boty); | |
/* try ins/del lines */ | |
if (wy == idby) { | |
curscr->_cury = cy; | |
curscr->_curx = cx; | |
(*_useidln)(); | |
cy = curscr->_cury; | |
cx = curscr->_curx; | |
} | |
if (*bnsch < scrco) | |
_updateln(wy); | |
next: | |
*bnsch = _INFINITY; | |
*ensch = -1; | |
} | |
/* do hardware soft labels; if _changed == 2, */ | |
/* slk's are in clear mode. */ | |
if (slk && (slk->_changed == TRUE) && !(slk->_win)) | |
(*_do_slk_ref)(); | |
/* move cursor */ | |
wy = _virtscr->_cury; | |
wx = _virtscr->_curx; | |
if (wy != cy || wx != cx) { | |
(void) mvcur(cy, cx, wy, wx); | |
/* LINTED */ | |
cy = (short)wy; | |
/* LINTED */ | |
cx = (short)wx; | |
} | |
/* reset the flags */ | |
curscr->_clear = FALSE; | |
_virtscr->_use_idl = FALSE; | |
_virtscr->_use_idc = TRUE; | |
_INPUTPENDING = FALSE; | |
/* virtual image is now up-to-date */ | |
_VIRTTOP = scrli; | |
_VIRTBOT = -1; | |
done : | |
curscr->_cury = cy; | |
curscr->_curx = cx; | |
(void) fflush(SP->term_file); | |
return (outchcount); | |
} | |
/* Shift appropriate portions of a line to leave space for cookies. */ | |
static chtype * | |
_shove(int wy) | |
{ | |
chtype *wcp, *cp, prev; | |
short curx; | |
int x, cury, didshift; | |
static chtype *line; | |
static int length; | |
/* allocate space for shifted line */ | |
if (length < scrco) { | |
free(line); | |
line = (chtype *) malloc(scrco * sizeof (chtype)); | |
length = line ? scrco : 0; | |
} | |
/* no space to do it */ | |
if (!line) | |
return (_virtscr->_y[wy]); | |
prev = A_NORMAL; | |
cp = line; | |
wcp = _virtscr->_y[wy]; | |
curx = _virtscr->_curx; | |
cury = _virtscr->_cury; | |
didshift = FALSE; | |
for (x = 0; x < scrco; ++x, ++wcp, ++cp) { | |
if (_ATTR(*wcp) != prev) { | |
/* use existing blank */ | |
if (_CHAR(*wcp) == ' ') | |
*cp = ' ' | _ATTR(*(wcp + 1)); | |
/* use previous blank */ | |
else | |
if ((x > 0) && _CHAR(*(cp - 1)) == ' ') { | |
*(cp - 1) = ' ' | _ATTR(*wcp); | |
*cp = *wcp; | |
} else { | |
if ((curx >= x) && (cury == wy)) | |
++curx; | |
*cp = ' ' | _ATTR(*wcp); | |
--wcp; | |
didshift = TRUE; | |
} | |
prev = _ATTR(*cp); | |
} else | |
*cp = *wcp; | |
} | |
/* make sure that the end of the line is normal */ | |
cp = line + scrco - 1; | |
if (didshift || (_ATTR(*cp) != A_NORMAL) || | |
((wy == scrli - 1) && (_ATTR(*(cp - 1)) != A_NORMAL))) { | |
*cp = didshift ? ' ' : _CHAR(*cp); | |
if (wy == scrli - 1) | |
*(cp - 1) = didshift ? ' ' : _CHAR(*(cp - 1)); | |
} | |
if (wy == cury) | |
_virtscr->_curx = curx >= scrco ? scrco - 1 : curx; | |
return (line); | |
} | |
/* | |
* Update a line. | |
* Three schemes of coloring are allowed. The first is the usual | |
* pen-up/pen-down model. The second is the HP26*-like model. | |
* In this case, colorings are specified by intervals, the left | |
* side of the interval has the coloring mark, the right side | |
* has the end-coloring mark. We assume that clear sequences will | |
* clear ALL marks in the affected regions. The second case is | |
* signified by the boolean flag ceol_standout_glitch. | |
* The third case is for terminals that leave visible cookies on | |
* the screen. This last case is at most an approximation of what | |
* can be done right. | |
*/ | |
static void | |
_updateln(int wy) | |
{ | |
chtype *wcp, *scp, *wp, *sp, wc, sc; | |
int wx, lastx, x, mtch, idch, blnkx, idcx, video_attrx, | |
color_attrx, maxi, endns, begns, wx_sav, multi_col; | |
bool redraw, changed, didcolor, didvideo; | |
redraw = (_virtscr->_firstch[wy] == _REDRAW); | |
endns = _ENDNS[wy]; | |
begns = _BEGNS[wy]; | |
/* easy case */ | |
if (!redraw && (_virtscr->_lastch[wy] == _BLANK) && (begns >= scrco)) | |
return; | |
/* line images */ | |
wcp = magic_cookie_glitch <= 0 ? _virtscr->_y[wy] : _shove(wy); | |
scp = curscr->_y[wy]; | |
/* the interval to be updated */ | |
if (redraw || magic_cookie_glitch >= 0) { | |
wx = 0; | |
lastx = scrco; | |
} else { | |
wx = _virtscr->_firstch[wy]; | |
lastx = _virtscr->_lastch[wy] == _BLANK ? scrco : | |
_virtscr->_lastch[wy] + 1; | |
} | |
/* skip equal parts */ | |
if (!redraw) { | |
/* skip the starting equal part */ | |
wp = wcp + wx; | |
sp = scp + wx; | |
for (; wx < lastx; ++wx) | |
if (*wp++ != *sp++) | |
break; | |
if (wx >= lastx) | |
return; | |
/* start update at an entire character */ | |
for (sp = scp+wx, wp = wcp+wx; wp > wcp; --wp, --sp, --wx) | |
if (!ISCBIT(*wp) && !ISCBIT(*sp)) | |
break; | |
/* skip the ending equal part */ | |
wp = wcp + lastx - 1; | |
sp = scp + lastx - 1; | |
for (; lastx > wx; --lastx) | |
if (*wp-- != *sp--) | |
break; | |
++wp; | |
++wp; | |
++sp; | |
++sp; | |
for (; lastx < scrco; ++wp, ++sp, ++lastx) | |
if (!ISCBIT(*wp) && !ISCBIT(*sp)) | |
break; | |
} | |
/* place to do clear-eol */ | |
if (!clr_eol || endns >= lastx) | |
blnkx = scrco; | |
else | |
if (_virtscr->_lastch[wy] == _BLANK) | |
blnkx = -1; | |
else { | |
for (blnkx = lastx - 1, wp = wcp + blnkx; | |
blnkx >= wx; --blnkx, --wp) | |
if (_DARKCHAR(*wp)) | |
break; | |
for (sp = scp + blnkx + 1; blnkx < scrco - 1; | |
++sp, ++blnkx) | |
if (!ISCBIT(*sp)) | |
break; | |
if (blnkx + _COST(Clr_eol) >= lastx) | |
blnkx = scrco; | |
} | |
/* on cookie terminals, we may need to do more work */ | |
if (marks) { | |
/* video_attrx = color_attrx = scrco; */ | |
video_attrx = color_attrx = (lastx >= scrco) ? lastx - 1 : | |
lastx; | |
/* find the last video attribute on the line */ | |
wp = wcp + video_attrx; | |
for (; video_attrx >= wx; --video_attrx, --wp) | |
if (_VIDEO(*wp) != A_NORMAL) | |
break; | |
/* find the last color attribute on the line */ | |
if (color_marks) { | |
wp = wcp + color_attrx; | |
for (; color_attrx >= wx; --color_attrx, --wp) | |
if (_COLOR(*wp) != A_NORMAL) | |
break; | |
if (color_attrx < lastx) | |
color_attrx++; | |
} | |
if (video_attrx < lastx) | |
video_attrx++; | |
if (video_attrx >= scrco) | |
--video_attrx; | |
if (color_marks && color_attrx >= scrco) | |
--color_attrx; | |
if (magic_cookie_glitch > 0 && wy == scrli - 1 && | |
video_attrx == scrco - 1) | |
--video_attrx; | |
if (color_marks && magic_cookie_glitch > 0 && | |
wy == scrli - 1 && color_attrx == scrco - 1) | |
--color_attrx; | |
for (wp = wcp+video_attrx; wp >= wcp+wx; --wp) | |
if (!ISCBIT(*wp)) | |
break; | |
} | |
/* place for insert/delete chars */ | |
#define SLACK 4 | |
if (redraw || (!SP->dchok && !SP->ichok) || !(_virtscr->_use_idc) || | |
endns < wx || (endns >= lastx && (scrco - lastx) > SLACK)) { | |
idcx = scrco; | |
} else | |
if (!marks) | |
idcx = -1; | |
else { | |
/* on cookie term, only do idch where no attrs */ | |
/* are used */ | |
for (idcx = scrco - 1, wp = wcp + idcx; idcx >= wx; | |
--idcx, --wp) | |
if (_ATTR(*wp) || _ISMARK1(wy, idcx) || | |
_ISMARK2(wy, idcx)) | |
break; | |
if (idcx >= scrco - SLACK) | |
idcx = scrco; | |
} | |
if (idcx < lastx && endns >= lastx) | |
lastx = scrco; | |
/* max amount of insert allow */ | |
if (idcx == scrco || !SP->ichok) | |
maxi = 0; | |
else | |
if (lastx == scrco) | |
maxi = scrco; | |
else | |
maxi = lastx - (endns + 1); | |
/* go */ | |
wcp += wx; | |
scp += wx; | |
didvideo = changed = FALSE; | |
didcolor = (color_marks) ? FALSE : TRUE; | |
while (wx < lastx) { | |
/* skip things that are already right */ | |
if (!redraw) { | |
multi_col = 0; | |
wx_sav = wx; | |
for (; wx < lastx; ++wx, ++wcp, ++scp) | |
if (*wcp != *scp) | |
break; | |
if (wx >= lastx) | |
goto done; | |
for (; wx > wx_sav; --wx, --wcp, --scp) { | |
if (!ISCBIT(*wcp) && !ISCBIT(*scp)) | |
break; | |
multi_col = 1; | |
} | |
} | |
/* try clear-bol, we'll assume exclusive clr_bol */ | |
if (!changed && !marks && clr_bol && blnkx > wx && | |
begns >= wx) { | |
for (x = wx, wp = wcp; x < lastx; ++x, ++wp) | |
if (_DARKCHAR(*wp)) | |
break; | |
/* clearing only whole screen characters */ | |
for (sp = scp+(x-wx); x >= wx; --x, --sp) | |
if (!ISCBIT(*sp)) | |
break; | |
x -= 1; | |
if ((x - (redraw ? 0 : begns)) > _COST(Clr_bol)) { | |
(void) mvcur(cy, cx, wy, x); | |
/* MORE?: colors - mvcur will shuts of */ | |
/* colors when msgr is not defined */ | |
/* SS: colors */ | |
if (back_color_erase) | |
_turn_off_background(); | |
_PUTS(clr_bol, 1); | |
/* LINTED */ | |
cy = (short)wy; | |
/* LINTED */ | |
cx = (short)x; | |
mtch = x - wx; | |
(void) memcpy(scp, wcp, | |
(mtch * sizeof (chtype))); | |
wcp += mtch; | |
scp += mtch; | |
wx = x; | |
} | |
} | |
/* screen image is changing */ | |
changed = TRUE; | |
/* move to the point to start refresh */ | |
if (cy != wy || cx != wx) | |
(void) mvcur(cy, cx, wy, wx); | |
/* LINTED */ | |
cy = (short)wy; | |
/* LINTED */ | |
cx = (short)wx; | |
/* update screen image */ | |
while (wx < lastx) { | |
wc = *wcp; | |
sc = *scp; | |
if (!redraw && !multi_col && wc == sc) | |
break; | |
/* real video attributes */ | |
if (marks) | |
curscr->_attrs = _ATTR(sc); | |
/* blanks only */ | |
if (wx > blnkx) { | |
/* SS: colors */ | |
if (back_color_erase) | |
_turn_off_background(); | |
_PUTS(clr_eol, 1); | |
/* LINTED */ | |
curscr->_curx = (short)wx; | |
/* LINTED */ | |
curscr->_cury = (short)wy; | |
(void) wclrtoeol(curscr); | |
if (marks && wx > 0 && _ATTR(*(scp - 1)) != | |
A_NORMAL) { | |
_VIDS(A_NORMAL, _ATTR(*(scp - 1))); | |
if (_VIDEO(*scp - 1)) | |
_setmark1(wy, wx, NULL); | |
if (_COLOR(*scp - 1)) | |
_setmark2(wy, wx, NULL); | |
} | |
goto done; | |
} | |
/* try insert/delete chars */ | |
if (wx > idcx && !ISCBIT(*scp) && | |
(mtch = _useidch(wcp, scp, lastx - wx, | |
maxi, &idch))) { | |
maxi -= idch; | |
wx += mtch; | |
scp += mtch; | |
wcp += mtch; | |
break; | |
} | |
/* about to output chars, make sure insert */ | |
/* mode is off */ | |
if (SP->phys_irm) | |
_OFFINSERT(); | |
/* color and video attributes */ | |
if (_ATTR(wc) != curscr->_attrs) { | |
bool color_change = FALSE; | |
bool video_change = FALSE; | |
if (marks) { | |
if (_VIDEO(wc) != | |
_VIDEO(curscr->_attrs)) { | |
video_change = TRUE; | |
} | |
} | |
if (color_marks) { | |
if (_COLOR(wc) != | |
_COLOR(curscr->_attrs)) { | |
color_change = TRUE; | |
} | |
} | |
/* the following may occurs when, for */ | |
/* example the application */ | |
/* is written for color terminal and then */ | |
/* run on a monocrome */ | |
if (marks && !video_change && !color_change) | |
goto no_change; | |
/* prevent spilling out of line */ | |
if (marks && !(didcolor && didvideo)) { | |
if ((video_change && !_ISMARK1(wy, | |
video_attrx)) || (color_change && | |
!_ISMARK2(wy, color_attrx))) { | |
int tempx; | |
chtype sa = curscr->_attrs; | |
bool first = FALSE; | |
bool second = FALSE; | |
if (!didvideo && video_change && | |
!_ISMARK1(wy, video_attrx)) { | |
didvideo = TRUE; | |
(void) mvcur(wy, wx, | |
wy, video_attrx); | |
_VIDS(_VIDEO(_virtscr->_y[wy] | |
[video_attrx]), | |
_VIDEO(_virtscr->_y[wy] | |
[video_attrx-1])); | |
_setmark1(wy, video_attrx, | |
NULL); | |
first = TRUE; | |
} | |
if (!didcolor && color_change && | |
!_ISMARK2(wy, color_attrx)) { | |
didcolor = TRUE; | |
tempx = first ? video_attrx : wx; | |
if (tempx != color_attrx) | |
(void) mvcur(wy, tempx, wy, | |
color_attrx); | |
/* | |
* sc = _COLOR(curscr->_y[wy][color_attrx]); | |
* _VIDS(sc, (~sc & A_COLOR)); | |
*/ | |
_VIDS(_COLOR(_virtscr->_y[wy] | |
[color_attrx]), | |
_COLOR(_virtscr->_y[wy] | |
[color_attrx-1])); | |
_setmark2(wy, color_attrx, NULL); | |
second = TRUE; | |
} | |
(void) mvcur(wy, (second ? color_attrx : | |
video_attrx), wy, wx); | |
curscr->_attrs = sa; | |
} | |
} | |
_VIDS(_ATTR(wc), curscr->_attrs); | |
/* on cookie terminals mark the interval */ | |
if (video_change) | |
_setmark1(wy, wx, scp); | |
if (color_change) | |
_setmark2(wy, wx, scp); | |
} | |
/* end-of-line */ | |
no_change: | |
x = 1; | |
if (_scrmax > 1) | |
x = _curs_scrwidth[TYPE(RBYTE(wc))]; | |
if (wx == scrco - x) { | |
_rmargin(wx); | |
goto done; | |
} | |
if (transparent_underline && erase_overstrike && | |
_CHAR(wc) == '_') { | |
(void) _outch(' '); | |
(void) mvcur(wy, wx + 1, wy, wx); | |
} | |
/* put out the character */ | |
(void) _outwch(tilde_glitch && _CHAR(wc) == '~' ? '`' : wc); | |
*scp++ = wc; | |
wcp++; | |
wx++; | |
cx++; | |
/* output entire multi-byte chars */ | |
while (wx < lastx && ISCBIT(*wcp)) { | |
(void) _outwch(*wcp); | |
*scp++ = *wcp++; | |
wx++; | |
cx++; | |
} | |
} | |
} | |
done: | |
if (changed) { | |
/* update the blank structure */ | |
for (wx = 0, scp = curscr->_y[wy]; wx < scrco; ++wx, ++scp) | |
if (_DARKCHAR(*scp)) | |
break; | |
/* LINTED */ | |
_BEGNS[wy] = (short)wx; | |
if (wx == scrco) | |
_ENDNS[wy] = -1; | |
else { | |
wx = scrco - 1; | |
scp = curscr->_y[wy] + wx; | |
for (; wx >= 0; --wx, --scp) | |
if (_DARKCHAR(*scp)) | |
break; | |
/* LINTED */ | |
_ENDNS[wy] = (short)wx; | |
} | |
/* update the hash structure */ | |
_CURHASH[wy] = _BEGNS[wy] < scrco ? _NOHASH : 0; | |
} | |
} | |
/* | |
* See if a left or right shift is apppropriate | |
* This routine is called only if !cookie_glitch or no video attributes | |
* are used in the affected part. | |
* The main idea is to find a longest common substring which is a | |
* prefix of one of 'wcp' or 'scp', then either delete or | |
* insert depending on where the prefix is. | |
* | |
* wcp : what we want the screen to look like | |
* scp : what the screen looks like now | |
* length: the length to be updated | |
* maxi: maximum possible insert amount | |
* id; *id returns the amount of insert/delete | |
* | |
* Return the number of chars matched after the shift. | |
*/ | |
static int | |
_useidch(chtype *wcp, chtype *scp, int length, int maxi, int *id) | |
{ | |
int x1, x2, blnk, idch, cost, cost_ich1, match; | |
chtype wc; | |
/* try deletion */ | |
if (SP->dchok && _CHAR(*wcp) != ' ') { | |
if ((match = _prefix(wcp, scp, length, length / 2, &idch)) > 0) | |
cost = _COST(dcfixed) + (parm_dch ? _COST(Parm_dch) : | |
_COST(Delete_character) * idch); | |
else | |
cost = _INFINITY; | |
if (match >= cost) { | |
/* SS: colors */ | |
if (back_color_erase) | |
_turn_off_background(); | |
if (SP->dmode) { | |
if (SP->sid_equal) { | |
if (!(SP->phys_irm)) | |
_ONINSERT(); | |
} else { | |
if (SP->phys_irm) | |
_OFFINSERT(); | |
_PUTS(enter_delete_mode, 1); | |
} | |
} | |
if (parm_dch) | |
_PUTS(tparm_p1(parm_dch, idch), 1); | |
else | |
for (x1 = 0; x1 < idch; ++x1) | |
_PUTS(delete_character, 1); | |
if (SP->dmode) { | |
if (SP->eid_equal) | |
SP->phys_irm = FALSE; | |
_PUTS(exit_delete_mode, 1); | |
} | |
/* update screen image */ | |
for (x1 = 0, x2 = idch; x2 < length; ++x1, ++x2) | |
scp[x1] = scp[x2]; | |
for (; x1 < length; ++x1) | |
scp[x1] = ' '; | |
*id = -idch; | |
return (match); | |
} | |
} | |
/* no insertion wanted or possible */ | |
if (!(SP->ichok) || _CHAR(*scp) == ' ') | |
return (0); | |
/* see if insertion is worth it */ | |
maxi = (idch = length / 2) < maxi ? idch : maxi; | |
if ((match = _prefix(scp, wcp, length, maxi, &idch)) <= 0) | |
return (0); | |
/* see if inserting blanks only */ | |
for (blnk = 0; blnk < idch; ++blnk) | |
if (wcp[blnk] != ' ') { | |
blnk = 0; | |
break; | |
} | |
/* see if doing insertion is worth it */ | |
cost_ich1 = idch * _COST(Insert_character); | |
if (SP->imode) { | |
cost = SP->phys_irm ? 0 : _COST(icfixed); | |
if (blnk > _COST(Parm_ich) && _COST(Parm_ich) < cost_ich1) | |
cost += _COST(Parm_ich); | |
else | |
if (insert_character) | |
cost += cost_ich1; | |
} else { | |
if (parm_ich && _COST(Parm_ich) < cost_ich1) | |
cost = _COST(Parm_ich); | |
else | |
cost = cost_ich1; | |
} | |
if ((cost - blnk) > match) | |
return (0); | |
/* perform the insertions */ | |
/* SS: colors */ | |
if (back_color_erase) | |
_turn_off_background(); | |
if (SP->imode) { | |
if (!SP->phys_irm) | |
_ONINSERT(); | |
if (blnk > _COST(Parm_ich) && _COST(Parm_ich) < cost_ich1) | |
_PUTS(tparm_p1(parm_ich, idch), 1); | |
else | |
if (insert_character) | |
goto do_insert_char; | |
else | |
/* so that we'll do real char insertions */ | |
blnk = 0; | |
} else { | |
if (parm_ich && _COST(Parm_ich) < cost_ich1) | |
_PUTS(tparm_p1(parm_ich, idch), 1); | |
else { | |
do_insert_char: | |
for (x1 = 0; x1 < idch; ++x1) | |
_PUTS(insert_character, 1); | |
} | |
} | |
/* inserting desired characters */ | |
if (!blnk) | |
for (x1 = 0; x1 < idch; ++x1) { | |
wc = wcp[x1]; | |
if (_ATTR(wc) != curscr->_attrs) | |
_VIDS(_ATTR(wc), curscr->_attrs); | |
(void) _outwch(_CHAR(wc) == '~' && | |
tilde_glitch ? '`' : wc); | |
++cx; | |
} | |
/* update the screen image */ | |
for (x1 = length - 1, x2 = length - idch - 1; x2 >= 0; --x1, --x2) | |
scp[x1] = scp[x2]; | |
(void) memcpy(scp, wcp, idch * sizeof (chtype)); | |
*id = idch; | |
return (match + idch); | |
} | |
/* | |
* Find a substring of s2 that match a prefix of s1. | |
* The substring is such that: | |
* 1. it does not start with an element | |
* that is in perfect alignment with one in s1 and | |
* 2: it is at least as long as the displacement. | |
* | |
* length: the length of s1, s2. | |
* maxs: only search for match in [1,maxs] of s2. | |
* begm: *begm returns where the match begins. | |
* | |
* Return the number of matches. | |
*/ | |
static int | |
_prefix(chtype *s1, chtype *s2, int length, int maxs, int *begm) | |
{ | |
int m, n, k; | |
n = 0; | |
for (m = 1; m <= maxs; ++m) | |
/* testing for s1[m] != s2[m] is condition 1 */ | |
if (s1[0] == s2[m] && s1[m] != s2[m]) { | |
/* see if it's long enough (condition 2) */ | |
for (k = 2 * m - 1; k > m; --k) | |
if (s1[k - m] != s2[k]) | |
break; | |
/* found a match with a good length */ | |
if (k == m) { | |
*begm = m; | |
/* count the # of matches */ | |
s2 += m; | |
length -= m; | |
for (n = m; n < length; ++n) | |
if (s1[n] != s2[n]) | |
break; | |
goto done; | |
} | |
} | |
done: | |
return (n); | |
} | |
/* Set video markers for cookie terminal. */ | |
static void | |
_setmark1(int y, int x, chtype *s) | |
{ | |
long a; | |
/* set the mark map */ | |
marks[y][x / BITSPERBYTE] |= (1 << (x % BITSPERBYTE)); | |
if (s) { | |
a = _VIDEO(curscr->_attrs); | |
/* set the video attr of the first char here */ | |
/* LINTED */ | |
*s = _CHAR(*s) | _COLOR(*s) | a; | |
/* now the video attr of the rest of the affected interval */ | |
for (x += 1, s += 1; x < scrco; ++x, ++s) | |
if (_ISMARK1(y, x)) | |
break; | |
else | |
/* LINTED */ | |
*s = _CHAR(*s) | _COLOR(*s) | a; | |
} | |
} | |
/* Set color markers for cookie terminal. */ | |
static void | |
_setmark2(int y, int x, chtype *s) | |
{ | |
long a; | |
/* set the mark map */ | |
color_marks[y][x / BITSPERBYTE] |= (1 << (x % BITSPERBYTE)); | |
if (s) { | |
a = _COLOR(curscr->_attrs); | |
/* set the video attr of the first char here */ | |
/* LINTED */ | |
*s = _CHAR(*s) | _VIDEO(*s) | a; | |
/* now the video attr of the rest of the affected interval */ | |
for (x += 1, s += 1; x < scrco; ++x, ++s) | |
if (_ISMARK2(y, x)) | |
break; | |
else | |
/* LINTED */ | |
*s = _CHAR(*s) | _VIDEO(*s) | a; | |
} | |
} | |
/* At the right margin various weird things can happen. We treat them here. */ | |
/* At the right margin various weird things can happen. We treat them here. */ | |
static void | |
_rmargin(int wx) | |
{ | |
int x, w, ix; | |
chtype sc; | |
chtype *wcp = _virtscr->_y[cy]; | |
/* screen may scroll */ | |
if (cy == scrli - 1) { | |
/* can't do anything */ | |
if (!SP->ichok) | |
return; | |
/* the width of the new character */ | |
w = _curs_scrwidth[TYPE(RBYTE(wcp[wx]))]; | |
/* the place to put it without causing scrolling */ | |
for (x = wx - 1; x > 0; --x) | |
if (!ISCBIT(wcp[x])) | |
break; | |
sc = curscr->_y[cy][x]; | |
(void) mvcur(cy, cx, cy, x); | |
if (_ATTR(wcp[wx]) != curscr->_attrs) | |
_VIDS(_ATTR(wcp[wx]), curscr->_attrs); | |
(void) _outwch(tilde_glitch && | |
_CHAR(wcp[wx]) == '~' ? '`' : wcp[wx]); | |
for (ix = wx + 1; ix < scrco; ++ix) { | |
(void) _outwch(wcp[ix]); | |
} | |
/* insert sc back in and push wcp[wx] right */ | |
(void) mvcur(cy, x+w, cy, x); | |
/* SS: colors */ | |
if (back_color_erase) | |
_turn_off_background(); | |
if (SP->imode && !SP->phys_irm) | |
_ONINSERT(); | |
/* width of the old character that was overwritten */ | |
w = _curs_scrwidth[TYPE(RBYTE(curscr->_y[cy][x]))]; | |
if (insert_character) | |
for (ix = 0; ix < w; ++ix) | |
_PUTS(insert_character, 1); | |
else | |
if (parm_ich && !SP->imode) | |
_PUTS(tparm_p1(parm_ich, w), 1); | |
if (_ATTR(sc) != curscr->_attrs) | |
_VIDS(_ATTR(sc), curscr->_attrs); | |
for (ix = x; w > 0; --w, ++ix) | |
(void) _outwch(curscr->_y[cy][ix]); | |
/* make sure the video attrs are ok */ | |
if (marks && (_ATTR(sc) || _ATTR(wcp[wx]))) | |
_VIDS(_ATTR(wcp[wx]), ~_ATTR(sc)); | |
/* update screen image */ | |
/* LINTED */ | |
cx = (short)wx; | |
curscr->_y[cy][wx] = wcp[wx]; | |
for (x = wx + 1; x < scrco; ++x) { | |
(void) _outwch(wcp[x]); | |
curscr->_y[cy][x] = wcp[x]; | |
} | |
return; | |
} | |
/* put char out and update screen image */ | |
(void) _outwch(tilde_glitch && _CHAR(wcp[wx]) == '~' ? '`' : wcp[wx]); | |
curscr->_y[cy][wx] = wcp[wx]; | |
for (x = wx + 1; x < scrco; ++x) { | |
(void) _outwch(wcp[x]); | |
curscr->_y[cy][x] = wcp[x]; | |
} | |
/* make sure that wrap-around happens */ | |
if (!auto_right_margin || eat_newline_glitch) { | |
(void) _outch('\r'); | |
(void) _outch('\n'); | |
} | |
cx = 0; | |
++cy; | |
} | |
/* | |
* Find the top-most line to do clear-to-eod. | |
* | |
* topy, boty: the region to consider | |
*/ | |
static int | |
_getceod(int topy, int boty) | |
{ | |
chtype *wcp, *ecp; | |
int wy; | |
short *begch, *endch, *begns; | |
/* do nothing */ | |
if ((topy + 1) >= boty) | |
return (boty); | |
wy = boty - 1; | |
begch = _virtscr->_firstch + wy; | |
endch = _virtscr->_lastch + wy; | |
begns = _BEGNS + wy; | |
for (; wy >= topy; --wy, --begch, --endch, --begns) { | |
if (*endch == _BLANK || (*begch >= scrco && *begns >= scrco)) | |
continue; | |
wcp = _virtscr->_y[wy]; | |
ecp = wcp + scrco; | |
for (; wcp < ecp; ++wcp) | |
if (_DARKCHAR(*wcp)) | |
break; | |
if (wcp != ecp) | |
break; | |
*endch = _BLANK; | |
} | |
return (wy + 1); | |
} | |
/* Use hardware clear-to-bottom. */ | |
static void | |
_useceod(int topy, int boty) | |
{ | |
short *begns, *begch; | |
/* skip lines already blanked */ | |
begch = _virtscr->_firstch + topy; | |
begns = _BEGNS + topy; | |
for (; topy < boty; ++topy, ++begns, ++begch) | |
if (*begns < scrco || *begch == _REDRAW) | |
break; | |
else | |
*begch = _INFINITY; | |
/* nothing to do */ | |
if (topy + 1 >= boty) | |
return; | |
/* see if bottom is clear */ | |
for (begns = _BEGNS + boty; boty < scrli; ++boty, ++begns) | |
if (*begns < scrco) | |
return; | |
/* use clear-screen if appropriate */ | |
if (topy == 0) { | |
/* SS: colors */ | |
if (back_color_erase) | |
_turn_off_background(); | |
_PUTS(clear_screen, scrli); | |
cy = 0; cx = 0; | |
(void) werase(curscr); | |
} else { | |
/* use clear-to-end-of-display or delete lines */ | |
if (clr_eos || (parm_delete_line && !memory_below)) { | |
(void) mvcur(cy, cx, topy, 0); | |
/* LINTED */ | |
cy = (short)topy; | |
cx = 0; | |
/* SS: colors */ | |
if (back_color_erase) | |
_turn_off_background(); | |
_PUTS(clr_eos ? clr_eos : tparm_p1(parm_delete_line, | |
scrli - topy), scrli - topy); | |
/* update curscr */ | |
/* LINTED */ | |
curscr->_cury = (short)topy; | |
curscr->_curx = 0; | |
(void) wclrtobot(curscr); | |
} else { | |
/* no hardware support */ | |
return; | |
} | |
} | |
/* correct the update structure */ | |
(void) wtouchln(_virtscr, topy, scrli, FALSE); | |
} | |
static void | |
_turn_off_background(void) | |
{ | |
/* this routine turn the background color to zero. This need to be */ | |
/* done only in forllowing cases: */ | |
/* 1) We are using Tek type terminal (which has bce terminfo */ | |
/* variable) */ | |
/* 2) The current background is not already zero */ | |
if (set_background && cur_term->_cur_pair.background > 0) { | |
_PUTS(orig_pair, 1); | |
cur_term->_cur_pair.foreground = -1; | |
cur_term->_cur_pair.background = -1; | |
curscr->_attrs &= ~A_COLOR; | |
} | |
} |