source: trunk/minix/commands/elle/eefd.c@ 9

Last change on this file since 9 was 9, checked in by Mattia Monga, 13 years ago

Minix 3.1.2a

File size: 11.1 KB
RevLine 
[9]1/* ELLE - Copyright 1982, 1987 by Ken Harrenstien, SRI International
2 * This software is quasi-public; it may be used freely with
3 * like software, but may NOT be sold or made part of licensed
4 * products without permission of the author.
5 */
6
7/* EEFD Display control functions
8 */
9
10#include "elle.h"
11
12
13#if FX_NEWWIN
14/* EFUN: "New Window" */
15/* Clear current window and set as requested.
16 * ^L - clear current window and redisplay it (default top)
17 * <arg>^L - select new window so that current line is
18 * the <arg>'th from top of window (0 = top line)
19 * ^U^L - clear current line and redisplay.
20 */
21f_newwin()
22{ register int i, n;
23 register struct window *w;
24
25 d_fixcur(); /* Ensure screen vars correct */
26 w = cur_win;
27 if (exp_p)
28 { if((n = exp) == 4 && exp_p == 4 /* CTRL-U? */
29 && (i = d_line(cur_dot)) >= 0) /* On valid line? */
30 { d_lupd(w, i); /* Update it */
31 return;
32 }
33 }
34 else /* No argument given */
35 { redp(RD_SCREEN); /* Clear whole screen (later just window? */
36#if IMAGEN
37 return;
38#else
39 n = (ev_nwpct*w->w_ht)/100; /* Set new window using % */
40#endif /*-IMAGEN*/
41 }
42 if (n < 0) n = 0; /* Ensure # is reasonable */
43 else if (n >= w->w_ht)
44 n = w->w_ht - 1;
45 d_fgoloff(-n); /* Go up given # of lines */
46 w->w_topldot = e_dot(); /* Set new top-line dot */
47 e_gocur(); /* Move back to cur_dot */
48 redp(RD_FIXWIN); /* Say to re-hack window */
49}
50#endif /*FX_NEWWIN*/
51
52#if FX_NSCREEN
53/* EFUN: "Next Screen" */
54f_nscreen()
55{ d_screen( exp);
56}
57#endif /*FX_NSCREEN*/
58
59#if FX_PSCREEN
60/* EFUN: "Previous Screen" */
61f_pscreen()
62{ d_screen(-exp);
63}
64#endif /*FX_PSCREEN*/
65
66#if FX_OTHNSCREEN
67/* EFUN: "Other New Screen" (not EMACS) - from IMAGEN config */
68f_othnscreen()
69{
70 if (! oth_win)
71 return;
72 f_othwind();
73 if (exp_p) /* With arg, back up */
74 d_screen(-1);
75 else
76 d_screen(1);
77 f_othwind();
78 redp(RD_WINDS); /* Look at all windows */
79}
80#endif /*FX_OTHNSCREEN*/
81
82
83#if FX_LWINDBORD
84/* EFUN: "Line to Window Border" (not EMACS) - from IMAGEN config */
85f_lwindbord()
86{
87 if (exp_p)
88 /* With arg, means "to bottom" */
89 exp = cur_win->w_ht - 1;
90 else
91 /* Else, to top */
92 exp = 0;
93
94 /* Just a "front end" for ^L */
95 exp_p = 1;
96 f_newwin();
97}
98#endif /*FX_LWINDBORD*/
99
100#if FX_SCUPWIND
101/* EFUN: "Scroll Window Up" (not EMACS) - from IMAGEN config */
102f_scupwind()
103{
104 scroll_win(exp);
105}
106#endif /*FX_SCUPWIND*/
107
108#if FX_SCDNWIND
109/* EFUN: "Scroll Window Down" (not EMACS) - from IMAGEN config */
110f_scdnwind()
111{
112 scroll_win(-exp);
113}
114#endif /*FX_SCDNWIND*/
115
116
117#if FX_MVWTOP
118/* EFUN: "Move to Window Top" (not EMACS) - from IMAGEN config */
119f_mvwtop()
120{
121 extern moveborder();
122 moveborder(1);
123}
124#endif /*FX_MVWTOP*/
125
126#if FX_MVWBOT
127/* EFUN: "Move to Window Bottom" (not EMACS) - from IMAGEN config */
128f_mvwbot()
129{
130 extern moveborder();
131 moveborder(0);
132}
133#endif /*FX_MVWBOT*/
134
135
136
137
138#if FX_NSCREEN || FX_PSCREEN || FX_OTHNSCREEN
139/* Move to new loc by N screenfuls.
140 * If moving downward, keep bottom 2 lines of current screen on top of next.
141 * If moving up, keep top 2 lines of current screen on bottom of next.
142 */
143d_screen(rep)
144int rep;
145{
146 register int i;
147 register struct window *w;
148 chroff newdot;
149
150 w = cur_win;
151 if((i = w->w_ht - 2) <= 0) /* Just-in-case check */
152 i = 1;
153 if((i *= rep) == 0)
154 return;
155 d_fixcur(); /* Ensure window fixed up */
156 e_go(w->w_topldot); /* Start at top of screen */
157 d_fgoloff(i);
158
159 /* Find where we are now, and make that the new top of window. */
160 if((newdot = e_dot()) != e_blen()) /* If not at EOF, */
161 w->w_topldot = newdot; /* set new top of window! */
162 else w->w_topldot = 0; /* Else let fix_wind select top. */
163
164 e_setcur(); /* Ensure cur_dot set to real loc */
165#if IMAGEN
166 redp(RD_WINRES|RD_REDO); /* HINT: just repaint screen */
167#else
168 redp(RD_FIXWIN|RD_MOVE);
169#endif /*-IMAGEN*/
170}
171#endif /*FX_NSCREEN || FX_PSCREEN || FX_OTHNSCREEN*/
172
173
174#if FX_SCUPWIND || FX_SCDNWIND /* If want scroll-window function */
175scroll_win(n)
176register int n;
177{ register struct window *w = cur_win;
178 chroff savdot;
179
180 if (n == 0) return;
181 d_fixcur(); /* Ensure screen vars for win all set up */
182 e_go(w->w_topldot); /* Go to top of current window */
183 d_fgoloff(n); /* Move given # of display lines */
184 w->w_topldot = e_dot(); /* Set new top of window */
185 redp(RD_FIXWIN); /* Say new window needs fixing up */
186
187 /* Now adjust position of current dot so it is still within window */
188 if (n > 0)
189 { /* Moving screen text "up" (win down) */
190 if (cur_dot < w->w_topldot) /* See if scrolled off top */
191 e_setcur(); /* yes, make dot be win top */
192 }
193 else { /* Moving screen text "down" (win up) */
194 savdot = cur_dot; /* Save since must temporarily */
195 e_setcur(); /* set current dot within window, */
196 d_fixcur(); /* so screen can be fixed up. */
197 if (inwinp(w, savdot)) /* Now see if old dot in new win */
198 cur_dot = savdot; /* Yes, just restore it! */
199 else /* No, make it beg of bottom line. */
200 cur_dot = scr[w->w_pos + w->w_ht - 1]->sl_boff;
201 }
202 e_gocur(); /* Make current pos be cur_dot */
203}
204#endif /* FX_SC%%WIND */
205
206#if FX_MVWTOP || FX_MVWBOT /* Guts for above two functions */
207static
208moveborder(top)
209int top;
210{
211 d_fixcur(); /* Ensure current win screen image fixed up */
212 e_gosetcur(top ? cur_win->w_topldot
213 : scr[cur_win->w_pos + cur_win->w_ht - 1]->sl_boff);
214
215 redp(RD_MOVE); /* Should only be cursor adjustment */
216}
217#endif /*FX_MVW%%%*/
218
219
220/* Given a line and a position in that line, return the xpos.
221 * NOTE CAREFULLY that when line extends over several screen lines,
222 * the value returned is the screen X position even though it
223 * may be some lines down from the start of the logical line!
224 * Also note this won't work very well if tabs exist on the extra
225 * lines. This rtn should not be used for cursor positioning.
226 * Also note: d_ncols() will never return -1 meaning EOL because the
227 * setup guarantees there is no EOL within the range checked.
228 */
229d_curind() /* Find current indentation */
230{ indtion(e_dot());
231}
232indtion(lin)
233chroff lin;
234{ register int i, col;
235 chroff savdot;
236 chroff nchars;
237
238 savdot = e_dot(); /* Save current position */
239 e_go(lin); /* Go to line caller wants */
240 e_gobol(); /* Go to its beginning */
241 col = 0; /* Start at left margin */
242 if((nchars = lin - e_dot()) > 0)
243 do {
244 if(nchars < (i = scr_wd0))
245 i = nchars;
246 if((col = d_ncols(i, col)) < 0) /* Hit edge of screen? */
247 col = 0; /* Reset to left margin */
248 } while((nchars -= i) > 0);
249 e_go(savdot); /* Restore current position */
250 return(col);
251}
252
253/* ININDEX - How many positions in lin must we go to get to xpos?
254 * Returns -1 if can't be done. Assumes "lin" is at beginning of a line!
255 */
256
257inindex (lin, xpos)
258chroff lin;
259int xpos;
260{ register int col, x;
261 chroff savdot;
262 char tmp[MAXLINE+MAXCHAR];
263 extern int sctreol; /* From EEDISP */
264
265 if((x = xpos) <= 0) return(0);
266 if(x >= MAXLINE) return(-1); /* ?!? */
267 col = 0;
268 savdot = e_dot();
269 e_go(lin); /* Assumes this is start of line */
270 col = sctrin(tmp, x, 0); /* Translate from sb_getc input */
271 if((col - x) >= 0) /* Exact count-out or past it? */
272 { x = e_dot() - lin; /* Yup, win. */
273 if (sctreol > 0) /* Did we hit (and include) EOL? */
274#if FX_EOLMODE /* If so, back up over the EOL. */
275 x -= eolcrlf(cur_buf) ? 2 : 1;
276#else
277 --x;
278#endif
279 }
280 else x = -1; /* Nope, EOL or EOF hit too soon. */
281 e_go(savdot);
282 return(x);
283}
284
285
286/*
287 * D_ ROUTINES - display-relative functions. Similar to E_, but
288 * a "line" is defined as one line of the screen rather than
289 * as a logical text line. Also, for efficiency reasons
290 * arguments are given saying how many lines to hack.
291 */
292
293d_gopl() { return(d_goloff(-1)); }
294d_gonl() { return(d_goloff( 1)); }
295
296/* D_GOLOFF(i) - Go to beginning of a display line
297 * D_FGOLOFF(i) - ditto, but assumes screen image of window already fixed up.
298 * i - # of lines offset. Negative moves up, positive down.
299 * Zero arg goes to beginning of current display line.
300 * Side effects: screen image of window is fixed up at
301 * start of routine, but is NOT updated by the move to new location.
302 */
303d_goloff(cnt)
304int cnt;
305{ d_fixcur();
306 d_fgoloff(cnt); /* Now can invoke fixed-up fast version */
307}
308d_fgoloff(cnt)
309register int cnt;
310{ register int y;
311 struct scr_line l;
312 char line[MAXLINE+MAXCHAR];
313 int top, bot;
314
315 /* Find current position in window, since can save time
316 * by using stuff already in fixed-up screen image.
317 */
318 if((y = d_line(e_dot())) < 0) /* Get current Y position */
319 {
320 errbarf("Dot out of window");
321 y = 0;
322 }
323 top = cur_win->w_pos; /* 1st line of window */
324 bot = top + cur_win->w_ht; /* 1st line not in window */
325 l.sl_boff = scr[y]->sl_boff;
326 l.sl_nlin = &line[0];
327 l.sl_cont = 0;
328
329 if(cnt > 0) goto down;
330
331 /* Go upwards. This is hairy because we want to be clever about
332 * huge logical lines -- avoid going all the way back to BOL.
333 */
334 if((y+cnt) >= top) /* Fits? */
335 goto onscr; /* Hurray, hack it! */
336 cnt += y - top; /* Sigh, find # lines to skip */
337 y = top;
338 l.sl_boff = scr[y]->sl_boff;
339 e_go(l.sl_boff);
340
341 /* Okay, here's the hairy part. Must go backwards from top
342 * line; if no EOL within scr_wid*cnt chars, then simply assume one is
343 * seen.
344 */
345 cnt = -cnt;
346 d_backup(cnt);
347 return; /* Really should re-adjust stuff, but... */
348
349 /* Go downwards. Not too bad... */
350down:
351 if((y+cnt) <= bot) /* Fits? */
352 goto onscr; /* Hurray, hack it! */
353 cnt -= bot - y; /* Sigh, find # lines can skip */
354 y = bot - 1;
355 l.sl_boff = scr[y]->sl_boff + scr[y]->sl_len;
356 if(y > top
357 && (l.sl_cont = scr[y-1]->sl_cont))
358 l.sl_line = scr[y-1]->sl_line;
359 e_go(l.sl_boff);
360
361 do {
362 fix_line(&l,&l);
363 } while(--cnt > 0 && l.sl_len);
364 return;
365
366onscr: if((y += cnt) >= bot)
367 { --y;
368 e_go(scr[y]->sl_boff + scr[y]->sl_len);
369 }
370 else e_go(scr[y]->sl_boff);
371}
372
373/* D_FIXCUR() - Ensure current window is fixed up, with
374 * current location (not necessarily cur_dot)!
375 * Ensure cur_dot reflects real loc so that fix_wind will work,
376 * and always call fix_wind to ensure that screen image vars
377 * are set properly. Note any active redisplay flags must be carried
378 * on into window redisplay flags, so fix_wind will notice them.
379 */
380d_fixcur()
381{ register struct window *w;
382 chroff savedot;
383
384 w = cur_win;
385 savedot = cur_dot;
386 e_setcur();
387 w->w_redp |= rd_type&RDS_WINFLGS;
388 fix_wind(w); /* Always ensure window is set up! */
389 redp(w->w_redp); /* Add back new flags */
390 rd_type &= ~RDS_DOFIX; /* and flush fix-invoking ones */
391 cur_dot = savedot; /* Restore cur_dot, no longer hacked. */
392}
393
394
395d_backup(nlin) /* Try to back up by nlin screen lines */
396int nlin;
397{ register int cnt, n, c;
398 int eolstop;
399
400 if((cnt = nlin+1) <= 0) return;
401 c = 0;
402 do
403 { n = scr_wid;
404 eolstop = 0; /* Not yet stopped at EOL */
405 do { if((c = e_rgetc()) == EOF)
406 return;
407 if(c == LF)
408 {
409#if FX_EOLMODE
410 if(eolcrlf(cur_buf))
411 { if((c = e_rgetc()) == CR)
412 { eolstop++;
413 break;
414 }
415 if(c != EOF)
416 e_getc();
417 }
418 else
419#endif
420 { eolstop++;
421 break;
422 }
423 }
424 } while(--n);
425 } while(--cnt);
426 if(eolstop)
427 {
428#if FX_EOLMODE
429 if(eolcrlf(cur_buf)) e_getc(); /* Skip back over CR */
430#endif
431 e_getc(); /* Skip back over LF */
432 }
433
434 /* At this point, dot is guaranteed to be less than goal,
435 * which is the important thing for fix_wind, which can handle
436 * things okay if dot is off bottom of window.
437 */
438 return(1); /* Say always test result */
439}
Note: See TracBrowser for help on using the repository browser.