Blame | Last modification | View Log | RSS feed
/*
* This code contains changes by
* Gunnar Ritter, Freiburg i. Br., Germany, 2002. All rights reserved.
*
* Conditions 1, 2, and 4 and the no-warranty notice below apply
* to these changes.
*
*
* Copyright (c) 1980, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*
* Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* Redistributions of source code and documentation must retain the
* above copyright notice, this list of conditions and the following
* disclaimer.
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed or owned by Caldera
* International, Inc.
* Neither the name of Caldera International, Inc. nor the names of
* other contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
* INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE
* LIABLE FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef lint
#ifdef DOSCCS
static char sccsid[] = "@(#)ex_v.c 1.17 (gritter) 11/27/04";
#endif
#endif
/* from ex_v.c 7.8.1 (2.11BSD GTE) 12/9/94 */
#include "ex.h"
#include "ex_re.h"
#include "ex_tty.h"
#include "ex_vis.h"
/*
* Entry points to open and visual from command mode processor.
* The open/visual code breaks down roughly as follows:
*
* ex_v.c entry points, checking of terminal characteristics
*
* ex_vadj.c logical screen control, use of intelligent operations
* insert/delete line and coordination with screen image;
* updating of screen after changes.
*
* ex_vget.c input of single keys and reading of input lines
* from the echo area, handling of memory for repeated
* commands and small saved texts from inserts and partline
* deletes, notification of multi line changes in the echo
* area.
*
* ex_vmain.c main command decoding, some command processing.
*
* ex_voperate.c decoding of operator/operand sequences and
* contextual scans, implementation of word motions.
*
* ex_vops.c major operator interfaces, undos, motions, deletes,
* changes, opening new lines, shifts, replacements and yanks
* coordinating logical and physical changes.
*
* ex_vops2.c subroutines for operator interfaces in ex_vops.c,
* insert mode, read input line processing at lowest level.
*
* ex_vops3.c structured motion definitions of ( ) { } and [ ] operators,
* indent for lisp routines, () and {} balancing.
*
* ex_vput.c output routines, clearing, physical mapping of logical cursor
* positioning, cursor motions, handling of insert character
* and delete character functions of intelligent and unintelligent
* terminals, visual mode tracing routines (for debugging),
* control of screen image and its updating.
*
* ex_vwind.c window level control of display, forward and backward rolls,
* absolute motions, contextual displays, line depth determination
*/
JMP_BUF venv;
/*
* Enter open mode
*/
#ifdef u370
cell atube[TUBESIZE+LBSIZE];
#endif
void
oop(void)
{
register char *ic;
#ifndef u370
cell atube[TUBESIZE + LBSIZE];
#endif
struct termios f; /* mjm: was register */
int resize;
resize = SETJMP(venv);
if (resize) {
setsize();
initev = (char *)0;
inopen = 0;
addr1 = addr2 = dot;
}
#ifdef SIGWINCH
signal(SIGWINCH, onwinch);
#endif
ovbeg();
if (peekchar() == '/') {
ignore(compile(getchar(), 1));
savere(&scanre);
if (execute(0, dot) == 0)
error(catgets(catd, 1, 207,
"Fail|Pattern not found on addressed line"));
ic = loc1;
if (ic > linebuf && *ic == 0)
ic--;
} else {
getDOT();
ic = vskipwh(linebuf);
}
newline();
/*
* If overstrike then have to HARDOPEN
* else if can move cursor up off current line can use CRTOPEN (~~vi1)
* otherwise (ugh) have to use ONEOPEN (like adm3)
*/
if (OS && !EO)
bastate = HARDOPEN;
else if (CA || UP)
bastate = CRTOPEN;
else
bastate = ONEOPEN;
setwind();
/*
* To avoid bombing on glass-crt's when the line is too long
* pretend that such terminals are 160 columns wide.
* If a line is too wide for display, we will dynamically
* switch to hardcopy open mode.
*/
if (state != CRTOPEN)
WCOLS = TUBECOLS;
if (!inglobal)
savevis();
vok(atube);
if (state != CRTOPEN)
TCOLUMNS = WCOLS;
Outchar = vputchar;
f = ostart();
if (state == CRTOPEN) {
if (outcol == UKCOL)
outcol = 0;
vmoveitup(1, 1);
} else
outline = destline = WBOT;
vshow(dot, NOLINE);
vnline(ic);
vmain();
if (state != CRTOPEN)
vclean();
Command = "open";
ovend(f);
#ifdef SIGWINCH
signal(SIGWINCH, SIG_DFL);
#endif
}
void
ovbeg(void)
{
if (!value(OPEN))
error(catgets(catd, 1, 208,
"Can't use open/visual unless open option is set"));
if (inopen)
error(catgets(catd, 1, 209,
"Recursive open/visual not allowed"));
Vlines = lineDOL();
fixzero();
setdot();
pastwh();
dot = addr2;
}
void
ovend(struct termios f)
{
splitw++;
vgoto(WECHO, 0);
vclreol();
vgoto(WECHO, 0);
holdcm = 0;
splitw = 0;
ostop(f);
setoutt();
undvis();
TCOLUMNS = OCOLUMNS;
inopen = 0;
flusho();
netchHAD(Vlines);
}
/*
* Enter visual mode
*/
void
vop(void)
{
register int c;
#ifndef u370
cell atube[TUBESIZE + LBSIZE];
#endif
struct termios f; /* mjm: was register */
int resize;
if (!CA && UP == NOSTR) {
if (initev) {
toopen:
merror(catgets(catd, 1, 210, "[Using open mode]"));
putNFL();
oop();
return;
}
error(catgets(catd, 1, 211,
"Visual needs addressible cursor or upline capability"));
}
if (OS && !EO) {
if (initev)
goto toopen;
error(catgets(catd, 1, 212,
"Can't use visual on a terminal which overstrikes"));
}
if (!CL) {
if (initev)
goto toopen;
error(catgets(catd, 1, 213,
"Visual requires clear screen capability"));
}
if (NS && !SF) {
if (initev)
goto toopen;
error(catgets(catd, 1, 214, "Visual requires scrolling"));
}
resize = SETJMP(venv);
if (resize) {
setsize();
initev = (char *)0;
inopen = 0;
addr1 = addr2 = dot;
}
#ifdef SIGWINCH
signal(SIGWINCH, onwinch);
#endif
ovbeg();
bastate = VISUAL;
c = 0;
if (any(peekchar(), "+-^."))
c = getchar();
pastwh();
vsetsiz(isdigit(peekchar()) ? getnum() : value(WINDOW));
setwind();
newline();
vok(atube);
if (!inglobal)
savevis();
Outchar = vputchar;
vmoving = 0;
f = ostart();
if (initev == 0) {
vcontext(dot, c);
vnline(NOSTR);
}
vmain();
Command = "visual";
ovend(f);
#ifdef SIGWINCH
signal(SIGWINCH, SIG_DFL);
#endif
}
/*
* Hack to allow entry to visual with
* empty buffer since routines internally
* demand at least one line.
*/
void
fixzero(void)
{
if (dol == zero) {
register bool ochng = chng;
vdoappend("");
if (!ochng)
synced();
fixedzero++;
addr1 = addr2 = one;
} else if (addr2 == zero)
addr2 = one;
}
/*
* Save lines before visual between unddol and truedol.
* Accomplish this by throwing away current [unddol,truedol]
* and then saving all the lines in the buffer and moving
* unddol back to dol. Don't do this if in a global.
*
* If you do
* g/xxx/vi.
* and then do a
* :e xxxx
* at some point, and then quit from the visual and undo
* you get the old file back. Somewhat weird.
*/
void
savevis(void)
{
if (inglobal)
return;
truedol = unddol;
saveall();
unddol = dol;
undkind = UNDNONE;
}
/*
* Restore a sensible state after a visual/open, moving the saved
* stuff back to [unddol,dol], and killing the partial line kill indicators.
*/
void
undvis(void)
{
if (ruptible)
signal(SIGINT, onintr);
squish();
pkill[0] = pkill[1] = 0;
unddol = truedol;
unddel = zero;
undap1 = one;
undap2 = dol + 1;
undkind = UNDALL;
if (undadot <= zero || undadot > dol)
undadot = zero+1;
}
/*
* Set the window parameters based on the base state bastate
* and the available buffer space.
*/
void
setwind(void)
{
WCOLS = TCOLUMNS;
switch (bastate) {
case ONEOPEN:
if (AM)
WCOLS--;
/* fall into ... */
case HARDOPEN:
basWTOP = WTOP = WBOT = WECHO = 0;
ZERO = 0;
holdcm++;
break;
case CRTOPEN:
basWTOP = TLINES - 2;
/* fall into */
case VISUAL:
ZERO = TLINES - TUBESIZE / WCOLS;
if (ZERO < 0)
ZERO = 0;
if (ZERO > basWTOP)
error(catgets(catd, 1, 215,
"Screen too large for internal buffer"));
WTOP = basWTOP; WBOT = TLINES - 2; WECHO = TLINES - 1;
break;
}
state = bastate;
basWLINES = WLINES = WBOT - WTOP + 1;
}
/*
* Can we hack an open/visual on this terminal?
* If so, then divide the screen buffer up into lines,
* and initialize a bunch of state variables before we start.
*/
void
vok(register cell *atube)
{
register int i;
if (WCOLS == 1000)
serror(catgets(catd, 1, 216,
"Don't know enough about your terminal to use %s"), Command);
if (WCOLS > TUBECOLS)
error(catgets(catd, 1, 217, "Terminal too wide"));
if (WLINES >= TUBELINES || WCOLS * (WECHO - ZERO + 1) > TUBESIZE)
error(catgets(catd, 1, 218, "Screen too large"));
vtube0 = atube;
vclrcell(atube, WCOLS * (WECHO - ZERO + 1));
for (i = 0; i < ZERO; i++)
vtube[i] = (cell *) 0;
for (; i <= WECHO; i++)
vtube[i] = atube, atube += WCOLS;
for (; i < TUBELINES; i++)
vtube[i] = (cell *) 0;
vutmp = (char *)atube;
vundkind = VNONE;
vUNDdot = 0;
OCOLUMNS = TCOLUMNS;
inopen = 1;
signal(SIGINT, vintr);
vmoving = 0;
splitw = 0;
doomed = 0;
holdupd = 0;
Peekkey = 0;
vcnt = vcline = 0;
if (vSCROLL == 0)
vSCROLL = value(SCROLL);
/*old vSCROLL = (value(WINDOW)+1)/2;*//* round up so dft=6,11 */
}
void
vintr(int signum)
{
extern JMP_BUF readbuf;
extern int doingread;
signal(SIGINT, vintr);
if (vcatch)
onintr(SIGINT);
ungetkey(ATTN);
draino();
if (doingread) {
doingread = 0;
LONGJMP(readbuf, 1);
}
}
/*
* Set the size of the screen to size lines, to take effect the
* next time the screen is redrawn.
*/
void
vsetsiz(int size)
{
register int b;
if (bastate != VISUAL)
return;
b = TLINES - 1 - size;
if (b >= TLINES - 1)
b = TLINES - 2;
if (b < 0)
b = 0;
basWTOP = b;
basWLINES = WBOT - b + 1;
}
#ifdef SIGWINCH
void
onwinch(int signum)
{
vsave();
setty(normf);
LONGJMP(venv, 1);
}
#endif