8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / cmd / vi / port / ex_vwind.c
blobcdaf577a2bb7cca37f12e7797b76a31351bc8b4c
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 /* Copyright (c) 1981 Regents of the University of California */
32 #include "ex.h"
33 #include "ex_tty.h"
34 #include "ex_vis.h"
37 * Routines to adjust the window, showing specified lines
38 * in certain positions on the screen, and scrolling in both
39 * directions. Code here is very dependent on mode (open versus visual).
43 * Move in a nonlocal way to line addr.
44 * If it isn't on screen put it in specified context.
45 * New position for cursor is curs.
46 * Like most routines here, we vsave().
48 void
49 vmoveto(addr, curs, context)
50 line *addr;
51 unsigned char *curs;
52 unsigned char context;
55 markit(addr);
56 vsave();
57 vjumpto(addr, curs, context);
61 * Vjumpto is like vmoveto, but doesn't mark previous
62 * context or save linebuf as current line.
64 void
65 vjumpto(line *addr, unsigned char *curs, unsigned char context)
68 noteit(0);
69 if (context != 0)
70 vcontext(addr, context);
71 else
72 vshow(addr, NOLINE);
73 noteit(1);
74 vnline(curs);
78 * Go up or down cnt (negative is up) to new position curs.
80 void
81 vupdown(int cnt, unsigned char *curs)
84 if (cnt > 0)
85 vdown(cnt, 0, 0);
86 else if (cnt < 0)
87 vup(-cnt, 0, 0);
88 if (vcnt == 0)
89 vrepaint(curs);
90 else
91 vnline(curs);
95 * Go up cnt lines, afterwards preferring to be ind
96 * logical lines from the top of the screen.
97 * If scroll, then we MUST use a scroll.
98 * Otherwise clear and redraw if motion is far.
100 void
101 vup(int cnt, int ind, bool scroll)
103 int i, tot;
105 if (dot == one) {
106 (void) beep();
107 return;
109 vsave();
110 i = lineDOT() - 1;
111 if (cnt > i) {
112 ind -= cnt - i;
113 if (ind < 0)
114 ind = 0;
115 cnt = i;
117 if (!scroll && cnt <= vcline) {
118 vshow(dot - cnt, NOLINE);
119 return;
121 cnt -= vcline, dot -= vcline, vcline = 0;
122 if (hold & HOLDWIG)
123 goto contxt;
124 if (state == VISUAL && !insert_line && !scroll_reverse &&
125 cnt <= WTOP - ZERO && vfit(dot - cnt, cnt) <= WTOP - ZERO)
126 goto okr;
127 tot = WECHO - WTOP;
128 if (state != VISUAL || (!insert_line && !scroll_reverse) || (!scroll && (cnt > tot || vfit(dot - cnt, cnt) > tot / 3 + 1))) {
129 if (ind > basWLINES / 2)
130 ind = basWLINES / 3;
131 contxt:
132 vcontext(dot + ind - cnt, '.');
133 return;
135 okr:
136 vrollR(cnt);
137 if (scroll) {
138 vcline += ind, dot += ind;
139 if (vcline >= vcnt)
140 dot -= vcline - vcnt + 1, vcline = vcnt - 1;
141 getDOT();
146 * Like vup, but scrolling down.
148 void
149 vdown(int cnt, int ind, bool scroll)
151 int i, tot;
153 if (dot == dol) {
154 (void) beep();
155 return;
157 vsave();
158 i = dol - dot;
159 if (cnt > i) {
160 ind -= cnt - i;
161 if (ind < 0)
162 ind = 0;
163 cnt = i;
165 i = vcnt - vcline - 1;
166 if (!scroll && cnt <= i) {
167 vshow(dot + cnt, NOLINE);
168 return;
170 cnt -= i, dot += i, vcline += i;
171 if (hold & HOLDWIG)
172 goto dcontxt;
173 if (!scroll) {
174 tot = WECHO - WTOP;
175 if (state != VISUAL || cnt - tot > 0 || vfit(dot, cnt) > tot / 3 + 1) {
176 dcontxt:
177 vcontext(dot + cnt, '.');
178 return;
181 if (cnt > 0)
182 vroll(cnt);
183 if (state == VISUAL && scroll) {
184 vcline -= ind, dot -= ind;
185 if (vcline < 0)
186 dot -= vcline, vcline = 0;
187 getDOT();
192 * Show line addr in context where on the screen.
193 * Work here is in determining new top line implied by
194 * this placement of line addr, since we always draw from the top.
196 void
197 vcontext(line *addr, unsigned char where)
199 line *top;
201 getaline(*addr);
202 if (state != VISUAL)
203 top = addr;
204 else switch (where) {
206 case '^':
207 addr = vback(addr, basWLINES - vdepth());
208 getaline(*addr);
209 /* fall into ... */
211 case '-':
212 top = vback(addr, basWLINES - vdepth());
213 getaline(*addr);
214 break;
216 case '.':
217 top = vback(addr, basWLINES / 2 - vdepth());
218 getaline(*addr);
219 break;
221 default:
222 top = addr;
223 break;
225 if (state == ONEOPEN && LINE(0) == WBOT)
226 vup1();
227 vcnt = vcline = 0;
228 vclean();
229 if (state == CRTOPEN)
230 vup1();
231 vshow(addr, top);
235 * Get a clean line. If we are in a hard open
236 * we may be able to reuse the line we are on
237 * if it is blank. This is a real win.
239 void
240 vclean(void)
243 if (state != VISUAL && state != CRTOPEN) {
244 destcol = 0;
245 if (!ateopr())
246 vup1();
247 vcnt = 0;
252 * Show line addr with the specified top line on the screen.
253 * Top may be 0; in this case have vcontext compute the top
254 * (and call us recursively). Eventually, we clear the screen
255 * (or its open mode equivalent) and redraw.
257 void
258 vshow(line *addr, line *top)
260 #ifndef CBREAK
261 bool fried = 0;
262 #endif
263 int cnt = addr - dot;
264 int i = vcline + cnt;
265 short oldhold = hold;
267 if (state != HARDOPEN && state != ONEOPEN && i >= 0 && i < vcnt) {
268 dot = addr;
269 getDOT();
270 vcline = i;
271 return;
273 if (state != VISUAL) {
274 dot = addr;
275 vopen(dot, WBOT);
276 return;
278 if (top == 0) {
279 vcontext(addr, '.');
280 return;
282 dot = top;
283 #ifndef CBREAK
284 if (vcookit(2))
285 fried++, vcook();
286 #endif
287 oldhold = hold;
288 hold |= HOLDAT;
289 vclear();
290 vreset(0);
291 vredraw(WTOP);
292 /* error if vcline >= vcnt ! */
293 vcline = addr - top;
294 dot = addr;
295 getDOT();
296 hold = oldhold;
297 vsync(LASTLINE);
298 #ifndef CBREAK
299 if (fried)
300 flusho(), vraw();
301 #endif
305 * reset the state.
306 * If inecho then leave us at the beginning of the echo
307 * area; we are called this way in the middle of a :e escape
308 * from visual, e.g.
310 void
311 vreset(bool inecho)
314 vcnt = vcline = 0;
315 WTOP = basWTOP;
316 WLINES = basWLINES;
317 if (inecho)
318 splitw = 1, vgoto(WECHO, 0);
322 * Starting from which line preceding tp uses almost (but not more
323 * than) cnt physical lines?
325 line *
326 vback(tp, cnt)
327 int cnt;
328 line *tp;
330 int d;
332 if (cnt > 0)
333 for (; tp > one; tp--) {
334 getaline(tp[-1]);
335 d = vdepth();
336 if (d > cnt)
337 break;
338 cnt -= d;
340 return (tp);
344 * How much scrolling will it take to roll cnt lines starting at tp?
347 vfit(line *tp, int cnt)
349 int j;
351 j = 0;
352 while (cnt > 0) {
353 cnt--;
354 getaline(tp[cnt]);
355 j += vdepth();
357 if (tp > dot)
358 j -= WBOT - LASTLINE;
359 return (j);
363 * Roll cnt lines onto the screen.
365 void
366 vroll(int cnt)
368 #ifndef CBREAK
369 bool fried = 0;
370 #endif
371 short oldhold = hold;
373 #ifdef ADEBUG
374 if (trace)
375 tfixnl(), fprintf(trace, "vroll(%d)\n", cnt);
376 #endif
377 if (state != VISUAL)
378 hold |= HOLDAT|HOLDROL;
379 if (WBOT == WECHO) {
380 vcnt = 0;
381 if (state == ONEOPEN)
382 vup1();
384 #ifndef CBREAK
385 if (vcookit(cnt))
386 fried++, vcook();
387 #endif
388 for (; cnt > 0 && Peekkey != ATTN; cnt--) {
389 dot++, vcline++;
390 vopen(dot, LASTLINE);
391 vscrap();
393 hold = oldhold;
394 if (state == HARDOPEN)
395 sethard();
396 vsyncCL();
397 #ifndef CBREAK
398 if (fried)
399 flusho(), vraw();
400 #endif
404 * Roll backwards (scroll up).
406 void
407 vrollR(int cnt)
409 bool fried = 0;
410 short oldhold = hold;
412 #ifdef ADEBUG
413 if (trace)
414 tfixnl(), fprintf(trace, "vrollR(%d), dot=%d\n", cnt, lineDOT());
415 #endif
416 #ifndef CBREAK
417 if (vcookit(cnt))
418 fried++, vcook();
419 #endif
420 if (WBOT == WECHO)
421 vcnt = 0;
422 heldech = 0;
423 hold |= HOLDAT|HOLDECH;
424 for (; cnt > 0 && Peekkey != ATTN; cnt--) {
425 dot--;
426 vopen(dot, WTOP);
427 vscrap();
429 hold = oldhold;
430 if (heldech)
431 vclrech(0);
432 vsync(LINE(vcnt-1));
433 #ifndef CBREAK
434 if (fried)
435 flusho(), vraw();
436 #endif
440 * Go into cooked mode (allow interrupts) during
441 * a scroll if we are at less than 1200 baud and not
442 * a 'vi' command, of if we are in a 'vi' command and the
443 * scroll is more than 2 full screens.
445 * BUG: An interrupt during a scroll in this way
446 * dumps to command mode.
449 vcookit(int cnt)
452 return (cnt > 1 && (ospeed < B1200 && !initev || cnt > lines * 2));
456 * Determine displayed depth of current line.
459 vdepth(void)
461 int d;
463 d = (column(NOSTR) + WCOLS - 1 + (Putchar == listchar) + insert_null_glitch) / WCOLS;
464 #ifdef ADEBUG
465 if (trace)
466 tfixnl(), fprintf(trace, "vdepth returns %d\n", d == 0 ? 1 : d);
467 #endif
468 return (d == 0 ? 1 : d);
472 * Move onto a new line, with cursor at position curs.
474 void
475 vnline(unsigned char *curs)
477 unsigned char *owcursor;
478 int j;
479 if (curs) {
480 if(curs >= strend(linebuf)) {
481 if(!*linebuf)
482 wcursor = linebuf;
483 else {
484 wcursor = strend(linebuf);
485 wcursor = lastchr(linebuf, wcursor);
487 } else {
488 owcursor = wcursor = curs;
489 j = wcursor - linebuf;
490 for(wcursor = linebuf; wcursor - linebuf < j; ) {
491 owcursor = wcursor;
492 wcursor = nextchr(wcursor);
494 if(wcursor - linebuf > j)
495 wcursor = owcursor;
498 } else if (vmoving)
499 wcursor = vfindcol(vmovcol);
500 else
501 wcursor = vskipwh(linebuf);
502 cursor = linebuf;
503 (void) vmove();