/* * 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