📄 eedisp.c
字号:
int lcnt;int ccol;{ register int col, i; register SBBUF *sb; int c; char tmp[MAXCHAR*2]; /* MAXCHAR is enough, but *2 just in case */ col = ccol; sb = (SBBUF *) cur_buf; if((i = lcnt) > 0) do { if((c = sb_getc(sb)) == EOF) break; /* Check to see if we've run into an EOL */#if FX_EOLMODE if(c == CR) { if(eolcrlf(sb)) { if((c = sb_getc(sb)) == LF) /* EOL? */ /* Real EOL. Fail unless point ** is between CR and LF, in which case ** we return 0 (left margin). */ return (i==1 ? 0 : -1); /* Stray CR, back up & fall thru */ if(c != EOF) sb_backc(sb); c = CR; } } else if (c == LF) { if(!eolcrlf(sb)) /* Real EOL? */ return -1; /* Yes, fail */ /* If EOL mode is CRLF then hitting a LF ** can only happen for stray LFs (the ** previous check for CR takes care of ** CRLFs, and we never start scanning ** from the middle of a CRLF. ** Drop thru to show stray LF. */ }#else if(c == LF) return(-1);#endif /*-FX_EOLMODE*/ col += sctr(c, tmp, col); } while(--i); if(col > scr_wd0) return(-1); return(col);}/* D_LUPD - called from command level to completely redisplay a * specific line on the screen. */d_lupd(w, idx)struct window *w; /* Window this line belongs to, if known */int idx;{ t_curpos(idx, 0); t_docleol(); /* Zap physical screen line */ scr[idx]->sl_col = 0; /* Reflect it on phys screen image */ if(w) /* Mark window for updating */ w->w_redp |= RD_WINRES; else redp(RD_WINDS); /* No window given, assume global */ redp(RD_MOVE); /* Cursor has moved */}/* Clear a window completely the "quickest possible way" */clear_wind(w)register struct window *w;{ register int i = w->w_pos; /* Top line of window */ register int bot = i + w->w_ht; /* Bottom line (plus 1) of window */ for ( ; i < bot; ++i) d_lupd(w, i); /* Zap that line */}/* FIX_WIND - Sets up window screen image. Does not generate any * terminal output, but completely specifies what the new screen * image should look like. * Only the following 4 flags (lumped together in RDS_DOFIX) * provoke fix_wind to do something: * RD_MOVE - cursor has moved, must make sure still within * window, and select new one if not. * RD_TMOD - Text has been changed somewhere. * RD_FIXWIN - Something requested that fix_wind fix things. * Normally this is set when a new w_topldot is set. * RD_WINRES - Window needs to be completely regenerated. * Results: * Verifies that the current dot for the window (w_dot) exists. * If it is past the end of buffer, it is reset to EOB, and if this is * the current window, also updates cur_dot. Otherwise, w_dot is never * adjusted; it is fix_wind's responsibility to make sure that the window * displays w_dot. * Verifies that current w_topldot setting will result in cursor * (specified by w_dot) appearing within window. If not, resets w_topldot * to an appropriate value (1/3 of way down from top, unless * moving up in which case 1/3 of way up from bottom). * Makes sure that sl_boff, sl_len, sl_flg, and sl_cont * are set properly for all lines in window. SL_MOD is set * for any lines requiring screen updates; these lines * also have sl_nlin and sl_ncol properly set. * Note that sl_line and sl_col are NOT updated or changed, because * the physical screen has not been altered! * * Returns 0 if no physical screen updates are needed (other than * cursor moving and mode line updating). * Returns 1 if screen updates are needed; RD_UPDWIN is set in w_redp, * indicating that UPD_WIND should be called. */fix_wind (win)struct window *win;{ register struct window *w; register int i; register struct scr_line *s; chroff cdot, bdelta, updot, sdot, newz; chroff savdot; struct buffer *savbuf; int bot, nlmod, savi, contf, ocontf, randomflg; int newpct; if(!(w = win)) return(0); if(!(w->w_redp&RDS_DOFIX)) /* Anything we need to do? */ return(0); /* Nope, just ignore */ /* Find current dot for this window, and set up other stuff */ cdot = (w == cur_win) ? cur_dot : w->w_dot; bot = w->w_pos + w->w_ht; savbuf = cur_buf; cur_buf = w->w_buf; savdot = e_dot(); nlmod = 0; /* No screen image changes so far */ /* Dot (ie cursor) is before current top? If so, must move * backwards to find a new topldot. Note also that buffer may have * changed so that either cdot or topldot points past EOF. */ if(w->w_topldot > cdot) { /* Yes, must search backwards scrht/3 screen lines */ /* from cdot in order to find topldot. */ /* Don't bother updating scr stuff beforehand since we'll * have to revise everything anyway and can do it on the fly. */ i = (ev_mvpct * w->w_ht) / 100; goto skipdn; finddn: i = ((100 - ev_mvpct) * w->w_ht) / 100; skipdn: if(i <= 0) i = 1; /* Ensure # is reasonable */ else if(i >= w->w_ht) i = w->w_ht-1; e_go(cdot); /* Start here (may normalize to EOF)*/ d_backup(i ? i : 1); /* Try to back up cleverly */ w->w_topldot = e_dot(); randomflg = 0; /* We have some idea where we are */ fixall: /* Entry point for later recheck, with randomflg==1 */ newz = e_blen(); if(newz < cdot) /* Part of buf may have gone away */ { /* So normalize dot to EOF */ w->w_dot = cdot = newz; if(w == cur_win) /* Special check for fixing */ cur_dot = newz; /* up cur_dot too! */ goto finddn; /* and get a new top-of-window loc */ } retry: i = w->w_pos; contf = 0; s = 0; for(; i < bot; i++) { nlmod++; fix_line(scr[i], s); /* s = 0 the first time */ s = scr[i];#if FX_SOWIND if(w->w_flags & W_STANDOUT) s->sl_flg |= SL_NSO; else s->sl_flg &= ~SL_NSO;#endif } if(inwinp(w,cdot)) /* Ensure in window */ goto mdone; if(randomflg) /* If jumped randomly, */ { i = (ev_nwpct * w->w_ht) / 100; goto skipdn; /* Try to select new window */ } /* We tried to back up and went too far. */ if(cdot < w->w_topldot) /* Verify place is ahead */ { errbarf("fix_wind failed"); /* Didn't back up?? */ goto finddn; } /* Move down one line and try again */ if(w->w_ht > 1) w->w_topldot = scr[w->w_pos+1]->sl_boff; else { s = scr[w->w_pos]; w->w_topldot = s->sl_boff + s->sl_len; } e_go(w->w_topldot); goto retry; } /* At some future point, could separate out processing for * RD_WINRES and RD_FIXWIN. Latter flag implies only w_topldot * has changed (new window selected). Former implies whole * buffer has been munged, and everything is completely redone. */ if(w->w_redp&(RD_WINRES|RD_FIXWIN)) /* If re-figuring whole window */ { e_go(w->w_topldot); /* Start here, and */ randomflg = 1; /* set up flag saying random jump */ goto fixall; /* and go crunch all lines. */ } if((w->w_redp&RD_TMOD)==0) /* If claims no text mods, */ { if(inwinp(w,cdot)==0) /* Just verify cursor loc. */ goto finddn; /* Sigh.... */ newz = w->w_oldz; /* Win, set up for exit. */ goto done; } /* Here only when RD_TMOD is set, indicating changes are * between range variables. */ /* Find upper bound of any mods. This is a little gross in the * speed dept and some faster way should perhaps be devised. * In particular the main loop should incrementally keep track of * buffer size, and should set a flag RD_TEXT if anything has * actually been changed. Edit routines should have lots of * flags available to tell main loop more precisely what they did, * so main loop can take care of updating b/emod and stuff. */ if((newz = e_blen()) == 0) goto finddn; /* Ensure blank window is cleared */ bdelta = newz - w->w_oldz; if((updot = newz) > w->w_emod) updot -= w->w_emod; if(bdelta == 0 && (updot == w->w_bmod)) goto inwinq; /* Could also check for updot < w_topldot (changes above win) * or sl_boff+sl_len < w_bmod (changes below win) but those * cases are probably pretty rare. */ /* First find line where changes start */ for(i = w->w_pos; i < bot; i++) { s = scr[i]; if(w->w_bmod <= s->sl_boff) /* Changes prior to this? */ break; } if(i >= bot) /* Test last line specially */ { if(w->w_bmod > (s->sl_boff + (chroff)s->sl_len)) goto inwinq; /* Outside window */ /* Last line changed, hack it */ } if(i > w->w_pos /* If we have a prev line */ && (s->sl_len == 0 /* and we're at EOF, */ || w->w_bmod != s->sl_boff /* or not at start of line */ || scr[i-1]->sl_cont)) /* or prev line is continuation */ s = scr[--i]; /* then it's prev line we want */ /* I has index for screen line changes begin on; S has ptr. * This piece of code handles case where buffer has been modified * starting at BMOD, and BDELTA chars have been inserted/deleted; * range of changes ends at UPDOT. */ savi = i; while(++i < bot) scr[i]->sl_boff += bdelta; i = savi; /* Now start with 1st changed line and start figuring new line * lengths. Stop when hit end, or past updot and boff is correct * for start of line. */ /* can improve this by jumping out when past emod, and testing for * an EOL - then know stuff has to match someplace, so look for that. * could then simply update lengths or something? */ if(i > w->w_pos) /* Find # cols already there from prev line*/ contf = scr[i-1]->sl_cont; else contf = 0; ocontf = 1; /* Fake it so always update 1st line*/ e_go(sdot = s->sl_boff); for(; i < bot; i++) { s = scr[i]; if(updot <= sdot /* If past changed stuff */ && sdot == s->sl_boff /* and locs are lined up */ && contf == 0 /* and previous line clean */ && ocontf == 0) /* (both old and new images) */ break; /* Then done. */ nlmod++; ocontf = s->sl_cont; /* Save old-image contf value */ fix_line(s, (i > w->w_pos) ? scr[i-1] : 0);#if FX_SOWIND if(w->w_flags & W_STANDOUT) s->sl_flg |= SL_NSO; else s->sl_flg &= ~SL_NSO;#endif sdot = e_dot(); contf = s->sl_cont; /* Get new-image contf value */ } if(inwinp(w,cdot)) /* OK, screen fixed, see if cursor inside */ goto mdone; goto finddn; /* Test if still in window and dispatch appropriately */inwinq: if(inwinp(w,cdot)) goto done; else goto finddn; /* Come here when done, after mods made to window. * Calculate new %-of-buffer position for window's view, and * see if it's changed from current %. */mdone: if(w != cur_win) goto done; /* If not current window, ignore */ s = scr[bot-1]; if((s->sl_boff + (chroff)s->sl_len) >= newz) if(w->w_topldot) newpct = 150; /* BOT */ else newpct = 200; /* ALL */ else if(w->w_topldot == 0) newpct = -1; /* TOP */ else /* NOTE: This won't work if topldot is huge */ newpct = (w->w_topldot*100)/newz; /* nn% */ if(newpct != w->w_pct) /* OK, now compare with old % */ { w->w_pct = newpct; /* Different, must set and */ redp(RD_MODE); /* invoke redisplay of mode line! */ }done: w->w_bmod = -1; /* To indicate vars not set */ w->w_oldz = newz; w->w_redp &= ~RDS_DOFIX; /* Clear flags that invoked us */ if(nlmod) w->w_redp |= RD_UPDWIN; /* Say stuff to be updated */ e_go(savdot); cur_buf = savbuf; return(nlmod);}/* INWINP - Returns true if given dot is inside given window. */inwinp(win,cdot)struct window *win;chroff cdot;{ register struct scr_line *s; register struct window *w; chroff sdot; w = win; if(cdot < w->w_topldot) return(0); s = scr[(w->w_pos + w->w_ht) - 1]; sdot = s->sl_boff + (chroff)s->sl_len; if(cdot < sdot) return(1); /* Yup, inside window. */ if(cdot > sdot) return(0); /* Dot is exactly at end of window, must check further. */ if(s->sl_len /* If line exists, */ && ((s->sl_flg&SL_EOL) /* and ends in LF, */ || s->sl_cont > 1)) /* or sl_cont > 1, lose. */ return(0); return(1); /* Else inside, win. */}/* * UPD_WIND * If argument 0, assumes cur_win and DOESN'T interrupt if input * detected. */upd_wind(win)struct window *win;{ register int i, n; register struct scr_line *s; struct window *w; int top, bot, dspf, num, isave, noicost, nodcost, iline, dline;#if FX_SOWIND int oldso;#endif#if IMAGEN int origdspf; char redpmsg[128];#endif /*IMAGEN*/ if((w=win)==0) w = cur_win; dspf = w->w_redp; /* Get update flags for window */#if IMAGEN origdspf = dspf;#endif /*IMAGEN*/ if(w == cur_win) /* If updating current window, */ dspf |= rd_type; /* merge in global flags */ if((dspf &= RDS_WINFLGS) == 0) /* Well, it might happen sometimes */ goto zdone; w->w_redp = dspf; if(dspf&(RD_WINRES|RD_TMOD|RD_MOVE|RD_FIXWIN)) { fix_wind(w); /* May set some flags, so */ dspf = w->w_redp; /* get them back... */ } if((dspf&RD_UPDWIN)==0) /* Must ask for update! */ goto zdone;#if IMAGEN if (dbg_redp) { sprintf(redpmsg, "buffer: %14s, rd_type: %06o, w_redp: %06o, dspf: %06o", w->w_buf->b_name, rd_type, origdspf, dspf); barf2(redpmsg); }#endif /*IMAGEN*/ /* Assume screen structure set up by FIX_WIND, just go * effect change for every line modified. */#if FX_SOWIND oldso = t_dostandout((w->w_flags&W_STANDOUT)? 1:0);#endif top = w->w_pos; bot = top + w->w_ht; for(i = top; i < bot; ++i) if((s = scr[i])->sl_flg&SL_MOD) { if(win && tinwait()) /* If OK, stop if any chars typed */ { tbufls(); w->w_redp = dspf;#if FX_SOWIND t_dostandout(oldso);#endif return(1); /* Return immediately, say int'd */ } if(slineq(s,s)) /* Compare old with new */ goto ldone; /* Lines equal, no update needed */ #if IMAGEN /* If hint says redo entirely */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -