add f_sourceany, so we can print an error message
[nvi.git] / vi / vs_refresh.c
blobdb4deb508d975bfda80173008b598fff610bcad5
1 /*-
2 * Copyright (c) 1992, 1993
3 * The Regents of the University of California. All rights reserved.
5 * %sccs.include.redist.c%
6 */
8 #ifndef lint
9 static char sccsid[] = "$Id: vs_refresh.c,v 8.41 1993/12/02 18:11:15 bostic Exp $ (Berkeley) $Date: 1993/12/02 18:11:15 $";
10 #endif /* not lint */
12 #include <sys/types.h>
14 #include <ctype.h>
15 #include <curses.h>
16 #include <stdlib.h>
17 #include <string.h>
19 #include "vi.h"
20 #include "svi_screen.h"
21 #include "sex/sex_screen.h"
23 static int svi_modeline __P((SCR *, EXF *));
24 static int svi_msgflush __P((SCR *));
26 int
27 svi_refresh(sp, ep)
28 SCR *sp;
29 EXF *ep;
31 SCR *tsp;
32 u_int paintbits;
35 * 1: Resize the screen.
37 * Notice that a resize is requested, and set up everything so that
38 * the file gets reinitialized. Done here, instead of in the vi loop
39 * because there may be other initialization that other screens need
40 * to do. The actual changing of the row/column values was done by
41 * calling the ex options code which put them into the environment,
42 * which is used by curses. Stupid, but ugly.
44 if (F_ISSET(sp, S_RESIZE)) {
45 /* Reinitialize curses. */
46 if (svi_curses_end(sp) || svi_curses_init(sp))
47 return (1);
49 /* Lose any svi_screens() cached information. */
50 SVP(sp)->ss_lno = OOBLNO;
53 * Fill the map, incidentally losing any svi_line()
54 * cached information.
56 if (sp->s_fill(sp, ep, sp->lno, P_FILL))
57 return (1);
58 F_CLR(sp, S_RESIZE | S_REFORMAT);
59 F_SET(sp, S_REDRAW);
63 * 2: S_REFRESH
65 * If S_REFRESH is set in the current screen, repaint everything
66 * that we can find.
68 if (F_ISSET(sp, S_REFRESH))
69 for (tsp = sp->gp->dq.cqh_first;
70 tsp != (void *)&sp->gp->dq; tsp = tsp->q.cqe_next)
71 if (tsp != sp)
72 F_SET(tsp, S_REDRAW);
74 * 3: Related or dirtied screens, or screens with messages.
76 * If related screens share a view into a file, they may have been
77 * modified as well. Refresh any screens with paint or dirty bits
78 * set, or where messages are waiting.
80 paintbits = S_REDRAW | S_REFORMAT | S_REFRESH;
81 if (O_ISSET(sp, O_NUMBER))
82 paintbits |= S_RENUMBER;
83 for (tsp = sp->gp->dq.cqh_first;
84 tsp != (void *)&sp->gp->dq; tsp = tsp->q.cqe_next)
85 if (tsp != sp &&
86 (F_ISSET(tsp, paintbits) ||
87 F_ISSET(SVP(tsp), SVI_SCREENDIRTY) ||
88 tsp->msgq.lh_first != NULL &&
89 !F_ISSET(tsp->msgq.lh_first, M_EMPTY))) {
90 (void)svi_paint(tsp, tsp->ep);
91 F_CLR(SVP(tsp), SVI_SCREENDIRTY);
95 * 4: Refresh the current screen.
97 * Always refresh the current screen, it may be a cursor movement.
98 * Also, always do it last -- that way, S_REFRESH can be set in
99 * the current screen only, and the screen won't flash.
101 F_CLR(sp, SVI_SCREENDIRTY);
102 return (svi_paint(sp, ep));
106 * svi_paint --
107 * This is the guts of the vi curses screen code. The idea is that
108 * the SCR structure passed in contains the new coordinates of the
109 * screen. What makes this hard is that we don't know how big
110 * characters are, doing input can put the cursor in illegal places,
111 * and we're frantically trying to avoid repainting unless it's
112 * absolutely necessary. If you change this code, you'd better know
113 * what you're doing. It's subtle and quick to anger.
116 svi_paint(sp, ep)
117 SCR *sp;
118 EXF *ep;
120 CHNAME const *cname;
121 SMAP *smp, tmp;
122 SVI_PRIVATE *svp;
123 recno_t lastline, lcnt;
124 size_t cwtotal, cnt, len, x, y;
125 int ch, didpaint;
126 char *p;
128 #define LNO sp->lno
129 #define OLNO svp->olno
130 #define CNO sp->cno
131 #define OCNO svp->ocno
132 #define SCNO svp->sc_col
134 didpaint = 0;
135 svp = SVP(sp);
138 * 1: Reformat the lines.
140 * If the lines themselves have changed (:set list, for example),
141 * fill in the map from scratch. Adjust the screen that's being
142 * displayed if the leftright flag is set.
144 if (F_ISSET(sp, S_REFORMAT)) {
145 /* Toss svi_screens() cached information. */
146 SVP(sp)->ss_lno = OOBLNO;
148 /* Toss svi_line() cached information. */
149 if (svi_sm_fill(sp, ep, HMAP->lno, P_TOP))
150 return (1);
151 if (O_ISSET(sp, O_LEFTRIGHT) &&
152 (cnt = svi_screens(sp, ep, LNO, &CNO)) != 1)
153 for (smp = HMAP; smp <= TMAP; ++smp)
154 smp->off = cnt;
155 F_CLR(sp, S_REFORMAT);
156 F_SET(sp, S_REDRAW);
160 * 2: Line movement.
162 * Line changes can cause the top line to change as well. As
163 * before, if the movement is large, the screen is repainted.
165 * 2a: Tiny screens.
167 * Tiny screens cannot be permitted into the "scrolling" parts of
168 * the smap code for two reasons. If the screen size is 1 line,
169 * HMAP == TMAP and the code will quickly drop core. If the screen
170 * size is 2, none of the divisions by 2 will work, and scrolling
171 * won't work. In fact, because no line change will be less than
172 * HALFTEXT(sp), we always ending up "filling" the map, with a
173 * P_MIDDLE flag, which isn't what the user wanted. Tiny screens
174 * can go into the "fill" portions of the smap code, however.
176 if (sp->t_rows <= 2) {
177 if (LNO < HMAP->lno) {
178 if (svi_sm_fill(sp, ep, LNO, P_TOP))
179 return (1);
180 } else if (LNO > TMAP->lno)
181 if (svi_sm_fill(sp, ep, LNO, P_BOTTOM))
182 return (1);
183 if (sp->t_rows == 1) {
184 HMAP->off = svi_screens(sp, ep, LNO, &CNO);
185 goto paint;
187 F_SET(sp, S_REDRAW);
188 goto adjust;
192 * 2b: Small screens.
194 * Users can use the window, w300, w1200 and w9600 options to make
195 * the screen artificially small. The behavior of these options
196 * in the historic vi wasn't all that consistent, and, in fact, it
197 * was never documented how various screen movements affected the
198 * screen size. Generally, one of three things would happen:
199 * 1: The screen would expand in size, showing the line
200 * 2: The screen would scroll, showing the line
201 * 3: The screen would compress to its smallest size and
202 * repaint.
203 * In general, scrolling didn't cause compression (200^D was handled
204 * the same as ^D), movement to a specific line would (:N where N
205 * was 1 line below the screen caused a screen compress), and cursor
206 * movement would scroll if it was 11 lines or less, and compress if
207 * it was more than 11 lines. (And, no, I have no idea where the 11
208 * comes from.)
210 * What we do is try and figure out if the line is less than half of
211 * a full screen away. If it is, we expand the screen if there's
212 * room, and then scroll as necessary. The alternative is to compress
213 * and repaint.
215 * !!!
216 * This code is a special case from beginning to end. Unfortunately,
217 * home modems are still slow enough that it's worth having.
219 * XXX
220 * If the line a really long one, i.e. part of the line is on the
221 * screen but the column offset is not, we'll end up in the adjust
222 * code, when we should probably have compressed the screen.
224 if (ISSMALLSCREEN(sp))
225 if (LNO < HMAP->lno) {
226 lcnt = svi_sm_nlines(sp, ep, HMAP, LNO, sp->t_maxrows);
227 if (lcnt <= HALFSCREEN(sp))
228 for (; lcnt && sp->t_rows != sp->t_maxrows;
229 --lcnt, ++sp->t_rows) {
230 ++TMAP;
231 if (svi_sm_1down(sp, ep))
232 return (1);
234 else
235 goto small_fill;
236 } else if (LNO > TMAP->lno) {
237 lcnt = svi_sm_nlines(sp, ep, TMAP, LNO, sp->t_maxrows);
238 if (lcnt <= HALFSCREEN(sp))
239 for (; lcnt && sp->t_rows != sp->t_maxrows;
240 --lcnt, ++sp->t_rows) {
241 if (svi_sm_next(sp, ep, TMAP, TMAP + 1))
242 return (1);
243 ++TMAP;
244 if (svi_line(sp, ep, TMAP, NULL, NULL))
245 return (1);
247 else {
248 small_fill: MOVE(sp, INFOLINE(sp), 0);
249 clrtoeol();
250 for (; sp->t_rows > sp->t_minrows;
251 --sp->t_rows, --TMAP) {
252 MOVE(sp, TMAP - HMAP, 0);
253 clrtoeol();
255 if (svi_sm_fill(sp, ep, LNO, P_FILL))
256 return (1);
257 F_SET(sp, S_REDRAW);
258 goto adjust;
263 * 3a: Line down.
265 if (LNO >= HMAP->lno) {
266 if (LNO <= TMAP->lno)
267 goto adjust;
270 * If less than half a screen away, scroll down until the
271 * line is on the screen.
273 lcnt = svi_sm_nlines(sp, ep, TMAP, LNO, HALFTEXT(sp));
274 if (lcnt < HALFTEXT(sp)) {
275 while (lcnt--)
276 if (svi_sm_1up(sp, ep))
277 return (1);
278 goto adjust;
282 * If less than a full screen from the bottom of the file, put
283 * the last line of the file on the bottom of the screen. The
284 * calculation is safe because we know there's at least one
285 * full screen of lines, otherwise couldn't have gotten here.
287 if (file_lline(sp, ep, &lastline))
288 return (1);
289 tmp.lno = LNO;
290 tmp.off = 1;
291 lcnt = svi_sm_nlines(sp, ep, &tmp, lastline, sp->t_rows);
292 if (lcnt < sp->t_rows) {
293 if (svi_sm_fill(sp, ep, lastline, P_BOTTOM))
294 return (1);
295 F_SET(sp, S_REDRAW);
296 goto adjust;
300 * If more than a full screen from the last line of the file,
301 * put the new line in the middle of the screen.
303 goto middle;
307 * 3b: Line up.
309 * If less than half a screen away, scroll up until the line is
310 * the first line on the screen.
312 lcnt = svi_sm_nlines(sp, ep, HMAP, LNO, HALFTEXT(sp));
313 if (lcnt < HALFTEXT(sp)) {
314 while (lcnt--)
315 if (svi_sm_1down(sp, ep))
316 return (1);
317 goto adjust;
321 * If less than half a screen from the top of the file, put the first
322 * line of the file at the top of the screen. Otherwise, put the line
323 * in the middle of the screen.
325 tmp.lno = 1;
326 tmp.off = 1;
327 lcnt = svi_sm_nlines(sp, ep, &tmp, LNO, HALFTEXT(sp));
328 if (lcnt < HALFTEXT(sp)) {
329 if (svi_sm_fill(sp, ep, 1, P_TOP))
330 return (1);
331 } else
332 middle: if (svi_sm_fill(sp, ep, LNO, P_MIDDLE))
333 return (1);
334 F_SET(sp, S_REDRAW);
337 * At this point we know part of the line is on the screen. Since
338 * scrolling is done using logical lines, not physical, all of the
339 * line may not be on the screen. While that's not necessarily bad,
340 * if the part the cursor is on isn't there, we're going to lose.
341 * This can be tricky; if the line covers the entire screen, lno
342 * may be the same as both ends of the map, that's why we test BOTH
343 * the top and the bottom of the map. This isn't a problem for
344 * left-right scrolling, the cursor movement code handles the problem.
346 * There's a performance issue here if editing *really* long lines.
347 * This gets to the right spot by scrolling, and, in a binary, by
348 * scrolling hundreds of lines. If the adjustment looks like it's
349 * going to be a serious problem, refill the screen and repaint.
351 adjust: if (!O_ISSET(sp, O_LEFTRIGHT) &&
352 (LNO == HMAP->lno || LNO == TMAP->lno)) {
353 cnt = svi_screens(sp, ep, LNO, &CNO);
354 if (LNO == HMAP->lno && cnt < HMAP->off)
355 if ((HMAP->off - cnt) > HALFTEXT(sp)) {
356 HMAP->off = cnt;
357 svi_sm_fill(sp, ep, OOBLNO, P_TOP);
358 F_SET(sp, S_REDRAW);
359 } else
360 while (cnt < HMAP->off)
361 if (svi_sm_1down(sp, ep))
362 return (1);
363 if (LNO == TMAP->lno && cnt > TMAP->off)
364 if ((cnt - TMAP->off) > HALFTEXT(sp)) {
365 TMAP->off = cnt;
366 svi_sm_fill(sp, ep, OOBLNO, P_BOTTOM);
367 F_SET(sp, S_REDRAW);
368 } else
369 while (cnt > TMAP->off)
370 if (svi_sm_1up(sp, ep))
371 return (1);
374 /* If the screen needs to be repainted, skip cursor optimization. */
375 if (F_ISSET(sp, S_REDRAW))
376 goto paint;
379 * 4: Cursor movements.
381 * Decide cursor position. If the line has changed, the cursor has
382 * moved over a tab, or don't know where the cursor was, reparse the
383 * line. Note, if we think that the cursor "hasn't moved", reparse
384 * the line. This is 'cause if it hasn't moved, we've almost always
385 * lost track of it.
387 * Otherwise, we've just moved over fixed-width characters, and can
388 * calculate the left/right scrolling and cursor movement without
389 * reparsing the line. Note that we don't know which (if any) of
390 * the characters between the old and new cursor positions changed.
392 * XXX
393 * With some work, it should be possible to handle tabs quickly, at
394 * least in obvious situations, like moving right and encountering
395 * a tab, without reparsing the whole line.
398 /* If the line we're working with has changed, reparse. */
399 if (F_ISSET(SVP(sp), SVI_CUR_INVALID) || LNO != OLNO) {
400 F_CLR(SVP(sp), SVI_CUR_INVALID);
401 goto slow;
404 /* Otherwise, if nothing's changed, go fast. */
405 if (CNO == OCNO)
406 goto fast;
409 * Get the current line. If this fails, we either have an empty
410 * file and can just repaint, or there's a real problem. This
411 * isn't a performance issue because there aren't any ways to get
412 * here repeatedly.
414 if ((p = file_gline(sp, ep, LNO, &len)) == NULL) {
415 if (file_lline(sp, ep, &lastline))
416 return (1);
417 if (lastline == 0)
418 goto slow;
419 GETLINE_ERR(sp, LNO);
420 return (1);
423 #ifdef DEBUG
424 /* This is just a test. */
425 if (CNO >= len && len != 0) {
426 msgq(sp, M_ERR, "Error: %s/%d: cno (%u) >= len (%u)",
427 tail(__FILE__), __LINE__, CNO, len);
428 return (1);
430 #endif
432 * The basic scheme here is to look at the characters in between
433 * the old and new positions and decide how big they are on the
434 * screen, and therefore, how many screen positions to move.
436 cname = sp->gp->cname;
437 if (CNO < OCNO) {
439 * 4a: Cursor moved left.
441 * Point to the old character. The old cursor position can
442 * be past EOL if, for example, we just deleted the rest of
443 * the line. In this case, since we don't know the width of
444 * the characters we traversed, we have to do it slowly.
446 p += OCNO;
447 cnt = (OCNO - CNO) + 1;
448 if (OCNO >= len)
449 goto slow;
452 * Quit sanity check -- it's hard to figure out exactly when
453 * we cross a screen boundary as we do in the cursor right
454 * movement. If cnt is so large that we're going to cross the
455 * boundary no matter what, stop now.
457 if (SCNO + 1 + MAX_CHARACTER_COLUMNS < cnt)
458 goto lscreen;
461 * Count up the widths of the characters. If it's a tab
462 * character, go do it the the slow way.
464 for (cwtotal = 0; cnt--; cwtotal += cname[ch].len)
465 if ((ch = *(u_char *)p--) == '\t')
466 goto slow;
469 * Decrement the screen cursor by the total width of the
470 * characters minus 1.
472 cwtotal -= 1;
475 * If we're moving left, and there's a wide character in the
476 * current position, go to the end of the character.
478 if (cname[ch].len > 1)
479 cwtotal -= cname[ch].len - 1;
482 * If the new column moved us out of the current screen,
483 * calculate a new screen.
485 if (SCNO < cwtotal) {
486 lscreen: if (O_ISSET(sp, O_LEFTRIGHT)) {
487 for (smp = HMAP; smp <= TMAP; ++smp)
488 --smp->off;
489 goto paint;
491 goto slow;
493 SCNO -= cwtotal;
494 } else {
496 * 4b: Cursor moved right.
498 * Point to the first character to the right.
500 p += OCNO + 1;
501 cnt = CNO - OCNO;
504 * Count up the widths of the characters. If it's a tab
505 * character, go do it the the slow way. If we cross a
506 * screen boundary, we can quit.
508 for (cwtotal = SCNO; cnt--;) {
509 if ((ch = *(u_char *)p++) == '\t')
510 goto slow;
511 if ((cwtotal += cname[ch].len) >= SCREEN_COLS(sp))
512 break;
516 * Increment the screen cursor by the total width of the
517 * characters.
519 SCNO = cwtotal;
522 * If the new column moved us out of the current screen,
523 * calculate a new screen.
525 if (SCNO >= SCREEN_COLS(sp)) {
526 if (O_ISSET(sp, O_LEFTRIGHT)) {
527 SCNO -= SCREEN_COLS(sp);
528 for (smp = HMAP; smp <= TMAP; ++smp)
529 ++smp->off;
530 goto paint;
532 goto slow;
537 * 4c: Fast cursor update.
539 * Retrieve the current cursor position, and correct it
540 * for split screens.
542 fast: getyx(stdscr, y, x);
543 y -= sp->woff;
544 goto number;
547 * 4d: Slow cursor update.
549 * Walk through the map and find the current line. If doing left-right
550 * scrolling and the cursor movement has changed the screen displayed,
551 * scroll the screen left or right, unless we're updating the info line
552 * in which case we just scroll that one line. Then update the screen
553 * lines for this file line until we have a new screen cursor position.
555 slow: for (smp = HMAP; smp->lno != LNO; ++smp);
556 if (O_ISSET(sp, O_LEFTRIGHT)) {
557 cnt = svi_screens(sp, ep, LNO, &CNO) % SCREEN_COLS(sp);
558 if (cnt != HMAP->off) {
559 if (ISINFOLINE(sp, smp))
560 smp->off = cnt;
561 else
562 for (smp = HMAP; smp <= TMAP; ++smp)
563 smp->off = cnt;
564 goto paint;
567 for (y = -1; smp <= TMAP && smp->lno == LNO; ++smp) {
568 if (svi_line(sp, ep, smp, &y, &SCNO))
569 return (1);
570 if (y != -1)
571 break;
573 goto number;
576 * 5: Repaint the entire screen.
578 * Lost big, do what you have to do. We flush the cache as S_REDRAW
579 * gets set when the screen isn't worth fixing, and it's simpler to
580 * repaint. So, don't trust anything that we think we know about it.
582 paint: for (smp = HMAP; smp <= TMAP; ++smp)
583 SMAP_FLUSH(smp);
584 for (smp = HMAP; smp <= TMAP; ++smp)
585 if (svi_line(sp, ep, smp, &y, &SCNO))
586 return (1);
588 * If it's a small screen and we're redrawing, clear the unused lines,
589 * ex may have overwritten them.
591 if (F_ISSET(sp, S_REDRAW)) {
592 if (ISSMALLSCREEN(sp))
593 for (cnt = sp->t_rows; cnt <= sp->t_maxrows; ++cnt) {
594 MOVE(sp, cnt, 0);
595 clrtoeol();
597 F_CLR(sp, S_REDRAW);
600 didpaint = 1;
603 * 6: Repaint the line numbers.
605 * If O_NUMBER is set and the S_RENUMBER bit is set, and we didn't
606 * repaint the screen, repaint all of the line numbers, they've
607 * changed.
609 number: if (O_ISSET(sp, O_NUMBER) && F_ISSET(sp, S_RENUMBER) && !didpaint) {
610 if (svi_number(sp, ep))
611 return (1);
612 F_CLR(sp, S_RENUMBER);
616 * 7: Refresh the screen.
618 * If the screen was corrupted, refresh it.
620 if (F_ISSET(sp, S_REFRESH)) {
621 wrefresh(curscr);
622 F_CLR(sp, S_REFRESH);
625 if (F_ISSET(sp, S_BELLSCHED))
626 svi_bell(sp);
628 * If the bottom line isn't in use by the colon command:
630 * Display any messages. Don't test S_UPDATE_MODE. The
631 * message printing routine set it to avoid anyone else
632 * destroying the message we're about to display.
634 * If the bottom line isn't in use by anyone, put out the
635 * standard status line.
637 if (!F_ISSET(SVP(sp), SVI_INFOLINE))
638 if (sp->msgq.lh_first != NULL &&
639 !F_ISSET(sp->msgq.lh_first, M_EMPTY))
640 svi_msgflush(sp);
641 else if (!F_ISSET(sp, S_UPDATE_MODE))
642 svi_modeline(sp, ep);
644 /* Update saved information. */
645 OCNO = CNO;
646 OLNO = LNO;
648 /* Place the cursor. */
649 MOVE(sp, y, SCNO);
651 /* Flush it all out. */
652 refresh();
654 return (0);
658 * svi_msgflush --
659 * Flush any accumulated messages.
661 static int
662 svi_msgflush(sp)
663 SCR *sp;
665 CH ikey;
666 CHAR_T ch;
667 CHNAME const *cname;
668 MSG *mp;
669 size_t chlen, len;
670 char *p;
672 #define MCONTMSG " [More ...]"
674 /* Display the messages. */
675 cname = sp->gp->cname;
676 for (mp = sp->msgq.lh_first, p = NULL;
677 mp != NULL && !F_ISSET(mp, M_EMPTY); mp = mp->q.le_next) {
678 p = mp->mbuf;
680 lcont: /* Move to the message line and clear it. */
681 MOVE(sp, INFOLINE(sp), 0);
682 clrtoeol();
685 * Turn on standout mode if requested, or, if we've split
686 * the screen and need a divider.
688 if (F_ISSET(mp, M_INV_VIDEO) ||
689 sp->q.cqe_next != (void *)&sp->gp->dq)
690 standout();
693 * Print up to the "more" message. Avoid the last character
694 * in the last line, some hardware doesn't like it.
696 if (svi_ncols(sp, p, mp->len, NULL) < sp->cols - 1)
697 len = sp->cols - 1;
698 else
699 len = (sp->cols - sizeof(MCONTMSG)) - 1;
700 for (;; ++p) {
701 if (!mp->len)
702 break;
703 ch = *(u_char *)p;
704 chlen = cname[ch].len;
705 if (chlen >= len)
706 break;
707 len -= chlen;
708 --mp->len;
709 ADDNSTR(cname[ch].name, chlen);
713 * If more, print continue message. If user key fails,
714 * keep showing the messages anyway.
716 if (mp->len || (mp->q.le_next != NULL &&
717 !F_ISSET(mp->q.le_next, M_EMPTY))) {
718 ADDNSTR(MCONTMSG, sizeof(MCONTMSG) - 1);
719 refresh();
720 for (;;) {
721 if (term_user_key(sp, &ikey) != INP_OK)
722 break;
723 if (ikey.value == K_CR ||
724 ikey.value == K_NL || isblank(ch))
725 break;
726 svi_bell(sp);
730 /* Turn off standout mode. */
731 if (F_ISSET(mp, M_INV_VIDEO) ||
732 sp->q.cqe_next != (void *)&sp->gp->dq)
733 standend();
735 if (mp->len)
736 goto lcont;
738 refresh();
739 F_SET(mp, M_EMPTY);
741 return (0);
744 #define RULERSIZE 15
745 #define MODESIZE (RULERSIZE + 15)
748 * svi_modeline --
749 * Update the mode line.
751 static int
752 svi_modeline(sp, ep)
753 SCR *sp;
754 EXF *ep;
756 char *s, buf[RULERSIZE];
758 MOVE(sp, INFOLINE(sp), 0);
759 clrtoeol();
761 /* Display a dividing line if not the bottom screen. */
762 if (sp->q.cqe_next != (void *)&sp->gp->dq)
763 svi_divider(sp);
765 /* Display the ruler. */
766 if (O_ISSET(sp, O_RULER) && sp->cols > RULERSIZE + 2) {
767 MOVE(sp, INFOLINE(sp), sp->cols / 2 - RULERSIZE / 2);
768 clrtoeol();
769 (void)snprintf(buf,
770 sizeof(buf), "%lu,%lu", sp->lno, sp->cno + 1);
771 ADDSTR(buf);
774 /* Show the modified bit. */
775 if (O_ISSET(sp, O_SHOWDIRTY) &&
776 F_ISSET(ep, F_MODIFIED) && sp->cols > MODESIZE) {
777 MOVE(sp, INFOLINE(sp), sp->cols - 9);
778 ADDSTR("*");
782 * Show the mode. Leave the last character blank, in case it's a
783 * really dumb terminal with hardware scroll. Second, don't try
784 * to *paint* the last character, SunOS 4.1.1 and Ultrix 4.2 curses
785 * won't let you paint the last character in the screen.
787 if (O_ISSET(sp, O_SHOWMODE) && sp->cols > MODESIZE) {
788 MOVE(sp, INFOLINE(sp), sp->cols - 8);
789 s = F_ISSET(sp, S_INPUT) ? " Input" : "Command";
790 ADDSTR(s);
793 return (0);
797 * svi_divider --
798 * Draw a dividing line between the screens.
801 svi_divider(sp)
802 SCR *sp;
804 size_t len;
806 #define DIVIDESTR "+=+=+=+=+=+=+=+"
807 len = sizeof(DIVIDESTR) - 1 > sp->cols ?
808 sp->cols : sizeof(DIVIDESTR) - 1;
809 ADDNSTR(DIVIDESTR, len);
810 return (0);