📄 redraw.c
字号:
/* This function draws a single line of text on the screen, possibly with * some cursor optimization. The cursor is repositioned before drawing * begins, so its position before doesn't really matter. */static void smartdrawtext(text, lno, showit) REG char *text; /* the text to draw */ long lno; /* line number of the text */ int showit; /* boolean: output line? (else just remember it) */{#ifdef CRUNCH move((int)(lno - topline), 0); if (showit) { drawtext(text, lno, TRUE); }#else /* not CRUNCH */ static char old[256]; /* how the line looked last time */ char new[256]; /* how it looks now */ char *build; /* used to put chars into new[] */ char *scan; /* used for moving thru new[] or old[] */ char *end; /* last non-blank changed char */ char *shift; /* used to insert/delete chars */ int same; /* length of a run of unchanged chars */ int limitcol; int col; int i; char numstr[9];# ifndef NO_CHARATTR /* if this line has attributes, do it the dumb way instead */ if (hasattr(lno, text)) { move((int)(lno - topline), 0); drawtext(text, lno, TRUE); return; }# endif# ifndef NO_SENTENCE /* if this line is a format line, & we're hiding format lines, then * let the dumb drawtext() function handle it */ if (*o_hideformat && *text == '.') { move((int)(lno - topline), 0); drawtext(text, lno, TRUE); return; }# endif# ifndef NO_VISIBLE if (vizchange) { move((int)(lno - topline), 0); drawtext(text, lno, TRUE); smartlno = 0L; return; }# endif /* skip stuff that was scrolled off left edge */ limitcol = leftcol; for (col = 0; (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */ text++) { if (i == '\t' && !*o_list) { col = col + *o_tabstop - (col % *o_tabstop); } else if (i >= 0 && i < ' ' || i == '\177') { col += 2; } else { col++; } } /* adjust for control char that was partially visible */ build = new; while (col > limitcol) { *build++ = ' '; limitcol++; } /* now for the visible characters */ limitcol = leftcol + COLS; if (*o_number) limitcol -= 8; for (; (i = *text) && col < limitcol; text++) { if (i == '\t' && !*o_list) { i = col + *o_tabstop - (col % *o_tabstop); while (col < i && col < limitcol) { *build++ = ' '; col++; } } else if (i >= 0 && i < ' ' || i == '\177') { col += 2; *build++ = '^'; if (col <= limitcol) { *build++ = (i ^ '@'); } } else { col++; *build++ = i; } } if (col < limitcol && *o_list) { *build++ = '$'; col++; } end = build; while (col < limitcol) { *build++ = ' '; col++; } /* if we're just supposed to remember this line, then remember it */ if (!showit) { smartlno = lno; strncpy(old, new, COLS); return; } /* locate the last non-blank character */ while (end > new && end[-1] == ' ') { end--; } /* can we optimize the displaying of this line? */ if (lno != smartlno) { /* nope, can't optimize - different line */ move((int)(lno - topline), 0); /* show the line number, if necessary */ if (*o_number) { sprintf(numstr, "%6ld |", lno); qaddstr(numstr); } /* show the new line */ for (scan = new, build = old; scan < end; ) { qaddch(*scan); *build++ = *scan++; } if (end < new + COLS - (*o_number ? 8 : 0)) { clrtoeol(); while (build < old + COLS) { *build++ = ' '; } } smartlno = lno; return; } /* skip any initial unchanged characters */ for (scan = new, build = old; scan < end && *scan == *build; scan++, build++) { } i = (scan - new); if (*o_number) i += 8; move((int)(lno - topline), i); /* The in-between characters must be changed */ same = 0; while (scan < end) { /* is this character a match? */ if (scan[0] == build[0]) { same++; } else /* do we want to insert? */ if (scan < end - 1 && scan[1] == build[0] && (has_IC || has_IM)) { nudgecursor(same, scan, new, lno); same = 0; insch(*scan); for (shift = old + COLS; --shift > build; ) { shift[0] = shift[-1]; } *build = *scan; } else /* do we want to delete? */ if (build < old + COLS - 1 && scan[0] == build[1] && has_DC) { nudgecursor(same, scan, new, lno); same = 0; delch(); same++; for (shift = build; shift < old + COLS - 1; shift++) { shift[0] = shift[1]; } if (*o_number) shift -= 8; *shift = ' '; } else /* we must overwrite */ { nudgecursor(same, scan, new, lno); same = 0; addch(*scan); *build = *scan; } build++; scan++; } /* maybe clear to EOL */ end = old + COLS - (*o_number ? 8 : 0); while (build < end && *build == ' ') { build++; } if (build < end) { nudgecursor(same, scan, new, lno); same = 0; clrtoeol(); while (build < old + COLS) { *build++ = ' '; } }#endif /* not CRUNCH */}/* This function is used in visual mode for drawing the screen (or just parts * of the screen, if that's all thats needed). It also takes care of * scrolling. */void redraw(curs, inputting) MARK curs; /* where to leave the screen's cursor */ int inputting; /* boolean: being called from input() ? */{ char *text; /* a line of text to display */ static long chgs; /* previous changes level */ long l; int i;#ifndef CRUNCH static long showtop; /* top line in window */ static long showbottom; /* bottom line in window */#endif /* if curs == MARK_UNSET, then we should reset internal vars */ if (curs == MARK_UNSET) { if (topline < 1 || topline > nlines) { topline = 1L; } else { move(LINES - 1, 0); clrtoeol(); } leftcol = 0; mustredraw = TRUE; redrawafter = INFINITY; preredraw = 0L; postredraw = 0L; chgs = 0; smartlno = 0L;#ifndef NO_VISIBLE vizlow = vizhigh = 0L; vizchange = FALSE;#endif#ifndef CRUNCH showtop = 0; showbottom = INFINITY;#endif return; }#ifndef NO_VISIBLE /* adjustments to hilited area may force extra lines to be redrawn. */ setviz(curs);#endif /* figure out which column the cursor will be in */ l = markline(curs); text = fetchline(l); mark2phys(curs, text, inputting);#ifndef NO_COLOR fixcolor();#endif /* adjust topline, if necessary, to get the cursor on the screen */ if (l >= topline && l <= botline) { /* it is on the screen already */ /* if the file was changed but !mustredraw, then redraw line */ if (!mustredraw && (chgs != changes#ifndef NO_VISIBLE || V_from#endif#ifndef CRUNCH || l < showtop || l > showbottom#endif )) { smartdrawtext(text, l, (chgs != changes)); } } else if (l < topline && l > topline - LINES && (has_SR || has_AL)) { /* near top - scroll down */ if (!mustredraw) { move(0,0); while (l < topline) { topline--; if (has_SR) { do_SR(); } else { insertln(); } text = fetchline(topline); drawtext(text, topline, FALSE); do_UP(); } /* blank out the last line */ move(LINES - 1, 0); clrtoeol(); } else { topline = l; redrawrange(0L, INFINITY, INFINITY); } } else if (l > topline && l < botline + LINES) { /* near bottom -- scroll up */ if (!mustredraw) { move(LINES - 1,0); clrtoeol(); while (l > botline) { topline++; /* <-- also adjusts botline */ text = fetchline(botline); drawtext(text, botline, FALSE); }#ifndef CRUNCH showbottom = l;#endif } else { topline = l - (LINES - 2); redrawrange(0L, INFINITY, INFINITY); } } else { /* distant line - center it & force a redraw */ topline = l - (LINES / 2) - 1; if (topline < 1) { topline = 1; } redrawrange(0L, INFINITY, INFINITY); changes++; }#ifndef CRUNCH /* make sure the current line is included in the "window" */ if (l < showtop) { redrawrange(l, showtop, showtop); showtop = l; } if (l > showbottom) { redrawrange(showbottom, l, l); showbottom = l; }#endif /* Now... do we really have to redraw? */ if (mustredraw) { /* If redrawfter (and friends) aren't set, assume we should * redraw everything. */ if (redrawafter == INFINITY) { redrawafter = 0L; preredraw = postredraw = INFINITY; }#ifndef CRUNCH /* shrink the window, if possible */ if (showtop < topline) { showtop = topline; } if (showbottom > botline) { showbottom = botline; } if (postredraw == INFINITY) { /* these will be set to more reasonable values later */ showtop = INFINITY; showbottom = 0L; }#endif /* adjust smartlno to correspond with inserted/deleted lines */ if (smartlno >= redrawafter) { if (smartlno < preredraw && postredraw != preredraw) /*!!!*/ { smartlno = 0L; } else { smartlno += (postredraw - preredraw); } } /* should we insert some lines into the screen? */ if (preredraw < postredraw && preredraw <= botline) { /* lines were inserted into the file */ /* decide where insertion should start */ if (preredraw < topline) { l = topline; } else { l = preredraw; } /* insert the lines... maybe */ if (l + postredraw - preredraw > botline || !has_AL || *o_number) { /* Whoa! a whole screen full - just redraw */ preredraw = postredraw = INFINITY; } else { /* really insert 'em */ move((int)(l - topline), 0); for (i = postredraw - preredraw; i > 0; i--) { insertln(); } /* NOTE: the contents of those lines will be * drawn as part of the regular redraw loop. */ /* clear the last line */ move(LINES - 1, 0); clrtoeol(); } } /* do we want to delete some lines from the screen? */ if (preredraw > postredraw && postredraw <= botline) { if (preredraw > botline || !has_DL || *o_number) { postredraw = preredraw = INFINITY; } else /* we'd best delete some lines from the screen */ { /* clear the last line, so it doesn't look * ugly as it gets pulled up into the screen */ move(LINES - 1, 0); clrtoeol(); /* delete the lines */ move((int)(postredraw - topline), 0); for (l = postredraw; l < preredraw && l <= botline; l++) { deleteln(); } /* draw the lines that are now newly visible * at the bottom of the screen */ i = LINES - 1 + (postredraw - preredraw); move(i, 0); for (l = topline + i; l <= botline; l++) { /* clear this line */ clrtoeol(); /* draw the line, or ~ for non-lines */ if (l <= nlines) { text = fetchline(l); drawtext(text, l, FALSE); } else { addstr("~\n"); } } } } /* redraw the current line */ l = markline(curs); pfetch(l); smartdrawtext(ptext, l, TRUE);#ifndef CRUNCH /* decide which lines must be in the "window" around the cursor */ l = markline(curs); if ((*o_window & 0xff) + 1 == LINES) { showtop = 1; showbottom = INFINITY; } else if (l < showtop || l > showbottom) { l -= (*o_window & 0xff) / 2; if (l < topline) { l = topline; } if (l < showtop) { showtop = l; } l += (*o_window & 0xff) - 1; if (l > botline) { showtop = showtop - l + botline; l = botline; } if (l > showbottom) { showbottom = l; } }#endif /* decide where we should start redrawing from */ if (redrawafter < topline) { l = topline; } else { l = redrawafter; } if (l <= botline && l < postredraw && (l != smartlno || botline != smartlno)) { /* draw the other lines */ move((int)(l - topline), 0); for (; l <= botline && l < postredraw; l++) { /* we already drew the current line, so skip it now */ if (l == smartlno) {#if OSK qaddch('\l');#else qaddch('\n');#endif continue; } /* draw the line, or ~ for non-lines */ if (l > nlines) { qaddch('~'); clrtoeol(); addch('\n'); }#ifndef CRUNCH else if (l < showtop || l > showbottom) { qaddch('@'); clrtoeol(); addch('\n'); }#endif else { text = fetchline(l); drawtext(text, l, TRUE); } } } mustredraw = FALSE; } /* force total (non-partial) redraw next time if not set */ redrawafter = INFINITY; preredraw = 0L; postredraw = 0L; /* move the cursor to where it belongs */ move((int)(markline(curs) - topline), physcol); wqrefresh(); chgs = changes;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -