kernel debug: priv can be NULL early on
[minix.git] / commands / elvis / redraw.c
blobae923cf60a30b5e5d8af3d09ae79cbb20ed23b74
1 /* redraw.c */
3 /* Author:
4 * Steve Kirkendall
5 * 14407 SW Teal Blvd. #C
6 * Beaverton, OR 97005
7 * kirkenda@cs.pdx.edu
8 */
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.
20 #include "config.h"
21 #include "vi.h"
23 /* This variable contains the line number that smartdrawtext() knows best */
24 static long smartlno;
26 /* This function remembers where changes were made, so that the screen can be
27 * redraw in a more efficient manner.
29 static long redrawafter; /* line# of first line that must be redrawn */
30 static long preredraw; /* line# of last line changed, before change */
31 static long postredraw; /* line# of last line changed, after change */
32 static int mustredraw; /* boolean: anything forcing a screen update? */
33 void 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 */
38 if (after == redrawafter)
40 /* multiple insertions/deletions at the same place -- combine
41 * them
43 preredraw -= (post - pre);
44 if (postredraw < post)
46 preredraw += (post - postredraw);
47 postredraw = post;
49 if (redrawafter > preredraw)
51 redrawafter = preredraw;
53 if (redrawafter < 1L)
55 redrawafter = 0L;
56 preredraw = postredraw = INFINITY;
59 else if (postredraw > 0L)
61 /* multiple changes in different places -- redraw everything
62 * after "after".
64 postredraw = preredraw = INFINITY;
65 if (after < redrawafter)
66 redrawafter = after;
68 else
70 /* first change */
71 redrawafter = after;
72 preredraw = pre;
73 postredraw = post;
75 mustredraw = TRUE;
79 #ifndef NO_CHARATTR
80 /* see if a given line uses character attribute strings */
81 static int hasattr(lno, text)
82 long lno; /* the line# of the cursor */
83 REG char *text; /* the text of the line, from fetchline */
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;
90 /* if charattr is off, then the answer is "no, it doesn't" */
91 if (!*o_charattr)
93 chgs = 0; /* <- forces us to check if charattr is later set */
94 return FALSE;
97 /* if we already know the answer, return it... */
98 if (lno == plno && chgs == changes)
100 return panswer;
103 /* get the line & look for "\fX" */
104 if (!text[0] || !text[1] || !text[2])
106 panswer = FALSE;
108 else
110 for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++)
113 panswer = (scan[2] != '\0');
116 /* save the results */
117 plno = lno;
118 chgs = changes;
120 /* return the results */
121 return panswer;
123 #endif
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.
130 static long vizlow, vizhigh; /* the starting and ending lines */
131 static int vizleft, vizright; /* starting & ending indicies */
132 static int vizchange; /* boolean: must use stupid drawtext? */
133 static void setviz(curs)
134 MARK curs;
136 long newlow, newhigh;
137 long extra = 0L;
139 /* for now, assume the worst... */
140 vizchange = TRUE;
142 /* set newlow & newhigh according to V_from and cursor */
143 if (!V_from)
145 /* no lines should have reverse-video */
146 if (vizlow)
148 redrawrange(vizlow, vizhigh + 1L, vizhigh + 1L);
149 vizlow = vizhigh = 0L;
151 else
153 vizchange = FALSE;
155 return;
158 /* figure out which lines *SHOULD* have hilites */
159 if (V_from < curs)
161 newlow = markline(V_from);
162 newhigh = markline(curs);
163 vizleft = markidx(V_from);
164 vizright = markidx(curs) + 1;
166 else
168 newlow = markline(curs);
169 newhigh = markline(V_from);
170 vizleft = markidx(curs);
171 vizright = markidx(V_from) + 1;
174 /* adjust for line-mode hiliting */
175 if (V_linemd)
177 vizleft = 0;
178 vizright = BLKSIZE - 1;
180 else
182 extra = 1L;
185 /* arrange for the necessary lines to be redrawn */
186 if (vizlow == 0L)
188 /* just starting to redraw */
189 redrawrange(newlow, newhigh, newhigh);
191 else
193 /* Were new lines added/removed at the front? */
194 if (newlow != vizlow)
196 if (newlow < vizlow)
197 redrawrange(newlow, vizlow + extra, vizlow + extra);
198 else
199 redrawrange(vizlow, newlow + extra, newlow + extra);
202 /* Were new lines added/removed at the back? */
203 if (newhigh != vizhigh)
205 if (newhigh < vizhigh)
206 redrawrange(newhigh + 1L - extra, vizhigh + 1L, vizhigh + 1L);
207 else
208 redrawrange(vizhigh + 1L - extra, newhigh, newhigh);
212 /* remember which lines will contain hilighted text now */
213 vizlow = newlow;
214 vizhigh = newhigh;
216 #endif /* !NO_VISIBLE */
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
222 int 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() ? */
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;
234 /* for now, assume we have to start counting at the left edge */
235 col = 0;
236 idx = markidx(curs);
238 /* if the file hasn't changed & line number is the same & it has no
239 * embedded character attribute strings, can we do shortcuts?
241 if (chgs == changes
242 && !((curs ^ pcursor) & ~(BLKSIZE - 1))
243 #ifndef NO_CHARATTR
244 && !hasattr(markline(curs), text)
245 #endif
248 /* no movement? */
249 if (curs == pcursor)
251 /* return the column of the char; for tabs, return its last column */
252 if (text[idx] == '\t' && !inputting && !*o_list)
254 return pcol + *o_tabstop - (pcol % *o_tabstop) - 1;
256 else
258 return pcol;
262 /* movement to right? */
263 if (curs > pcursor)
265 /* start counting from previous place */
266 col = pcol;
267 idx = markidx(curs) - markidx(pcursor);
268 text += markidx(pcursor);
272 /* count over to the char after the idx position */
273 while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */
275 if (i == '\t' && !*o_list)
277 col += *o_tabstop;
278 col -= col % *o_tabstop;
280 else if (i >= '\0' && i < ' ' || i == '\177')
282 col += 2;
284 #ifndef NO_CHARATTR
285 else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
287 text += 2; /* plus one more at bottom of loop */
288 idx -= 2;
290 #endif
291 else
293 col++;
295 text++;
296 idx--;
299 /* save stuff to speed next call */
300 pcursor = curs;
301 pcol = col;
302 chgs = changes;
304 /* return the column of the char; for tabs, return its last column */
305 if (*text == '\t' && !inputting && !*o_list)
307 return col + *o_tabstop - (col % *o_tabstop) - 1;
309 else
311 return col;
316 /* This function is similar to idx2col except that it takes care of sideways
317 * scrolling - for the given line, at least.
319 int 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() ? */
324 int i;
326 i = idx2col(m, text, inputting);
327 while (i < leftcol)
329 leftcol -= *o_sidescroll;
330 mustredraw = TRUE;
331 redrawrange(1L, INFINITY, INFINITY);
333 while (i > rightcol)
335 leftcol += *o_sidescroll;
336 mustredraw = TRUE;
337 redrawrange(1L, INFINITY, INFINITY);
339 physrow = markline(m) - topline;
340 physcol = i - leftcol;
341 if (*o_number)
342 physcol += 8;
344 return physcol;
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.
351 static 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? */
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];
367 /* show the line number, if necessary */
368 if (*o_number)
370 sprintf(numstr, "%6ld |", lno);
371 qaddstr(numstr);
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 == '.')
378 clrtoeol();
379 #if OSK
380 qaddch('\l');
381 #else
382 qaddch('\n');
383 #endif
384 return;
386 #endif
388 /* move some things into registers... */
389 limitcol = leftcol;
390 tabstop = *o_tabstop;
391 abnormal = FALSE;
393 #ifndef CRUNCH
394 if (clr)
395 clrtoeol();
396 #endif
398 /* skip stuff that was scrolled off left edge */
399 for (col = 0;
400 (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
401 text++)
403 #ifndef NO_VISIBLE
404 idx++;
405 #endif
406 if (i == '\t' && !*o_list)
408 col = col + tabstop - (col % tabstop);
410 else if (i >= 0 && i < ' ' || i == '\177')
412 col += 2;
414 #ifndef NO_CHARATTR
415 else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
417 text += 2; /* plus one more as part of "for" loop */
419 /* since this attribute might carry over, we need it */
420 switch (*text)
422 case 'R':
423 case 'P':
424 attrset(A_NORMAL);
425 abnormal = FALSE;
426 break;
428 case 'B':
429 attrset(A_BOLD);
430 abnormal = TRUE;
431 break;
433 case 'U':
434 attrset(A_UNDERLINE);
435 abnormal = TRUE;
436 break;
438 case 'I':
439 attrset(A_ALTCHARSET);
440 abnormal = TRUE;
441 break;
444 #endif
445 else
447 col++;
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))
457 do_VISIBLE();
458 rev = TRUE;
460 #endif
462 /* adjust for control char that was partially visible */
463 while (col > limitcol)
465 qaddch(' ');
466 limitcol++;
469 /* now for the visible characters */
470 limitcol = leftcol + COLS;
471 if (*o_number)
472 limitcol -= 8;
473 for (; (i = *text) && col < limitcol; text++)
475 #ifndef NO_VISIBLE
476 /* maybe turn hilite on/off in the middle of the line */
477 if (lno == vizlow && vizleft == idx)
479 do_VISIBLE();
480 rev = TRUE;
482 if (lno == vizhigh && vizright == idx)
484 do_SE();
485 rev = FALSE;
487 idx++;
489 /* if hiliting, never emit physical tabs */
490 if (rev && i == '\t' && !*o_list)
492 i = col + tabstop - (col % tabstop);
495 qaddch(' ');
496 col++;
497 } while (col < i);
499 else
500 #endif /* !NO_VISIBLE */
501 if (i == '\t' && !*o_list)
503 i = col + tabstop - (col % tabstop);
504 if (i < limitcol)
506 #ifdef CRUNCH
507 if (!clr && has_PT && !((i - leftcol) & 7))
508 #else
509 if (has_PT && !((i - leftcol) & 7))
510 #endif
514 qaddch('\t');
515 col += 8; /* not exact! */
516 } while (col < i);
517 col = i; /* NOW it is exact */
519 else
523 qaddch(' ');
524 col++;
525 } while (col < i);
528 else /* tab ending after screen? next line! */
530 col = limitcol;
531 if (has_AM)
533 addch('\n'); /* GB */
537 else if (i >= 0 && i < ' ' || i == '\177')
539 col += 2;
540 qaddch('^');
541 if (col <= limitcol)
543 qaddch(i ^ '@');
546 #ifndef NO_CHARATTR
547 else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
549 text += 2; /* plus one more as part of "for" loop */
550 switch (*text)
552 case 'R':
553 case 'P':
554 attrset(A_NORMAL);
555 abnormal = FALSE;
556 break;
558 case 'B':
559 attrset(A_BOLD);
560 abnormal = TRUE;
561 break;
563 case 'U':
564 attrset(A_UNDERLINE);
565 abnormal = TRUE;
566 break;
568 case 'I':
569 attrset(A_ALTCHARSET);
570 abnormal = TRUE;
571 break;
574 #endif
575 else
577 col++;
578 qaddch(i);
582 /* get ready for the next line */
583 #ifndef NO_CHARATTR
584 if (abnormal)
586 attrset(A_NORMAL);
588 #endif
589 if (*o_list && col < limitcol)
591 qaddch('$');
592 col++;
595 #ifndef NO_VISIBLE
596 /* did we hilite this whole line? If so, STOP! */
597 if (rev)
599 do_SE();
601 #endif
603 #ifdef CRUNCH
604 if (clr && col < limitcol)
606 clrtoeol();
608 #endif
609 if (!has_AM || col < limitcol)
611 addch('\n');
614 wqrefresh();
618 #ifndef CRUNCH
619 static 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 */
625 int col;
627 if (same > 0)
629 if (same < 5)
631 /* move the cursor by overwriting */
632 while (same > 0)
634 qaddch(scan[-same]);
635 same--;
638 else
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);
648 #endif /* not CRUNCH */
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.
654 static 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) */
659 #ifdef CRUNCH
660 move((int)(lno - topline), 0);
661 if (showit)
663 drawtext(text, lno, TRUE);
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];
678 # ifndef NO_CHARATTR
679 /* if this line has attributes, do it the dumb way instead */
680 if (hasattr(lno, text))
682 move((int)(lno - topline), 0);
683 drawtext(text, lno, TRUE);
684 return;
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
691 if (*o_hideformat && *text == '.')
693 move((int)(lno - topline), 0);
694 drawtext(text, lno, TRUE);
695 return;
697 # endif
698 # ifndef NO_VISIBLE
699 if (vizchange)
701 move((int)(lno - topline), 0);
702 drawtext(text, lno, TRUE);
703 smartlno = 0L;
704 return;
706 # endif
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++)
714 if (i == '\t' && !*o_list)
716 col = col + *o_tabstop - (col % *o_tabstop);
718 else if (i >= 0 && i < ' ' || i == '\177')
720 col += 2;
722 else
724 col++;
728 /* adjust for control char that was partially visible */
729 build = new;
730 while (col > limitcol)
732 *build++ = ' ';
733 limitcol++;
736 /* now for the visible characters */
737 limitcol = leftcol + COLS;
738 if (*o_number)
739 limitcol -= 8;
740 for (; (i = *text) && col < limitcol; text++)
742 if (i == '\t' && !*o_list)
744 i = col + *o_tabstop - (col % *o_tabstop);
745 while (col < i && col < limitcol)
747 *build++ = ' ';
748 col++;
751 else if (i >= 0 && i < ' ' || i == '\177')
753 col += 2;
754 *build++ = '^';
755 if (col <= limitcol)
757 *build++ = (i ^ '@');
760 else
762 col++;
763 *build++ = i;
766 if (col < limitcol && *o_list)
768 *build++ = '$';
769 col++;
771 end = build;
772 while (col < limitcol)
774 *build++ = ' ';
775 col++;
778 /* if we're just supposed to remember this line, then remember it */
779 if (!showit)
781 smartlno = lno;
782 strncpy(old, new, COLS);
783 return;
786 /* locate the last non-blank character */
787 while (end > new && end[-1] == ' ')
789 end--;
792 /* can we optimize the displaying of this line? */
793 if (lno != smartlno)
795 /* nope, can't optimize - different line */
796 move((int)(lno - topline), 0);
798 /* show the line number, if necessary */
799 if (*o_number)
801 sprintf(numstr, "%6ld |", lno);
802 qaddstr(numstr);
805 /* show the new line */
806 for (scan = new, build = old; scan < end; )
808 qaddch(*scan);
809 *build++ = *scan++;
811 if (end < new + COLS - (*o_number ? 8 : 0))
813 clrtoeol();
814 while (build < old + COLS)
816 *build++ = ' ';
819 smartlno = lno;
820 return;
823 /* skip any initial unchanged characters */
824 for (scan = new, build = old; scan < end && *scan == *build; scan++, build++)
827 i = (scan - new);
828 if (*o_number)
829 i += 8;
830 move((int)(lno - topline), i);
832 /* The in-between characters must be changed */
833 same = 0;
834 while (scan < end)
836 /* is this character a match? */
837 if (scan[0] == build[0])
839 same++;
841 else /* do we want to insert? */
842 if (scan < end - 1 && scan[1] == build[0] && (has_IC || has_IM))
844 nudgecursor(same, scan, new, lno);
845 same = 0;
847 insch(*scan);
848 for (shift = old + COLS; --shift > build; )
850 shift[0] = shift[-1];
852 *build = *scan;
854 else /* do we want to delete? */
855 if (build < old + COLS - 1 && scan[0] == build[1] && has_DC)
857 nudgecursor(same, scan, new, lno);
858 same = 0;
860 delch();
861 same++;
862 for (shift = build; shift < old + COLS - 1; shift++)
864 shift[0] = shift[1];
866 if (*o_number)
867 shift -= 8;
868 *shift = ' ';
870 else /* we must overwrite */
872 nudgecursor(same, scan, new, lno);
873 same = 0;
875 addch(*scan);
876 *build = *scan;
879 build++;
880 scan++;
883 /* maybe clear to EOL */
884 end = old + COLS - (*o_number ? 8 : 0);
885 while (build < end && *build == ' ')
887 build++;
889 if (build < end)
891 nudgecursor(same, scan, new, lno);
892 same = 0;
894 clrtoeol();
895 while (build < old + COLS)
897 *build++ = ' ';
900 #endif /* not CRUNCH */
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.
908 void redraw(curs, inputting)
909 MARK curs; /* where to leave the screen's cursor */
910 int inputting; /* boolean: being called from input() ? */
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
921 /* if curs == MARK_UNSET, then we should reset internal vars */
922 if (curs == MARK_UNSET)
924 if (topline < 1 || topline > nlines)
926 topline = 1L;
928 else
930 move(LINES - 1, 0);
931 clrtoeol();
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;
951 #ifndef NO_VISIBLE
952 /* adjustments to hilited area may force extra lines to be redrawn. */
953 setviz(curs);
954 #endif
956 /* figure out which column the cursor will be in */
957 l = markline(curs);
958 text = fetchline(l);
959 mark2phys(curs, text, inputting);
961 #ifndef NO_COLOR
962 fixcolor();
963 #endif
965 /* adjust topline, if necessary, to get the cursor on the screen */
966 if (l >= topline && l <= botline)
968 /* it is on the screen already */
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
980 smartdrawtext(text, l, (chgs != changes));
983 else if (l < topline && l > topline - LINES && (has_SR || has_AL))
985 /* near top - scroll down */
986 if (!mustredraw)
988 move(0,0);
989 while (l < topline)
991 topline--;
992 if (has_SR)
994 do_SR();
996 else
998 insertln();
1000 text = fetchline(topline);
1001 drawtext(text, topline, FALSE);
1002 do_UP();
1005 /* blank out the last line */
1006 move(LINES - 1, 0);
1007 clrtoeol();
1009 else
1011 topline = l;
1012 redrawrange(0L, INFINITY, INFINITY);
1015 else if (l > topline && l < botline + LINES)
1017 /* near bottom -- scroll up */
1018 if (!mustredraw)
1020 move(LINES - 1,0);
1021 clrtoeol();
1022 while (l > botline)
1024 topline++; /* <-- also adjusts botline */
1025 text = fetchline(botline);
1026 drawtext(text, botline, FALSE);
1028 #ifndef CRUNCH
1029 showbottom = l;
1030 #endif
1032 else
1034 topline = l - (LINES - 2);
1035 redrawrange(0L, INFINITY, INFINITY);
1038 else
1040 /* distant line - center it & force a redraw */
1041 topline = l - (LINES / 2) - 1;
1042 if (topline < 1)
1044 topline = 1;
1046 redrawrange(0L, INFINITY, INFINITY);
1047 changes++;
1050 #ifndef CRUNCH
1051 /* make sure the current line is included in the "window" */
1052 if (l < showtop)
1054 redrawrange(l, showtop, showtop);
1055 showtop = l;
1057 if (l > showbottom)
1059 redrawrange(showbottom, l, l);
1060 showbottom = l;
1062 #endif
1065 /* Now... do we really have to redraw? */
1066 if (mustredraw)
1068 /* If redrawfter (and friends) aren't set, assume we should
1069 * redraw everything.
1071 if (redrawafter == INFINITY)
1073 redrawafter = 0L;
1074 preredraw = postredraw = INFINITY;
1077 #ifndef CRUNCH
1078 /* shrink the window, if possible */
1079 if (showtop < topline)
1081 showtop = topline;
1083 if (showbottom > botline)
1085 showbottom = botline;
1087 if (postredraw == INFINITY)
1089 /* these will be set to more reasonable values later */
1090 showtop = INFINITY;
1091 showbottom = 0L;
1093 #endif
1095 /* adjust smartlno to correspond with inserted/deleted lines */
1096 if (smartlno >= redrawafter)
1098 if (smartlno < preredraw && postredraw != preredraw) /*!!!*/
1100 smartlno = 0L;
1102 else
1104 smartlno += (postredraw - preredraw);
1108 /* should we insert some lines into the screen? */
1109 if (preredraw < postredraw && preredraw <= botline)
1111 /* lines were inserted into the file */
1113 /* decide where insertion should start */
1114 if (preredraw < topline)
1116 l = topline;
1118 else
1120 l = preredraw;
1123 /* insert the lines... maybe */
1124 if (l + postredraw - preredraw > botline || !has_AL || *o_number)
1126 /* Whoa! a whole screen full - just redraw */
1127 preredraw = postredraw = INFINITY;
1129 else
1131 /* really insert 'em */
1132 move((int)(l - topline), 0);
1133 for (i = postredraw - preredraw; i > 0; i--)
1135 insertln();
1138 /* NOTE: the contents of those lines will be
1139 * drawn as part of the regular redraw loop.
1142 /* clear the last line */
1143 move(LINES - 1, 0);
1144 clrtoeol();
1148 /* do we want to delete some lines from the screen? */
1149 if (preredraw > postredraw && postredraw <= botline)
1151 if (preredraw > botline || !has_DL || *o_number)
1153 postredraw = preredraw = INFINITY;
1155 else /* we'd best delete some lines from the screen */
1157 /* clear the last line, so it doesn't look
1158 * ugly as it gets pulled up into the screen
1160 move(LINES - 1, 0);
1161 clrtoeol();
1163 /* delete the lines */
1164 move((int)(postredraw - topline), 0);
1165 for (l = postredraw;
1166 l < preredraw && l <= botline;
1167 l++)
1169 deleteln();
1172 /* draw the lines that are now newly visible
1173 * at the bottom of the screen
1175 i = LINES - 1 + (postredraw - preredraw);
1176 move(i, 0);
1177 for (l = topline + i; l <= botline; l++)
1179 /* clear this line */
1180 clrtoeol();
1182 /* draw the line, or ~ for non-lines */
1183 if (l <= nlines)
1185 text = fetchline(l);
1186 drawtext(text, l, FALSE);
1188 else
1190 addstr("~\n");
1196 /* redraw the current line */
1197 l = markline(curs);
1198 pfetch(l);
1199 smartdrawtext(ptext, l, TRUE);
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)
1206 showtop = 1;
1207 showbottom = INFINITY;
1209 else if (l < showtop || l > showbottom)
1211 l -= (*o_window & 0xff) / 2;
1212 if (l < topline)
1214 l = topline;
1216 if (l < showtop)
1218 showtop = l;
1220 l += (*o_window & 0xff) - 1;
1221 if (l > botline)
1223 showtop = showtop - l + botline;
1224 l = botline;
1226 if (l > showbottom)
1228 showbottom = l;
1231 #endif
1233 /* decide where we should start redrawing from */
1234 if (redrawafter < topline)
1236 l = topline;
1238 else
1240 l = redrawafter;
1242 if (l <= botline && l < postredraw && (l != smartlno || botline != smartlno))
1244 /* draw the other lines */
1245 move((int)(l - topline), 0);
1246 for (; l <= botline && l < postredraw; l++)
1248 /* we already drew the current line, so skip it now */
1249 if (l == smartlno)
1251 #if OSK
1252 qaddch('\l');
1253 #else
1254 qaddch('\n');
1255 #endif
1256 continue;
1259 /* draw the line, or ~ for non-lines */
1260 if (l > nlines)
1262 qaddch('~');
1263 clrtoeol();
1264 addch('\n');
1266 #ifndef CRUNCH
1267 else if (l < showtop || l > showbottom)
1269 qaddch('@');
1270 clrtoeol();
1271 addch('\n');
1273 #endif
1274 else
1276 text = fetchline(l);
1277 drawtext(text, l, TRUE);
1282 mustredraw = FALSE;
1285 /* force total (non-partial) redraw next time if not set */
1286 redrawafter = INFINITY;
1287 preredraw = 0L;
1288 postredraw = 0L;
1290 /* move the cursor to where it belongs */
1291 move((int)(markline(curs) - topline), physcol);
1292 wqrefresh();
1294 chgs = changes;