summaryrefslogtreecommitdiff
path: root/ex_vwind.c
diff options
context:
space:
mode:
Diffstat (limited to 'ex_vwind.c')
-rw-r--r--ex_vwind.c500
1 files changed, 500 insertions, 0 deletions
diff --git a/ex_vwind.c b/ex_vwind.c
new file mode 100644
index 0000000..751c991
--- /dev/null
+++ b/ex_vwind.c
@@ -0,0 +1,500 @@
+/*
+ * 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_vwind.c 1.9 (gritter) 11/23/04";
+#endif
+#endif
+
+/* from ex_vwind.c 7.3 (Berkeley) 6/7/85 */
+
+#include "ex.h"
+#include "ex_tty.h"
+#include "ex_vis.h"
+
+/*
+ * Routines to adjust the window, showing specified lines
+ * in certain positions on the screen, and scrolling in both
+ * directions. Code here is very dependent on mode (open versus visual).
+ */
+
+/*
+ * Move in a nonlocal way to line addr.
+ * If it isn't on screen put it in specified context.
+ * New position for cursor is curs.
+ * Like most routines here, we vsave().
+ */
+void
+vmoveto(register line *addr, char *curs, int context)
+{
+
+ markit(addr);
+ vsave();
+ vjumpto(addr, curs, context);
+}
+
+/*
+ * Vjumpto is like vmoveto, but doesn't mark previous
+ * context or save linebuf as current line.
+ */
+void
+vjumpto(register line *addr, char *curs, int context)
+{
+
+ noteit(0);
+ if (context != 0)
+ vcontext(addr, context);
+ else
+ vshow(addr, NOLINE);
+ noteit(1);
+ vnline(curs);
+}
+
+/*
+ * Go up or down cnt (negative is up) to new position curs.
+ */
+void
+vupdown(register int cnt, char *curs)
+{
+
+ if (cnt > 0)
+ vdown(cnt, 0, 0);
+ else if (cnt < 0)
+ vup(-cnt, 0, 0);
+ if (vcnt == 0)
+ vrepaint(curs);
+ else
+ vnline(curs);
+}
+
+/*
+ * Go up cnt lines, afterwards preferring to be ind
+ * logical lines from the top of the screen.
+ * If scroll, then we MUST use a scroll.
+ * Otherwise clear and redraw if motion is far.
+ */
+void
+vup(register int cnt, register int ind, int scroll)
+{
+ register int i, tot;
+
+ if (dot == one) {
+ beep();
+ return;
+ }
+ vsave();
+ i = lineDOT() - 1;
+ if (cnt > i) {
+ ind -= cnt - i;
+ if (ind < 0)
+ ind = 0;
+ cnt = i;
+ }
+ if (!scroll && cnt <= vcline) {
+ vshow(dot - cnt, NOLINE);
+ return;
+ }
+ cnt -= vcline, dot -= vcline, vcline = 0;
+ if (hold & HOLDWIG)
+ goto contxt;
+ if (state == VISUAL && !AL && !SR &&
+ cnt <= WTOP - ZERO && vfit(dot - cnt, cnt) <= WTOP - ZERO)
+ goto okr;
+ tot = WECHO - ZERO;
+ if (state != VISUAL || (!AL && !SR) || (!scroll && (cnt > tot || vfit(dot - cnt, cnt) > tot / 3 + 1))) {
+ if (ind > basWLINES / 2)
+ ind = basWLINES / 3;
+contxt:
+ vcontext(dot + ind - cnt, '.');
+ return;
+ }
+okr:
+ vrollR(cnt);
+ if (scroll) {
+ vcline += ind, dot += ind;
+ if (vcline >= vcnt)
+ dot -= vcline - vcnt + 1, vcline = vcnt - 1;
+ getDOT();
+ }
+}
+
+/*
+ * Like vup, but scrolling down.
+ */
+void
+vdown(register int cnt, register int ind, int scroll)
+{
+ register int i, tot;
+
+ if (dot == dol) {
+ beep();
+ return;
+ }
+ vsave();
+ i = dol - dot;
+ if (cnt > i) {
+ ind -= cnt - i;
+ if (ind < 0)
+ ind = 0;
+ cnt = i;
+ }
+ i = vcnt - vcline - 1;
+ if (!scroll && cnt <= i) {
+ vshow(dot + cnt, NOLINE);
+ return;
+ }
+ cnt -= i, dot += i, vcline += i;
+ if (hold & HOLDWIG)
+ goto dcontxt;
+ if (!scroll) {
+ tot = WECHO - ZERO;
+ if (state != VISUAL || cnt - tot > 0 || vfit(dot, cnt) > tot / 3 + 1) {
+dcontxt:
+ vcontext(dot + cnt, '.');
+ return;
+ }
+ }
+ if (cnt > 0)
+ vroll(cnt);
+ if (state == VISUAL && scroll) {
+ vcline -= ind, dot -= ind;
+ if (vcline < 0)
+ dot -= vcline, vcline = 0;
+ getDOT();
+ }
+}
+
+/*
+ * Show line addr in context where on the screen.
+ * Work here is in determining new top line implied by
+ * this placement of line addr, since we always draw from the top.
+ */
+void
+vcontext(register line *addr, int where)
+{
+ register line *top;
+
+ getline(*addr);
+ if (state != VISUAL)
+ top = addr;
+ else switch (where) {
+
+ case '^':
+ addr = vback(addr, basWLINES - vdepth());
+ getline(*addr);
+ /* fall into ... */
+
+ case '-':
+ top = vback(addr, basWLINES - vdepth());
+ getline(*addr);
+ break;
+
+ case '.':
+ top = vback(addr, basWLINES / 2 - vdepth());
+ getline(*addr);
+ break;
+
+ default:
+ top = addr;
+ break;
+ }
+ if (state == ONEOPEN && LINE(0) == WBOT)
+ vup1();
+ vcnt = vcline = 0;
+ vclean();
+ if (state == CRTOPEN)
+ vup1();
+ vshow(addr, top);
+}
+
+/*
+ * Get a clean line. If we are in a hard open
+ * we may be able to reuse the line we are on
+ * if it is blank. This is a real win.
+ */
+void
+vclean(void)
+{
+
+ if (state != VISUAL && state != CRTOPEN) {
+ destcol = 0;
+ if (!ateopr())
+ vup1();
+ vcnt = 0;
+ }
+}
+
+/*
+ * Show line addr with the specified top line on the screen.
+ * Top may be 0; in this case have vcontext compute the top
+ * (and call us recursively). Eventually, we clear the screen
+ * (or its open mode equivalent) and redraw.
+ */
+void
+vshow(line *addr, line *top)
+{
+ register int cnt = addr - dot;
+ register int i = vcline + cnt;
+ short oldhold = hold;
+
+ if (state != HARDOPEN && state != ONEOPEN && i >= 0 && i < vcnt) {
+ dot = addr;
+ getDOT();
+ vcline = i;
+ return;
+ }
+ if (state != VISUAL) {
+ dot = addr;
+ vopen(dot, WBOT);
+ return;
+ }
+ if (top == 0) {
+ vcontext(addr, '.');
+ return;
+ }
+ dot = top;
+ oldhold = hold;
+ hold |= HOLDAT;
+ vclear();
+ vreset(0);
+ vredraw(WTOP);
+ /* error if vcline >= vcnt ! */
+ vcline = addr - top;
+ dot = addr;
+ getDOT();
+ hold = oldhold;
+ vsync(LASTLINE);
+}
+
+/*
+ * reset the state.
+ * If inecho then leave us at the beginning of the echo
+ * area; we are called this way in the middle of a :e escape
+ * from visual, e.g.
+ */
+void
+vreset(int inecho)
+{
+
+ vcnt = vcline = 0;
+ WTOP = basWTOP;
+ WLINES = basWLINES;
+ if (inecho)
+ splitw = 1, vgoto(WECHO, 0);
+}
+
+/*
+ * Starting from which line preceding tp uses almost (but not more
+ * than) cnt physical lines?
+ */
+line *
+vback(register line *tp, register int cnt)
+{
+ register int d;
+
+ if (cnt > 0)
+ for (; tp > one; tp--) {
+ getline(tp[-1]);
+ d = vdepth();
+ if (d > cnt)
+ break;
+ cnt -= d;
+ }
+ return (tp);
+}
+
+/*
+ * How much scrolling will it take to roll cnt lines starting at tp?
+ */
+int
+vfit(register line *tp, int cnt)
+{
+ register int j;
+
+ j = 0;
+ while (cnt > 0) {
+ cnt--;
+ getline(tp[cnt]);
+ j += vdepth();
+ }
+ if (tp > dot)
+ j -= WBOT - LASTLINE;
+ return (j);
+}
+
+/*
+ * Roll cnt lines onto the screen.
+ */
+void
+vroll(register int cnt)
+{
+ short oldhold = hold;
+
+#ifdef ADEBUG
+ if (trace)
+ tfixnl(), fprintf(trace, "vroll(%d)\n", cnt);
+#endif
+ if (state != VISUAL)
+ hold |= HOLDAT|HOLDROL;
+ if (WBOT == WECHO) {
+ vcnt = 0;
+ if (state == ONEOPEN)
+ vup1();
+ }
+ for (; cnt > 0 && Peekkey != ATTN; cnt--) {
+ dot++, vcline++;
+ vopen(dot, LASTLINE);
+ vscrap();
+ }
+ hold = oldhold;
+ if (state == HARDOPEN)
+ sethard();
+ vsyncCL();
+}
+
+/*
+ * Roll backwards (scroll up).
+ */
+void
+vrollR(register int cnt)
+{
+ short oldhold = hold;
+
+#ifdef ADEBUG
+ if (trace)
+ tfixnl(), fprintf(trace, "vrollR(%d), dot=%d\n", cnt, lineDOT());
+#endif
+ if (WBOT == WECHO)
+ vcnt = 0;
+ heldech = 0;
+ hold |= HOLDAT|HOLDECH;
+ for (; cnt > 0 && Peekkey != ATTN; cnt--) {
+ dot--;
+ vopen(dot, WTOP);
+ vscrap();
+ }
+ hold = oldhold;
+ if (heldech)
+ vclrech(0);
+ vsync(LINE(vcnt-1));
+}
+
+/*
+ * Go into cooked mode (allow interrupts) during
+ * a scroll if we are at less than 1200 baud and not
+ * a 'vi' command, of if we are in a 'vi' command and the
+ * scroll is more than 2 full screens.
+ *
+ * BUG: An interrupt during a scroll in this way
+ * dumps to command mode.
+ */
+int
+vcookit(register int cnt)
+{
+
+ return (cnt > 1 && (ospeed < B1200 && !initev || cnt > TLINES * 2));
+}
+
+/*
+ * Determine displayed depth of current line.
+ */
+int
+vdepth(void)
+{
+ register int d;
+
+ d = (column(NOSTR) + WCOLS - 1 + (Putchar == listchar) + IN) / WCOLS;
+#ifdef ADEBUG
+ if (trace)
+ tfixnl(), fprintf(trace, "vdepth returns %d\n", d == 0 ? 1 : d);
+#endif
+ return (d == 0 ? 1 : d);
+}
+
+/*
+ * Move onto a new line, with cursor at position curs.
+ */
+void
+vnline(char *curs)
+{
+
+ if (curs)
+ wcursor = curs;
+ else if (vmoving)
+ wcursor = vfindcol(vmovcol);
+ else
+ wcursor = vskipwh(linebuf);
+ cursor = linebuf;
+ vmove(0);
+}