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