source: trunk/minix/commands/yap/display.c@ 15

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

Minix 3.1.2a

File size: 10.9 KB
Line 
1/* Copyright (c) 1985 Ceriel J.H. Jacobs */
2
3# ifndef lint
4static char rcsid[] = "$Header: /cvsup/minix/src/commands/yap/display.c,v 1.1.1.1 2005/04/21 14:55:39 beng Exp $";
5# endif
6
7# define _DISPLAY_
8
9# include "in_all.h"
10# include "display.h"
11# include "assert.h"
12# include "machine.h"
13# include "term.h"
14# include "output.h"
15# include "options.h"
16# include "process.h"
17# include "getline.h"
18# include "main.h"
19
20STATIC char * do_line();
21
22/*
23 * Fill n lines of the screen, each with "str".
24 */
25
26STATIC VOID
27fillscr(n,str) char *str; int n; {
28
29 while (n-- > 0) {
30 putline(str);
31 }
32}
33
34/*
35 * Skip "n" screenlines of line "p", and return what's left of it.
36 */
37
38STATIC char *
39skiplines(p,n) char *p; int n; {
40
41 while (n-- > 0) {
42 p = do_line(p,0);
43 scr_info.currentpos--;
44 }
45 return p;
46}
47
48/*
49 * Redraw screen.
50 * "n" = 1 if it is a real redraw, 0 if one page must be displayed.
51 * It is also called when yap receives a stop signal.
52 */
53
54VOID
55redraw(n) int n; {
56 register struct scr_info *p = &scr_info;
57 register int i;
58
59 i = pagesize;
60 if (n && p->currentpos) {
61 i = p->currentpos;
62 }
63 (VOID) display(p->firstline,p->nf,i,1);
64}
65
66/*
67 * Compute return value for the routines "display" and "scrollf".
68 * This return value indicates wether we are at the end of file
69 * or at the start, or both.
70 * "s" contains that part of the last line that was not displayed.
71 */
72
73STATIC int
74compretval(s) char *s; {
75 register int i;
76 register struct scr_info *p = &scr_info;
77
78 i = 0;
79 if (!s || (!*s && !getline(p->lastline+1, 1))) {
80 i = EOFILE;
81 }
82 if (p->firstline == 1 && !p->nf) {
83 i |= START;
84 }
85 status = i;
86 return i;
87}
88
89/*
90 * Display nlines, starting at line n, not displaying the first
91 * nd screenlines of n.
92 * If reallydispl = 0, the actual displaying is not performed,
93 * only the computing associated with it is done.
94 */
95
96int
97display(n,nd,nlines,reallydispl)
98 long n; int nd; register int nlines; int reallydispl; {
99
100 register struct scr_info *s = &scr_info;
101 register char *p; /* pointer to line to be displayed */
102
103 if (startcomm) { /* No displaying on a command from the
104 * yap command line. In this case, displaying
105 * will be done after executing the command,
106 * by a redraw.
107 */
108 reallydispl = 0;
109 }
110 if (!n) {
111 n = 1L;
112 nd = 0;
113 }
114 if (reallydispl) { /* move cursor to starting point */
115 if (stupid) {
116 putline(currentfile);
117 putline(", line ");
118 prnum(n);
119 nlines--;
120 }
121 if (cflag) {
122 putline("\r\n");
123 }
124 else {
125 home();
126 clrscreen();
127 }
128 }
129 /*
130 * Now, do computations and display
131 */
132 s->currentpos = 0;
133 s->nf = nd;
134 s->head = s->tail;
135 s->tail->cnt = 0;
136 s->tail->line = n;
137 p = skiplines(getline(n,1),nd);
138 while (nlines && p) {
139 /*
140 * While there is room,
141 * and there is something left to display ...
142 */
143 (s->tail->cnt)++;
144 nlines--;
145 if (*(p = do_line(p,reallydispl)) == '\0') {
146 /*
147 * File-line finished, get next one ...
148 */
149 p = getline(++n,1);
150 if (nlines && p) {
151 s->tail = s->tail->next;
152 s->tail->cnt = 0;
153 s->tail->line = n;
154 }
155 }
156 }
157 if (!stupid) {
158 s->currentpos += nlines;
159 if (reallydispl) {
160 fillscr(nlines, "~\r\n");
161 fillscr(maxpagesize - s->currentpos, "\r\n");
162 }
163 }
164 return compretval(p);
165}
166
167/*
168 * Scroll forwards n lines.
169 */
170
171int
172scrollf(n,reallydispl) int n; int reallydispl; {
173
174 register struct scr_info *s = &scr_info;
175 register char *p;
176 register long ll;
177 register int i;
178
179 /*
180 * First, find out how many screenlines of the last line were already
181 * on the screen, and possibly above it.
182 */
183
184 if (n <= 0 || (status & EOFILE)) return status;
185 if (startcomm) reallydispl = 0;
186 /*
187 * Find out where to begin displaying
188 */
189 i = s->tail->cnt;
190 if ((ll = s->lastline) == s->firstline) i += s->nf;
191 p = skiplines(getline(ll, 1), i);
192 /*
193 * Now, place the cursor at the first free line
194 */
195 if (reallydispl && !stupid) {
196 clrbline();
197 mgoto(s->currentpos);
198 }
199 /*
200 * Now display lines, keeping track of which lines are on the screen.
201 */
202 while (n-- > 0) { /* There are still rows to be displayed */
203 if (!*p) { /* End of line, get next one */
204 if (!(p = getline(++ll, 1))) {
205 /*
206 * No lines left. At end of file
207 */
208 break;
209 }
210 s->tail = s->tail->next;
211 s->tail->cnt = 0;
212 s->tail->line = ll;
213 }
214 if (s->currentpos >= maxpagesize) {
215 /*
216 * No room, delete first screen-line
217 */
218 s->currentpos--;
219 s->nf++;
220 if (--(s->head->cnt) == 0) {
221 /*
222 * The first file-line on the screen is wiped
223 * out completely; update administration
224 * accordingly.
225 */
226 s->nf = 0;
227 s->head = s->head->next;
228 assert(s->head->cnt > 0);
229 }
230 }
231 s->tail->cnt++;
232 p = do_line(p, reallydispl);
233 }
234 return compretval(p);
235}
236
237/*
238 * Scroll back n lines
239 */
240
241int
242scrollb(n, reallydispl) int n, reallydispl; {
243
244 register struct scr_info *s = &scr_info;
245 register char *p; /* Holds string to be displayed */
246 register int i;
247 register int count;
248 register long ln; /* a line number */
249 register int nodispl;
250 int cannotscroll; /* stupid or no insert-line */
251
252 /*
253 * First, find out where to start
254 */
255 if ((count = n) <= 0 || (status & START)) return status;
256 if (startcomm) reallydispl = 0;
257 cannotscroll = stupid || (!*AL && !*SR);
258 ln = s->firstline;
259 nodispl = s->nf;
260 while (count) { /* While scrolling back ... */
261 if (i = nodispl) {
262 /*
263 * There were screen-lines of s->firstline that were not
264 * displayed.
265 * We can use them now, but only "count" of them.
266 */
267 if (i > count) i = count;
268 s->currentpos += i;
269 nodispl -= i;
270 count -= i;
271 }
272 else { /* Get previous line */
273 if (ln == 1) break; /* isn't there ... */
274 p = getline(--ln, 1);
275 /*
276 * Make it the first line of the screen and compute
277 * how many screenlines it takes. These lines are not
278 * displayed, but nodispl is set to this count, so
279 * that it will be nonzero next time around
280 */
281 nodispl = 0;
282 do { /* Find out how many screenlines */
283 nodispl++;
284 p = skiplines(p, 1);
285 } while (*p);
286 }
287 }
288 n -= count;
289 if ((i = s->currentpos) > maxpagesize) i = maxpagesize;
290 if (reallydispl && hardcopy) i = n;
291 /*
292 * Now that we know where to start, we can use "display" to do the
293 * rest of the computing for us, and maybe even the displaying ...
294 */
295 i = display(ln,
296 nodispl,
297 i,
298 reallydispl && cannotscroll);
299 if (cannotscroll || !reallydispl) {
300 /*
301 * Yes, "display" did the displaying, or we did'nt have to
302 * display at all.
303 * I like it, but the user obviously does not.
304 * Let him buy another (smarter) terminal ...
305 */
306 return i;
307 }
308 /*
309 * Now, all we have to do is the displaying. And we are dealing with
310 * a smart terminal (it can insert lines or scroll back).
311 */
312 home();
313 /*
314 * Insert lines all at once
315 */
316 for (i = n; i; i--) {
317 if (DB && *CE) {
318 /*
319 * Grumble..., terminal retains lines below, so we have
320 * to clear the lines that we push off the screen
321 */
322 clrbline();
323 home();
324 }
325 if (*SR) {
326 scrollreverse();
327 }
328 else {
329# ifdef VT100_PATCH
330 insert_line(0);
331# else
332 insert_line();
333# endif
334 }
335 }
336 p = skiplines(getline(ln = s->firstline, 1), s->nf);
337 for (i = 0; i < n; i++) {
338 p = do_line(p,1);
339 s->currentpos--;
340 if (!*p) {
341 p = getline(++ln, 1);
342 }
343 }
344 return count;
345}
346
347/*
348 * Process a line.
349 * If reallydispl > 0 then display it.
350 */
351
352STATIC char *
353do_line(str, reallydispl) register char *str; int reallydispl; {
354
355 char buf[1024];
356 register char *p = buf;
357 register int pos = COLS;
358 register int c;
359 register int c1;
360 register int do_ul = 0, do_hl = 0;
361 int lastmode = 0, lasthlmode = 0;
362 int c2;
363
364 while (*str && pos > 0) {
365 if (*str < ' ' && (c1 = match(str,&c2,sppat)) > 0) {
366 /*
367 * We found a string that matches, and thus must be
368 * echoed literally
369 */
370 if ((pos - c2) <= 0) {
371 /*
372 * It did not fit
373 */
374 break;
375 }
376 pos -= c2;
377 str += c1;
378 if (reallydispl) {
379 c = *str;
380 *p = *str = 0;
381 cputline(p = buf);
382 putline(str - c1);
383 *str = c;
384 }
385 continue;
386 }
387 c = *str++;
388 do_hl = 0;
389 if (*str == '\b' && *(str+1) != 0
390 && (c != '_' || *(str+2) == '\b')) {
391 while (*str == '\b' && *(str+1) != 0) {
392 str++;
393 c = *str++;
394 do_hl = 1;
395 }
396 }
397 do_ul = 1;
398 /*
399 * Find underline sequences ...
400 */
401 if (c == '_' && *str == '\b') {
402 str++;
403 c = *str++;
404 }
405 else {
406 if (*str == '\b' && *(str+1) == '_') {
407 str += 2;
408 }
409 else do_ul = 0;
410 }
411 if (reallydispl && do_hl != lasthlmode) {
412 *p = 0;
413 cputline(p = buf);
414 if (do_hl) bold();
415 else end_bold();
416 }
417 lasthlmode = do_hl;
418 if (reallydispl && do_ul != lastmode) {
419 *p = 0;
420 cputline(p = buf);
421 if (do_ul) underline();
422 else end_underline();
423 }
424 lastmode = do_ul;
425 *p++ = c;
426 if (c >= ' ' && c < 0177) {
427 pos--;
428 if (reallydispl && do_ul && *UC && pos > 0) {
429 /*
430 * Underlining apparently is done one
431 * character at a time.
432 */
433 *p = 0;
434 cputline(p = buf);
435 backspace();
436 underchar();
437 }
438 continue;
439 }
440 if (c == '\t') {
441 p--;
442 c1 = 8 - ((COLS - pos) & 07);
443 /*
444 * Actually, if COLS is a multiple of 8, this can be
445 * simplified to
446 * c1 = pos & 07;
447 * But of course, we don't know that for sure.
448 */
449 if (pos - c1 < 0) break;
450 pos -= c1;
451 if (reallydispl) {
452 if (expandtabs) {
453 /*
454 * Expand tabs. We cannot let the
455 * kernel take care of this
456 * for two reasons:
457 * 1. There can be tabs in cursor
458 * addressing strings,
459 * 2. We probably do it better.
460 */
461 while (c1-- > 0) {
462 *p++ = ' ';
463 }
464 }
465 else {
466 *p = 0;
467 cputline(p = buf);
468 givetab();
469 }
470 }
471 continue;
472 }
473 /*
474 * Now we have a control character, which takes two positions
475 */
476 if (pos <= 1) {
477 p--;
478 break;
479 }
480 pos -= 2;
481 }
482 if (reallydispl) {
483 *p = 0;
484 cputline(buf);
485 if (pos > 0 || (pos <= 0 && (!AM || XN))) {
486 putline("\r\n");
487 }
488 /*
489 * The next should be here! I.e. it may not be before printing
490 * the newline. This has to do with XN. We don't know exactly
491 * WHEN the terminal will stop ignoring the newline.
492 * I have for example a terminal (Ampex a230) that will
493 * continue to ignore the newline after a clear to end of line
494 * sequence, but not after an end_underline sequence.
495 */
496 if (do_ul) {
497 end_underline();
498 }
499 if (do_hl) {
500 standend();
501 }
502 }
503 scr_info.currentpos++;
504 return str;
505}
506
507/* ARGSUSED */
508int
509setmark(cnt) long cnt; { /* Set a mark on the current page */
510 register struct scr_info *p = &scr_info;
511
512 p->savfirst = p->firstline;
513 p->savnf = p->nf;
514}
515
516/* ARGSUSED */
517int
518tomark(cnt) long cnt; { /* Go to the mark */
519 register struct scr_info *p = &scr_info;
520
521 (VOID) display(p->savfirst,p->savnf,pagesize,1);
522}
523
524/* ARGSUSED */
525int
526exgmark(cnt) long cnt; { /* Exchange mark and current page */
527 register struct scr_info *p = &scr_info;
528 register long svfirst;
529 register int svnf;
530
531 svfirst = p->firstline;
532 svnf = p->nf;
533 tomark(0L);
534 p->savfirst = svfirst;
535 p->savnf = svnf;
536}
537
538VOID
539d_clean() { /* Clean up */
540 register struct scr_info *p = &scr_info;
541
542 p->savnf = 0;
543 p->savfirst = 0;
544 p->head = p->tail;
545 p->head->line = 0;
546 p->currentpos = 0;
547}
Note: See TracBrowser for help on using the repository browser.