source: trunk/minix/commands/elvis/redraw.c@ 10

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

Minix 3.1.2a

File size: 25.0 KB
RevLine 
[9]1/* redraw.c */
2
3/* Author:
4 * Steve Kirkendall
5 * 14407 SW Teal Blvd. #C
6 * Beaverton, OR 97005
7 * kirkenda@cs.pdx.edu
8 */
9
10
11/* This file contains functions that draw text on the screen. The major entry
12 * points are:
13 * redrawrange() - called from modify.c to give hints about what parts
14 * of the screen need to be redrawn.
15 * redraw() - redraws the screen (or part of it) and positions
16 * the cursor where it belongs.
17 * idx2col() - converts a markidx() value to a logical column number.
18 */
19
20#include "config.h"
21#include "vi.h"
22
23/* This variable contains the line number that smartdrawtext() knows best */
24static long smartlno;
25
26/* This function remembers where changes were made, so that the screen can be
27 * redraw in a more efficient manner.
28 */
29static long redrawafter; /* line# of first line that must be redrawn */
30static long preredraw; /* line# of last line changed, before change */
31static long postredraw; /* line# of last line changed, after change */
32static int mustredraw; /* boolean: anything forcing a screen update? */
33void redrawrange(after, pre, post)
34 long after; /* lower bound of redrawafter */
35 long pre; /* upper bound of preredraw */
36 long post; /* upper bound of postredraw */
37{
38 if (after == redrawafter)
39 {
40 /* multiple insertions/deletions at the same place -- combine
41 * them
42 */
43 preredraw -= (post - pre);
44 if (postredraw < post)
45 {
46 preredraw += (post - postredraw);
47 postredraw = post;
48 }
49 if (redrawafter > preredraw)
50 {
51 redrawafter = preredraw;
52 }
53 if (redrawafter < 1L)
54 {
55 redrawafter = 0L;
56 preredraw = postredraw = INFINITY;
57 }
58 }
59 else if (postredraw > 0L)
60 {
61 /* multiple changes in different places -- redraw everything
62 * after "after".
63 */
64 postredraw = preredraw = INFINITY;
65 if (after < redrawafter)
66 redrawafter = after;
67 }
68 else
69 {
70 /* first change */
71 redrawafter = after;
72 preredraw = pre;
73 postredraw = post;
74 }
75 mustredraw = TRUE;
76}
77
78
79#ifndef NO_CHARATTR
80/* see if a given line uses character attribute strings */
81static int hasattr(lno, text)
82 long lno; /* the line# of the cursor */
83 REG char *text; /* the text of the line, from fetchline */
84{
85 static long plno; /* previous line number */
86 static long chgs; /* previous value of changes counter */
87 static int panswer;/* previous answer */
88 char *scan;
89
90 /* if charattr is off, then the answer is "no, it doesn't" */
91 if (!*o_charattr)
92 {
93 chgs = 0; /* <- forces us to check if charattr is later set */
94 return FALSE;
95 }
96
97 /* if we already know the answer, return it... */
98 if (lno == plno && chgs == changes)
99 {
100 return panswer;
101 }
102
103 /* get the line & look for "\fX" */
104 if (!text[0] || !text[1] || !text[2])
105 {
106 panswer = FALSE;
107 }
108 else
109 {
110 for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++)
111 {
112 }
113 panswer = (scan[2] != '\0');
114 }
115
116 /* save the results */
117 plno = lno;
118 chgs = changes;
119
120 /* return the results */
121 return panswer;
122}
123#endif
124
125
126#ifndef NO_VISIBLE
127/* This function checks to make sure that the correct lines are shown in
128 * reverse-video. This is used to handle the "v" and "V" commands.
129 */
130static long vizlow, vizhigh; /* the starting and ending lines */
131static int vizleft, vizright; /* starting & ending indicies */
132static int vizchange; /* boolean: must use stupid drawtext? */
133static void setviz(curs)
134 MARK curs;
135{
136 long newlow, newhigh;
137 long extra = 0L;
138
139 /* for now, assume the worst... */
140 vizchange = TRUE;
141
142 /* set newlow & newhigh according to V_from and cursor */
143 if (!V_from)
144 {
145 /* no lines should have reverse-video */
146 if (vizlow)
147 {
148 redrawrange(vizlow, vizhigh + 1L, vizhigh + 1L);
149 vizlow = vizhigh = 0L;
150 }
151 else
152 {
153 vizchange = FALSE;
154 }
155 return;
156 }
157
158 /* figure out which lines *SHOULD* have hilites */
159 if (V_from < curs)
160 {
161 newlow = markline(V_from);
162 newhigh = markline(curs);
163 vizleft = markidx(V_from);
164 vizright = markidx(curs) + 1;
165 }
166 else
167 {
168 newlow = markline(curs);
169 newhigh = markline(V_from);
170 vizleft = markidx(curs);
171 vizright = markidx(V_from) + 1;
172 }
173
174 /* adjust for line-mode hiliting */
175 if (V_linemd)
176 {
177 vizleft = 0;
178 vizright = BLKSIZE - 1;
179 }
180 else
181 {
182 extra = 1L;
183 }
184
185 /* arrange for the necessary lines to be redrawn */
186 if (vizlow == 0L)
187 {
188 /* just starting to redraw */
189 redrawrange(newlow, newhigh, newhigh);
190 }
191 else
192 {
193 /* Were new lines added/removed at the front? */
194 if (newlow != vizlow)
195 {
196 if (newlow < vizlow)
197 redrawrange(newlow, vizlow + extra, vizlow + extra);
198 else
199 redrawrange(vizlow, newlow + extra, newlow + extra);
200 }
201
202 /* Were new lines added/removed at the back? */
203 if (newhigh != vizhigh)
204 {
205 if (newhigh < vizhigh)
206 redrawrange(newhigh + 1L - extra, vizhigh + 1L, vizhigh + 1L);
207 else
208 redrawrange(vizhigh + 1L - extra, newhigh, newhigh);
209 }
210 }
211
212 /* remember which lines will contain hilighted text now */
213 vizlow = newlow;
214 vizhigh = newhigh;
215}
216#endif /* !NO_VISIBLE */
217
218
219/* This function converts a MARK to a column number. It doesn't automatically
220 * adjust for leftcol; that must be done by the calling function
221 */
222int idx2col(curs, text, inputting)
223 MARK curs; /* the line# & index# of the cursor */
224 REG char *text; /* the text of the line, from fetchline */
225 int inputting; /* boolean: called from input() ? */
226{
227 static MARK pcursor;/* previous cursor, for possible shortcut */
228 static MARK pcol; /* column number for pcol */
229 static long chgs; /* previous value of changes counter */
230 REG int col; /* used to count column numbers */
231 REG int idx; /* used to count down the index */
232 REG int i;
233
234 /* for now, assume we have to start counting at the left edge */
235 col = 0;
236 idx = markidx(curs);
237
238 /* if the file hasn't changed & line number is the same & it has no
239 * embedded character attribute strings, can we do shortcuts?
240 */
241 if (chgs == changes
242 && !((curs ^ pcursor) & ~(BLKSIZE - 1))
243#ifndef NO_CHARATTR
244 && !hasattr(markline(curs), text)
245#endif
246 )
247 {
248 /* no movement? */
249 if (curs == pcursor)
250 {
251 /* return the column of the char; for tabs, return its last column */
252 if (text[idx] == '\t' && !inputting && !*o_list)
253 {
254 return pcol + *o_tabstop - (pcol % *o_tabstop) - 1;
255 }
256 else
257 {
258 return pcol;
259 }
260 }
261
262 /* movement to right? */
263 if (curs > pcursor)
264 {
265 /* start counting from previous place */
266 col = pcol;
267 idx = markidx(curs) - markidx(pcursor);
268 text += markidx(pcursor);
269 }
270 }
271
272 /* count over to the char after the idx position */
273 while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */
274 {
275 if (i == '\t' && !*o_list)
276 {
277 col += *o_tabstop;
278 col -= col % *o_tabstop;
279 }
280 else if (i >= '\0' && i < ' ' || i == '\177')
281 {
282 col += 2;
283 }
284#ifndef NO_CHARATTR
285 else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
286 {
287 text += 2; /* plus one more at bottom of loop */
288 idx -= 2;
289 }
290#endif
291 else
292 {
293 col++;
294 }
295 text++;
296 idx--;
297 }
298
299 /* save stuff to speed next call */
300 pcursor = curs;
301 pcol = col;
302 chgs = changes;
303
304 /* return the column of the char; for tabs, return its last column */
305 if (*text == '\t' && !inputting && !*o_list)
306 {
307 return col + *o_tabstop - (col % *o_tabstop) - 1;
308 }
309 else
310 {
311 return col;
312 }
313}
314
315
316/* This function is similar to idx2col except that it takes care of sideways
317 * scrolling - for the given line, at least.
318 */
319int mark2phys(m, text, inputting)
320 MARK m; /* a mark to convert */
321 char *text; /* the line that m refers to */
322 int inputting; /* boolean: caled from input() ? */
323{
324 int i;
325
326 i = idx2col(m, text, inputting);
327 while (i < leftcol)
328 {
329 leftcol -= *o_sidescroll;
330 mustredraw = TRUE;
331 redrawrange(1L, INFINITY, INFINITY);
332 }
333 while (i > rightcol)
334 {
335 leftcol += *o_sidescroll;
336 mustredraw = TRUE;
337 redrawrange(1L, INFINITY, INFINITY);
338 }
339 physrow = markline(m) - topline;
340 physcol = i - leftcol;
341 if (*o_number)
342 physcol += 8;
343
344 return physcol;
345}
346
347/* This function draws a single line of text on the screen. The screen's
348 * cursor is assumed to be located at the leftmost column of the appropriate
349 * row.
350 */
351static void drawtext(text, lno, clr)
352 REG char *text; /* the text to draw */
353 long lno; /* the number of the line to draw */
354 int clr; /* boolean: do a clrtoeol? */
355{
356 REG int col; /* column number */
357 REG int i;
358 REG int tabstop; /* *o_tabstop */
359 REG int limitcol; /* leftcol or leftcol + COLS */
360 int abnormal; /* boolean: charattr != A_NORMAL? */
361#ifndef NO_VISIBLE
362 int rev; /* boolean: standout mode, too? */
363 int idx = 0;
364#endif
365 char numstr[9];
366
367 /* show the line number, if necessary */
368 if (*o_number)
369 {
370 sprintf(numstr, "%6ld |", lno);
371 qaddstr(numstr);
372 }
373
374#ifndef NO_SENTENCE
375 /* if we're hiding format lines, and this is one of them, then hide it */
376 if (*o_hideformat && *text == '.')
377 {
378 clrtoeol();
379#if OSK
380 qaddch('\l');
381#else
382 qaddch('\n');
383#endif
384 return;
385 }
386#endif
387
388 /* move some things into registers... */
389 limitcol = leftcol;
390 tabstop = *o_tabstop;
391 abnormal = FALSE;
392
393#ifndef CRUNCH
394 if (clr)
395 clrtoeol();
396#endif
397
398 /* skip stuff that was scrolled off left edge */
399 for (col = 0;
400 (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
401 text++)
402 {
403#ifndef NO_VISIBLE
404 idx++;
405#endif
406 if (i == '\t' && !*o_list)
407 {
408 col = col + tabstop - (col % tabstop);
409 }
410 else if (i >= 0 && i < ' ' || i == '\177')
411 {
412 col += 2;
413 }
414#ifndef NO_CHARATTR
415 else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
416 {
417 text += 2; /* plus one more as part of "for" loop */
418
419 /* since this attribute might carry over, we need it */
420 switch (*text)
421 {
422 case 'R':
423 case 'P':
424 attrset(A_NORMAL);
425 abnormal = FALSE;
426 break;
427
428 case 'B':
429 attrset(A_BOLD);
430 abnormal = TRUE;
431 break;
432
433 case 'U':
434 attrset(A_UNDERLINE);
435 abnormal = TRUE;
436 break;
437
438 case 'I':
439 attrset(A_ALTCHARSET);
440 abnormal = TRUE;
441 break;
442 }
443 }
444#endif
445 else
446 {
447 col++;
448 }
449 }
450
451#ifndef NO_VISIBLE
452 /* Should we start hiliting at the first char of this line? */
453 if ((lno > vizlow && lno <= vizhigh
454 || lno == vizlow && vizleft < idx)
455 && !(lno == vizhigh && vizright < idx))
456 {
457 do_VISIBLE();
458 rev = TRUE;
459 }
460#endif
461
462 /* adjust for control char that was partially visible */
463 while (col > limitcol)
464 {
465 qaddch(' ');
466 limitcol++;
467 }
468
469 /* now for the visible characters */
470 limitcol = leftcol + COLS;
471 if (*o_number)
472 limitcol -= 8;
473 for (; (i = *text) && col < limitcol; text++)
474 {
475#ifndef NO_VISIBLE
476 /* maybe turn hilite on/off in the middle of the line */
477 if (lno == vizlow && vizleft == idx)
478 {
479 do_VISIBLE();
480 rev = TRUE;
481 }
482 if (lno == vizhigh && vizright == idx)
483 {
484 do_SE();
485 rev = FALSE;
486 }
487 idx++;
488
489 /* if hiliting, never emit physical tabs */
490 if (rev && i == '\t' && !*o_list)
491 {
492 i = col + tabstop - (col % tabstop);
493 do
494 {
495 qaddch(' ');
496 col++;
497 } while (col < i);
498 }
499 else
500#endif /* !NO_VISIBLE */
501 if (i == '\t' && !*o_list)
502 {
503 i = col + tabstop - (col % tabstop);
504 if (i < limitcol)
505 {
506#ifdef CRUNCH
507 if (!clr && has_PT && !((i - leftcol) & 7))
508#else
509 if (has_PT && !((i - leftcol) & 7))
510#endif
511 {
512 do
513 {
514 qaddch('\t');
515 col += 8; /* not exact! */
516 } while (col < i);
517 col = i; /* NOW it is exact */
518 }
519 else
520 {
521 do
522 {
523 qaddch(' ');
524 col++;
525 } while (col < i);
526 }
527 }
528 else /* tab ending after screen? next line! */
529 {
530 col = limitcol;
531 if (has_AM)
532 {
533 addch('\n'); /* GB */
534 }
535 }
536 }
537 else if (i >= 0 && i < ' ' || i == '\177')
538 {
539 col += 2;
540 qaddch('^');
541 if (col <= limitcol)
542 {
543 qaddch(i ^ '@');
544 }
545 }
546#ifndef NO_CHARATTR
547 else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
548 {
549 text += 2; /* plus one more as part of "for" loop */
550 switch (*text)
551 {
552 case 'R':
553 case 'P':
554 attrset(A_NORMAL);
555 abnormal = FALSE;
556 break;
557
558 case 'B':
559 attrset(A_BOLD);
560 abnormal = TRUE;
561 break;
562
563 case 'U':
564 attrset(A_UNDERLINE);
565 abnormal = TRUE;
566 break;
567
568 case 'I':
569 attrset(A_ALTCHARSET);
570 abnormal = TRUE;
571 break;
572 }
573 }
574#endif
575 else
576 {
577 col++;
578 qaddch(i);
579 }
580 }
581
582 /* get ready for the next line */
583#ifndef NO_CHARATTR
584 if (abnormal)
585 {
586 attrset(A_NORMAL);
587 }
588#endif
589 if (*o_list && col < limitcol)
590 {
591 qaddch('$');
592 col++;
593 }
594
595#ifndef NO_VISIBLE
596 /* did we hilite this whole line? If so, STOP! */
597 if (rev)
598 {
599 do_SE();
600 }
601#endif
602
603#ifdef CRUNCH
604 if (clr && col < limitcol)
605 {
606 clrtoeol();
607 }
608#endif
609 if (!has_AM || col < limitcol)
610 {
611 addch('\n');
612 }
613
614 wqrefresh();
615}
616
617
618#ifndef CRUNCH
619static void nudgecursor(same, scan, new, lno)
620 int same; /* number of chars to be skipped over */
621 char *scan; /* where the same chars end */
622 char *new; /* where the visible part of the line starts */
623 long lno; /* line number of this line */
624{
625 int col;
626
627 if (same > 0)
628 {
629 if (same < 5)
630 {
631 /* move the cursor by overwriting */
632 while (same > 0)
633 {
634 qaddch(scan[-same]);
635 same--;
636 }
637 }
638 else
639 {
640 /* move the cursor by calling move() */
641 col = (int)(scan - new);
642 if (*o_number)
643 col += 8;
644 move((int)(lno - topline), col);
645 }
646 }
647}
648#endif /* not CRUNCH */
649
650/* This function draws a single line of text on the screen, possibly with
651 * some cursor optimization. The cursor is repositioned before drawing
652 * begins, so its position before doesn't really matter.
653 */
654static void smartdrawtext(text, lno, showit)
655 REG char *text; /* the text to draw */
656 long lno; /* line number of the text */
657 int showit; /* boolean: output line? (else just remember it) */
658{
659#ifdef CRUNCH
660 move((int)(lno - topline), 0);
661 if (showit)
662 {
663 drawtext(text, lno, TRUE);
664 }
665#else /* not CRUNCH */
666 static char old[256]; /* how the line looked last time */
667 char new[256]; /* how it looks now */
668 char *build; /* used to put chars into new[] */
669 char *scan; /* used for moving thru new[] or old[] */
670 char *end; /* last non-blank changed char */
671 char *shift; /* used to insert/delete chars */
672 int same; /* length of a run of unchanged chars */
673 int limitcol;
674 int col;
675 int i;
676 char numstr[9];
677
678# ifndef NO_CHARATTR
679 /* if this line has attributes, do it the dumb way instead */
680 if (hasattr(lno, text))
681 {
682 move((int)(lno - topline), 0);
683 drawtext(text, lno, TRUE);
684 return;
685 }
686# endif
687# ifndef NO_SENTENCE
688 /* if this line is a format line, & we're hiding format lines, then
689 * let the dumb drawtext() function handle it
690 */
691 if (*o_hideformat && *text == '.')
692 {
693 move((int)(lno - topline), 0);
694 drawtext(text, lno, TRUE);
695 return;
696 }
697# endif
698# ifndef NO_VISIBLE
699 if (vizchange)
700 {
701 move((int)(lno - topline), 0);
702 drawtext(text, lno, TRUE);
703 smartlno = 0L;
704 return;
705 }
706# endif
707
708 /* skip stuff that was scrolled off left edge */
709 limitcol = leftcol;
710 for (col = 0;
711 (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
712 text++)
713 {
714 if (i == '\t' && !*o_list)
715 {
716 col = col + *o_tabstop - (col % *o_tabstop);
717 }
718 else if (i >= 0 && i < ' ' || i == '\177')
719 {
720 col += 2;
721 }
722 else
723 {
724 col++;
725 }
726 }
727
728 /* adjust for control char that was partially visible */
729 build = new;
730 while (col > limitcol)
731 {
732 *build++ = ' ';
733 limitcol++;
734 }
735
736 /* now for the visible characters */
737 limitcol = leftcol + COLS;
738 if (*o_number)
739 limitcol -= 8;
740 for (; (i = *text) && col < limitcol; text++)
741 {
742 if (i == '\t' && !*o_list)
743 {
744 i = col + *o_tabstop - (col % *o_tabstop);
745 while (col < i && col < limitcol)
746 {
747 *build++ = ' ';
748 col++;
749 }
750 }
751 else if (i >= 0 && i < ' ' || i == '\177')
752 {
753 col += 2;
754 *build++ = '^';
755 if (col <= limitcol)
756 {
757 *build++ = (i ^ '@');
758 }
759 }
760 else
761 {
762 col++;
763 *build++ = i;
764 }
765 }
766 if (col < limitcol && *o_list)
767 {
768 *build++ = '$';
769 col++;
770 }
771 end = build;
772 while (col < limitcol)
773 {
774 *build++ = ' ';
775 col++;
776 }
777
778 /* if we're just supposed to remember this line, then remember it */
779 if (!showit)
780 {
781 smartlno = lno;
782 strncpy(old, new, COLS);
783 return;
784 }
785
786 /* locate the last non-blank character */
787 while (end > new && end[-1] == ' ')
788 {
789 end--;
790 }
791
792 /* can we optimize the displaying of this line? */
793 if (lno != smartlno)
794 {
795 /* nope, can't optimize - different line */
796 move((int)(lno - topline), 0);
797
798 /* show the line number, if necessary */
799 if (*o_number)
800 {
801 sprintf(numstr, "%6ld |", lno);
802 qaddstr(numstr);
803 }
804
805 /* show the new line */
806 for (scan = new, build = old; scan < end; )
807 {
808 qaddch(*scan);
809 *build++ = *scan++;
810 }
811 if (end < new + COLS - (*o_number ? 8 : 0))
812 {
813 clrtoeol();
814 while (build < old + COLS)
815 {
816 *build++ = ' ';
817 }
818 }
819 smartlno = lno;
820 return;
821 }
822
823 /* skip any initial unchanged characters */
824 for (scan = new, build = old; scan < end && *scan == *build; scan++, build++)
825 {
826 }
827 i = (scan - new);
828 if (*o_number)
829 i += 8;
830 move((int)(lno - topline), i);
831
832 /* The in-between characters must be changed */
833 same = 0;
834 while (scan < end)
835 {
836 /* is this character a match? */
837 if (scan[0] == build[0])
838 {
839 same++;
840 }
841 else /* do we want to insert? */
842 if (scan < end - 1 && scan[1] == build[0] && (has_IC || has_IM))
843 {
844 nudgecursor(same, scan, new, lno);
845 same = 0;
846
847 insch(*scan);
848 for (shift = old + COLS; --shift > build; )
849 {
850 shift[0] = shift[-1];
851 }
852 *build = *scan;
853 }
854 else /* do we want to delete? */
855 if (build < old + COLS - 1 && scan[0] == build[1] && has_DC)
856 {
857 nudgecursor(same, scan, new, lno);
858 same = 0;
859
860 delch();
861 same++;
862 for (shift = build; shift < old + COLS - 1; shift++)
863 {
864 shift[0] = shift[1];
865 }
866 if (*o_number)
867 shift -= 8;
868 *shift = ' ';
869 }
870 else /* we must overwrite */
871 {
872 nudgecursor(same, scan, new, lno);
873 same = 0;
874
875 addch(*scan);
876 *build = *scan;
877 }
878
879 build++;
880 scan++;
881 }
882
883 /* maybe clear to EOL */
884 end = old + COLS - (*o_number ? 8 : 0);
885 while (build < end && *build == ' ')
886 {
887 build++;
888 }
889 if (build < end)
890 {
891 nudgecursor(same, scan, new, lno);
892 same = 0;
893
894 clrtoeol();
895 while (build < old + COLS)
896 {
897 *build++ = ' ';
898 }
899 }
900#endif /* not CRUNCH */
901}
902
903
904/* This function is used in visual mode for drawing the screen (or just parts
905 * of the screen, if that's all thats needed). It also takes care of
906 * scrolling.
907 */
908void redraw(curs, inputting)
909 MARK curs; /* where to leave the screen's cursor */
910 int inputting; /* boolean: being called from input() ? */
911{
912 char *text; /* a line of text to display */
913 static long chgs; /* previous changes level */
914 long l;
915 int i;
916#ifndef CRUNCH
917 static long showtop; /* top line in window */
918 static long showbottom; /* bottom line in window */
919#endif
920
921 /* if curs == MARK_UNSET, then we should reset internal vars */
922 if (curs == MARK_UNSET)
923 {
924 if (topline < 1 || topline > nlines)
925 {
926 topline = 1L;
927 }
928 else
929 {
930 move(LINES - 1, 0);
931 clrtoeol();
932 }
933 leftcol = 0;
934 mustredraw = TRUE;
935 redrawafter = INFINITY;
936 preredraw = 0L;
937 postredraw = 0L;
938 chgs = 0;
939 smartlno = 0L;
940#ifndef NO_VISIBLE
941 vizlow = vizhigh = 0L;
942 vizchange = FALSE;
943#endif
944#ifndef CRUNCH
945 showtop = 0;
946 showbottom = INFINITY;
947#endif
948 return;
949 }
950
951#ifndef NO_VISIBLE
952 /* adjustments to hilited area may force extra lines to be redrawn. */
953 setviz(curs);
954#endif
955
956 /* figure out which column the cursor will be in */
957 l = markline(curs);
958 text = fetchline(l);
959 mark2phys(curs, text, inputting);
960
961#ifndef NO_COLOR
962 fixcolor();
963#endif
964
965 /* adjust topline, if necessary, to get the cursor on the screen */
966 if (l >= topline && l <= botline)
967 {
968 /* it is on the screen already */
969
970 /* if the file was changed but !mustredraw, then redraw line */
971 if (!mustredraw && (chgs != changes
972#ifndef NO_VISIBLE
973 || V_from
974#endif
975#ifndef CRUNCH
976 || l < showtop || l > showbottom
977#endif
978 ))
979 {
980 smartdrawtext(text, l, (chgs != changes));
981 }
982 }
983 else if (l < topline && l > topline - LINES && (has_SR || has_AL))
984 {
985 /* near top - scroll down */
986 if (!mustredraw)
987 {
988 move(0,0);
989 while (l < topline)
990 {
991 topline--;
992 if (has_SR)
993 {
994 do_SR();
995 }
996 else
997 {
998 insertln();
999 }
1000 text = fetchline(topline);
1001 drawtext(text, topline, FALSE);
1002 do_UP();
1003 }
1004
1005 /* blank out the last line */
1006 move(LINES - 1, 0);
1007 clrtoeol();
1008 }
1009 else
1010 {
1011 topline = l;
1012 redrawrange(0L, INFINITY, INFINITY);
1013 }
1014 }
1015 else if (l > topline && l < botline + LINES)
1016 {
1017 /* near bottom -- scroll up */
1018 if (!mustredraw)
1019 {
1020 move(LINES - 1,0);
1021 clrtoeol();
1022 while (l > botline)
1023 {
1024 topline++; /* <-- also adjusts botline */
1025 text = fetchline(botline);
1026 drawtext(text, botline, FALSE);
1027 }
1028#ifndef CRUNCH
1029 showbottom = l;
1030#endif
1031 }
1032 else
1033 {
1034 topline = l - (LINES - 2);
1035 redrawrange(0L, INFINITY, INFINITY);
1036 }
1037 }
1038 else
1039 {
1040 /* distant line - center it & force a redraw */
1041 topline = l - (LINES / 2) - 1;
1042 if (topline < 1)
1043 {
1044 topline = 1;
1045 }
1046 redrawrange(0L, INFINITY, INFINITY);
1047 changes++;
1048 }
1049
1050#ifndef CRUNCH
1051 /* make sure the current line is included in the "window" */
1052 if (l < showtop)
1053 {
1054 redrawrange(l, showtop, showtop);
1055 showtop = l;
1056 }
1057 if (l > showbottom)
1058 {
1059 redrawrange(showbottom, l, l);
1060 showbottom = l;
1061 }
1062#endif
1063
1064
1065 /* Now... do we really have to redraw? */
1066 if (mustredraw)
1067 {
1068 /* If redrawfter (and friends) aren't set, assume we should
1069 * redraw everything.
1070 */
1071 if (redrawafter == INFINITY)
1072 {
1073 redrawafter = 0L;
1074 preredraw = postredraw = INFINITY;
1075 }
1076
1077#ifndef CRUNCH
1078 /* shrink the window, if possible */
1079 if (showtop < topline)
1080 {
1081 showtop = topline;
1082 }
1083 if (showbottom > botline)
1084 {
1085 showbottom = botline;
1086 }
1087 if (postredraw == INFINITY)
1088 {
1089 /* these will be set to more reasonable values later */
1090 showtop = INFINITY;
1091 showbottom = 0L;
1092 }
1093#endif
1094
1095 /* adjust smartlno to correspond with inserted/deleted lines */
1096 if (smartlno >= redrawafter)
1097 {
1098 if (smartlno < preredraw && postredraw != preredraw) /*!!!*/
1099 {
1100 smartlno = 0L;
1101 }
1102 else
1103 {
1104 smartlno += (postredraw - preredraw);
1105 }
1106 }
1107
1108 /* should we insert some lines into the screen? */
1109 if (preredraw < postredraw && preredraw <= botline)
1110 {
1111 /* lines were inserted into the file */
1112
1113 /* decide where insertion should start */
1114 if (preredraw < topline)
1115 {
1116 l = topline;
1117 }
1118 else
1119 {
1120 l = preredraw;
1121 }
1122
1123 /* insert the lines... maybe */
1124 if (l + postredraw - preredraw > botline || !has_AL || *o_number)
1125 {
1126 /* Whoa! a whole screen full - just redraw */
1127 preredraw = postredraw = INFINITY;
1128 }
1129 else
1130 {
1131 /* really insert 'em */
1132 move((int)(l - topline), 0);
1133 for (i = postredraw - preredraw; i > 0; i--)
1134 {
1135 insertln();
1136 }
1137
1138 /* NOTE: the contents of those lines will be
1139 * drawn as part of the regular redraw loop.
1140 */
1141
1142 /* clear the last line */
1143 move(LINES - 1, 0);
1144 clrtoeol();
1145 }
1146 }
1147
1148 /* do we want to delete some lines from the screen? */
1149 if (preredraw > postredraw && postredraw <= botline)
1150 {
1151 if (preredraw > botline || !has_DL || *o_number)
1152 {
1153 postredraw = preredraw = INFINITY;
1154 }
1155 else /* we'd best delete some lines from the screen */
1156 {
1157 /* clear the last line, so it doesn't look
1158 * ugly as it gets pulled up into the screen
1159 */
1160 move(LINES - 1, 0);
1161 clrtoeol();
1162
1163 /* delete the lines */
1164 move((int)(postredraw - topline), 0);
1165 for (l = postredraw;
1166 l < preredraw && l <= botline;
1167 l++)
1168 {
1169 deleteln();
1170 }
1171
1172 /* draw the lines that are now newly visible
1173 * at the bottom of the screen
1174 */
1175 i = LINES - 1 + (postredraw - preredraw);
1176 move(i, 0);
1177 for (l = topline + i; l <= botline; l++)
1178 {
1179 /* clear this line */
1180 clrtoeol();
1181
1182 /* draw the line, or ~ for non-lines */
1183 if (l <= nlines)
1184 {
1185 text = fetchline(l);
1186 drawtext(text, l, FALSE);
1187 }
1188 else
1189 {
1190 addstr("~\n");
1191 }
1192 }
1193 }
1194 }
1195
1196 /* redraw the current line */
1197 l = markline(curs);
1198 pfetch(l);
1199 smartdrawtext(ptext, l, TRUE);
1200
1201#ifndef CRUNCH
1202 /* decide which lines must be in the "window" around the cursor */
1203 l = markline(curs);
1204 if ((*o_window & 0xff) + 1 == LINES)
1205 {
1206 showtop = 1;
1207 showbottom = INFINITY;
1208 }
1209 else if (l < showtop || l > showbottom)
1210 {
1211 l -= (*o_window & 0xff) / 2;
1212 if (l < topline)
1213 {
1214 l = topline;
1215 }
1216 if (l < showtop)
1217 {
1218 showtop = l;
1219 }
1220 l += (*o_window & 0xff) - 1;
1221 if (l > botline)
1222 {
1223 showtop = showtop - l + botline;
1224 l = botline;
1225 }
1226 if (l > showbottom)
1227 {
1228 showbottom = l;
1229 }
1230 }
1231#endif
1232
1233 /* decide where we should start redrawing from */
1234 if (redrawafter < topline)
1235 {
1236 l = topline;
1237 }
1238 else
1239 {
1240 l = redrawafter;
1241 }
1242 if (l <= botline && l < postredraw && (l != smartlno || botline != smartlno))
1243 {
1244 /* draw the other lines */
1245 move((int)(l - topline), 0);
1246 for (; l <= botline && l < postredraw; l++)
1247 {
1248 /* we already drew the current line, so skip it now */
1249 if (l == smartlno)
1250 {
1251#if OSK
1252 qaddch('\l');
1253#else
1254 qaddch('\n');
1255#endif
1256 continue;
1257 }
1258
1259 /* draw the line, or ~ for non-lines */
1260 if (l > nlines)
1261 {
1262 qaddch('~');
1263 clrtoeol();
1264 addch('\n');
1265 }
1266#ifndef CRUNCH
1267 else if (l < showtop || l > showbottom)
1268 {
1269 qaddch('@');
1270 clrtoeol();
1271 addch('\n');
1272 }
1273#endif
1274 else
1275 {
1276 text = fetchline(l);
1277 drawtext(text, l, TRUE);
1278 }
1279 }
1280 }
1281
1282 mustredraw = FALSE;
1283 }
1284
1285 /* force total (non-partial) redraw next time if not set */
1286 redrawafter = INFINITY;
1287 preredraw = 0L;
1288 postredraw = 0L;
1289
1290 /* move the cursor to where it belongs */
1291 move((int)(markline(curs) - topline), physcol);
1292 wqrefresh();
1293
1294 chgs = changes;
1295}
Note: See TracBrowser for help on using the repository browser.