/* * upddex: * de-extend any line that derserves it */ void upddex(void) { struct window *wp; struct line *lp; int i; wp = wheadp; while (wp != NULL) { lp = wp->w_linep; i = wp->w_toprow; while (i < wp->w_toprow + wp->w_ntrows) { if (vscreen[i]->v_flag & VFEXT) { if ((wp != curwp) || (lp != wp->w_dotp) || (curcol < term.t_ncol - 1)) { vtmove(i, 0); show_line(lp); vteeol(); /* this line no longer is extended */ vscreen[i]->v_flag &= ~VFEXT; vscreen[i]->v_flag |= VFCHG; } } lp = lforw(lp); ++i; } /* and onward to the next window */ wp = wp->w_wndp; } }
// Update the current line to the virtual screen in given window. static void vupd_dotline(EWindow *winp) { Line *lnp; // Line to update. int sline; // Physical screen line to update. int i; // Search down to the line we want... lnp = winp->w_face.wf_toplnp; sline = winp->w_toprow; while(lnp != winp->w_face.wf_dot.lnp) { ++sline; lnp = lforw(lnp); } // and update the virtual line. vscreen[sline]->v_flags |= VFCHGD; taboff = winp->w_face.wf_fcol; vtmove(sline,-taboff); // Move each char of line to virtual screen until at end. for(i = 0; i < lused(lnp); ++i) vtputc(lgetc(lnp,i)); #if COLOR vscreen[sline]->v_rfcolor = winp->w_face.wf_fcolor; vscreen[sline]->v_rbcolor = winp->w_bcolor; #endif vteeol(); taboff = 0; }
/* * updall: * update all the lines in a window on the virtual screen * * struct window *wp; window to update lines in */ static void updall(struct window *wp) { struct line *lp; /* line to update */ int sline; /* physical screen line to update */ /* search down the lines, updating them */ lp = wp->w_linep; sline = wp->w_toprow; while (sline < wp->w_toprow + wp->w_ntrows) { /* and update the virtual line */ vscreen[sline]->v_flag |= VFCHG; vscreen[sline]->v_flag &= ~VFREQ; vtmove(sline, 0); if (lp != wp->w_bufp->b_linep) { /* if we are not at the end */ show_line(lp); lp = lforw(lp); } /* on to the next one */ #if COLOR vscreen[sline]->v_rfcolor = wp->w_fcolor; vscreen[sline]->v_rbcolor = wp->w_bcolor; #endif vteeol(); ++sline; } }
/* * Redisplay the mode line for the window pointed to by the "wp". This is the * only routine that has any idea of how the modeline is formatted. You can * change the modeline format by hacking at this routine. Called by "update" * any time there is a dirty window. */ static void modeline(struct window *wp) { char *cp; int c; int n; /* cursor position count */ struct buffer *bp; int i; /* loop index */ int lchar; /* character to draw line in buffer with */ int firstm; /* is this the first mode? */ char tline[NLINE]; /* buffer for part of mode line */ n = wp->w_toprow + wp->w_ntrows; /* Location. */ vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL; /* Redraw next time. */ #if COLOR vscreen[n]->v_rfcolor = 0; /* black on */ vscreen[n]->v_rbcolor = 7; /* white..... */ #endif vtmove(n, 0); /* Seek to right line. */ if (wp == curwp) /* mark the current buffer */ #if PKCODE lchar = '-'; #else lchar = '='; #endif else #if REVSTA if (revexist)
// De-extend any line in any window that needs it. static void supd_dex(void) { EWindow *winp; Line *lnp; int i,j; int nlines; // Number of lines in the current window. winp = wheadp; do { lnp = winp->w_face.wf_toplnp; i = winp->w_toprow; nlines = winp->w_nrows; while(i < winp->w_toprow + nlines) { if(vscreen[i]->v_flags & VFEXT) { if(winp != curwp || lnp != winp->w_face.wf_dot.lnp || curcol < (int) term.t_ncol - 1) { if(lnp == winp->w_bufp->b_hdrlnp) vtmove(i,0); else { taboff = winp->w_face.wf_fcol; vtmove(i,-taboff); for(j = 0; j < lused(lnp); ++j) vtputc(lgetc(lnp,j)); taboff = 0; } vteeol(); // This line is no longer extended. vscreen[i]->v_flags &= ~VFEXT; vscreen[i]->v_flags |= VFCHGD; } } if(lnp != winp->w_bufp->b_hdrlnp) lnp = lforw(lnp); ++i; } // Onward to the next window. } while((winp = winp->w_nextp) != NULL); }
// Transfer all lines in given window to virtual screen. static void vupd_all(EWindow *winp) { Line *lnp; // Line to update. int sline; // Physical screen line to update. int i; int nlines; // Number of lines in the current window. // Search down the lines, updating them. lnp = winp->w_face.wf_toplnp; sline = winp->w_toprow; nlines = winp->w_nrows; taboff = winp->w_face.wf_fcol; while(sline < winp->w_toprow + nlines) { // Update the virtual line. vscreen[sline]->v_flags |= VFCHGD; vscreen[sline]->v_left = FARRIGHT; vscreen[sline]->v_right = 0; vtmove(sline,-taboff); // If we are not at the end... if(lnp != winp->w_bufp->b_hdrlnp) { for(i = 0; i < lused(lnp); ++i) vtputc(lgetc(lnp,i)); lnp = lforw(lnp); } // Make sure we are on screen. if(vtcol < 0) vtcol = 0; // On to the next line. #if COLOR vscreen[sline]->v_rfcolor = winp->w_face.wf_fcolor; vscreen[sline]->v_rbcolor = winp->w_bcolor; #endif vteeol(); ++sline; } taboff = 0; }
/* * updext: * update the extended line which the cursor is currently * on at a column greater than the terminal width. The line * will be scrolled right or left to let the user see where * the cursor is */ static void updext(void) { int rcursor; /* real cursor location */ struct line *lp; /* pointer to current line */ /* calculate what column the real cursor will end up in */ rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin; taboff = lbound = curcol - rcursor + 1; /* scan through the line outputing characters to the virtual screen */ /* once we reach the left edge */ vtmove(currow, -lbound); /* start scanning offscreen */ lp = curwp->w_dotp; /* line to output */ show_line(lp); /* truncate the virtual line, restore tab offset */ vteeol(); taboff = 0; /* and put a '$' in column 1 */ vscreen[currow]->v_text[0] = '$'; }
// Update the extended line which the cursor is currently on at a column greater than the terminal width. The line will be // scrolled right or left to let the user see where the cursor is. static void vupd_ext(void) { int rcursor; // Real cursor location. Line *lnp; // Pointer to current line. int j; // Index into line. // Calculate what column the real cursor will end up in. rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin; // 10% width <= rcursor < 90% lbound = curcol - rcursor + 1; taboff = lbound + curwp->w_face.wf_fcol; // Write the current line to the virtual screen. vtmove(currow,-taboff); // Start scanning offscreen. lnp = curwp->w_face.wf_dot.lnp; // Line to output. for(j = 0; j < lused(lnp); ++j) // Until the end-of-line. vtputc(lgetc(lnp,j)); // Truncate the virtual line, restore tab offset. vteeol(); taboff = 0; // and put a '$' in column 1. vscreen[currow]->v_text[0] = '$'; }
/* * updone: * update the current line to the virtual screen * * struct window *wp; window to update current line in */ static void updone(struct window *wp) { struct line *lp; /* line to update */ int sline; /* physical screen line to update */ /* search down the line we want */ lp = wp->w_linep; sline = wp->w_toprow; while (lp != wp->w_dotp) { ++sline; lp = lforw(lp); } /* and update the virtual line */ vscreen[sline]->v_flag |= VFCHG; vscreen[sline]->v_flag &= ~VFREQ; vtmove(sline, 0); show_line(lp); #if COLOR vscreen[sline]->v_rfcolor = wp->w_fcolor; vscreen[sline]->v_rbcolor = wp->w_bcolor; #endif vteeol(); }
// Redisplay the mode line for the window pointed to by winp. If popbuf is NULL, display a fully-formatted mode line containing // the current buffer's name and filename (but in condensed form if the current terminal width is less than 96 columns); // otherwise, display only the buffer name and filename of buffer "popbuf". This is the only routine that has any idea of how // the mode line is formatted. You can change the mode line format by hacking at this routine. Called by "update" any time // there is a dirty window. void wupd_modeline(EWindow *winp,Buffer *popbuf) { int c; int n; // Cursor position. Buffer *bufp; ModeSpec *msp; int lchar; int condensed = term.t_ncol < 80 ? -1 : term.t_ncol < 96 ? 1 : 0; char wkbuf[32]; // Work buffer. static struct { // Mode display parameters. int leadch,trailch; uint flags; } *mdp,md[] = { {'(',')',0}, {'[',']',0}, {-1,-1,0}}; n = winp->w_toprow + winp->w_nrows; // Row location. // Note that we assume that setting REVERSE will cause the terminal driver to draw with the inverted relationship of // fcolor and bcolor, so that when we say to set the foreground color to "white" and background color to "black", the // fact that "reverse" is enabled means that the terminal driver actually draws "black" on a background of "white". // Makes sense, no? This way, devices for which the color controls are optional will still get the "reverse" signals. vscreen[n]->v_left = 0; vscreen[n]->v_right = term.t_ncol; #if COLOR vscreen[n]->v_flags |= VFCHGD | VFCOLOR; // Redraw next time. vscreen[n]->v_rfcolor = 7; // Black on. vscreen[n]->v_rbcolor = 0; // White... #else vscreen[n]->v_flags |= VFCHGD; // Redraw next time. #endif vtmove(n,0); // Seek to right line. if(winp == curwp) // Make the current buffer stand out. lchar = '='; #if REVSTA else if(opflags & OPHAVEREV) lchar = ' '; #endif else lchar = '-'; // Full display? if(popbuf == NULL) { bufp = winp->w_bufp; vtputc((bufp->b_flags & BFTRUNC) ? '#' : lchar); // "#" if truncated. vtputc((bufp->b_flags & BFCHGD) ? '*' : lchar); // "*" if changed. vtputc((bufp->b_flags & BFNARROW) ? '<' : lchar); // "<" if narrowed. vtputc(' '); n = 4; // Display program name and version. if(!condensed) { sprintf(wkbuf,"%s %s ",Myself,Version); n += vtputs(wkbuf); } // Are we horizontally scrolled? if(winp->w_face.wf_fcol > 0) { sprintf(wkbuf,"[<%d] ",winp->w_face.wf_fcol); n += vtputs(wkbuf); } // Display the screen number if bottom window and there's more than one screen. if(winp->w_nextp == NULL && scrcount() > 1) { sprintf(wkbuf,"S%hu ",cursp->s_num); n += vtputs(wkbuf); } // Display keyboard macro recording state. if(kmacro.km_state == KMRECORD) n += vtputs("*R* "); // Display the line and/or column point position if enabled and winp is current window. if(winp == curwp) { if(curbp->b_modes & MDLINE) { sprintf(wkbuf,"L:%ld ",getlinenum(bufp,winp->w_face.wf_dot.lnp)); n += vtputs(wkbuf); } if(curbp->b_modes & MDCOL) { sprintf(wkbuf,"C:%d ",getccol()); n += vtputs(wkbuf); } } // Display the modes, in short form if condensed display. md[0].flags = modetab[MDR_GLOBAL].flags & modetab[MDR_SHOW].flags; md[1].flags = winp->w_bufp->b_modes; mdp = md; do { msp = ((c = mdp->leadch) == '[') ? bmodeinfo : gmodeinfo; do { if(mdp->flags & msp->mask) { n += vtputc(c); c = ' '; if(condensed >= 0) n += vtputs(msp->mlname); else { n += vtputc(msp->mlname[0]); if(msp->mlname[1] != '\0') n += vtputc(msp->mlname[1]); } } } while((++msp)->name != NULL); if(c != mdp->leadch) { n += vtputc(mdp->trailch); n += vtputc(' '); } } while((++mdp)->leadch > 0); #if 0 // Display internal modes on modeline. vtputc(lchar); vtputc((winp->w_flags & WFCOLOR) ? 'C' : lchar); vtputc((winp->w_flags & WFMODE) ? 'M' : lchar); vtputc((winp->w_flags & WFHARD) ? 'H' : lchar); vtputc((winp->w_flags & WFEDIT) ? 'E' : lchar); vtputc((winp->w_flags & WFMOVE) ? 'V' : lchar); vtputc((winp->w_flags & WFFORCE) ? 'F' : lchar); vtputc(lchar); n += 8; #endif n += wupd_tab(lchar); } else { n = 0; bufp = popbuf; vtputc(lchar); n += wupd_tab(lchar) + 1; } // Display the buffer name. n += vtputs(bufp->b_bname) + 1; vtputc(' '); // Display the filename in the remaining space using strfit(). if(bufp->b_fname != NULL) { char wkbuf[TT_MAXCOLS]; n += wupd_tab(lchar); if(condensed < 0) { vtputc(*text34); // "File: " vtputc(':'); vtputc(' '); n += 3; } else n += vtputs(text34); // "File: " n += vtputs(strfit(wkbuf,term.t_ncol - n - 1,bufp->b_fname,0)) + 1; vtputc(' '); } // If it's the current window, not a pop-up, "pwd" mode, and room still available, display the working directory as // well. if(winp == curwp && popbuf == NULL && (modetab[MDR_GLOBAL].flags & MDWKDIR) && ((int) term.t_ncol - n) > 12) { char *wdp; char wkbuf[TT_MAXCOLS]; n += wupd_tab(lchar); n += vtputs(text274); // "WD: " (void) getwkdir(&wdp,false); n += vtputs(strfit(wkbuf,term.t_ncol - n - 1,wdp,0)) + 1; vtputc(' '); } // Pad to full width. while(n < (int) term.t_ncol) { vtputc(lchar); ++n; } }
// Display a pop-up window and page it for the user. If altmodeline is true, display buffer name and filename (only) on bottom // mode line. If endprompt is true, wait for user to press a key before returning (regardless of page size). Current bindings // (if any) for backPage, forwPage, backLine, and forwLine commands are recognized as well as 'b' (backward page), 'f' or space // (forward page), 'u' (backward half page), 'd' (forward half page), 'g' (goto first page), 'G' (goto last page), ESC or 'q' // (exit), and '?' (help). Any non-navigation key gets pushed back into the input stream to be interpeted later as a command. // Return status. int bpop(Buffer *bufp,bool altmodeline,bool endprompt) { Line *lnp1,*lnp,*lpmax; int crow; // Current screen row number. int disprows; // Total number of display rows. int halfpage; // Rows in a half page. int n; // Rows to move. ushort ek; // Input extended key. char *strp,*strpz; // Line text pointers. char *hprompt = NULL; // Help prompt; bool firstpass = true; // Display special mode line if requested. if(altmodeline) { // Find last window on screen and rewrite its mode line. wupd_modeline(wnextis(NULL),bufp); } // Set up and display a pop-up "window". disprows = term.t_nrow - 2; // Check if buffer will fit on one page and if not, set lpmax to first line of last page. lpmax = NULL; n = 0; for(lnp = lforw(bufp->b_hdrlnp); lnp != bufp->b_hdrlnp; lnp = lforw(lnp)) { if(++n > disprows) { // Find beginning of last page. lpmax = bufp->b_hdrlnp; n = disprows; do { lpmax = lback(lpmax); } while(--n > 0); break; } } // Begin at the beginning. lnp1 = lforw(bufp->b_hdrlnp); halfpage = disprows / 2; n = 0; // Display a page (beginning at line lnp1 + n) and prompt for a naviagtion command. Loop until exit key entered or // endprompt is false and buffer fits on one page (lpmax is NULL). for(;;) { lnp = lnp1; // Moving backward? if(n < 0) { do { // At beginning of buffer? if(lpmax == NULL || lnp1 == lforw(bufp->b_hdrlnp)) break; // No, back up one line. lnp1 = lback(lnp1); } while(++n < 0); } // Moving forward? else if(n > 0) { do { // At end of buffer or max line? if(lpmax == NULL || lnp1 == bufp->b_hdrlnp || lnp1 == lpmax) break; // No, move forward one line. lnp1 = lforw(lnp1); } while(--n > 0); } // Illegal command? if(n != 0 && lnp1 == lnp) // Yes, ignore it. n = 0; else { // Found first row ... display page. lnp = lnp1; crow = 0; do { // At end of buffer? if(lnp == bufp->b_hdrlnp) { // Yes, erase remaining lines on physical screen. while(crow < disprows) { vtmove(crow,0); vteeol(); #if COLOR vscreen[crow]->v_rfcolor = gfcolor; vscreen[crow]->v_rbcolor = gbcolor; #endif vscreen[crow]->v_left = FARRIGHT; vscreen[crow]->v_right = 0; #if COLOR vscreen[crow++]->v_flags |= VFCHGD | VFCOLOR; #else vscreen[crow++]->v_flags |= VFCHGD; #endif } break; } // Update the virtual screen image for this line. Characters past right edge of screen won't be // displayed, so ignore those. vtmove(crow,0); strpz = (strp = ltext(lnp)) + (lused(lnp) <= (int) term.t_ncol ? lused(lnp) : term.t_ncol); while(strp < strpz) vtputc(*strp++); vteeol(); #if COLOR vscreen[crow]->v_rfcolor = gfcolor; vscreen[crow]->v_rbcolor = gbcolor; #endif vscreen[crow]->v_left = FARRIGHT; vscreen[crow]->v_right = 0; #if COLOR vscreen[crow++]->v_flags |= VFCHGD | VFCOLOR; #else vscreen[crow++]->v_flags |= VFCHGD; #endif // On to the next line. lnp = lforw(lnp); } while(crow < disprows); // Screen is full. Copy the virtual screen to the physical screen. if(pupd_all(false) != SUCCESS) return rc.status; // Bail out if called from terminp() and one-page buffer. if(firstpass && !endprompt && lpmax == NULL) goto uexit; firstpass = false; } // Display prompt. mlputs(MLHOME | MLFORCE,hprompt != NULL ? hprompt : lpmax == NULL || lnp1 == lpmax ? text201 : ": "); // "End: " if(TTflush() != SUCCESS) return rc.status; // Get response. for(;;) { // Get a keystroke and decode it. if(getkey(&ek) != SUCCESS) return rc.status; // Exit? if(ek == (CTRL | '[') || ek == 'q') goto uexit; // Forward whole page? if(ek == ' ' || ek == 'f' || iscmd(ek,forwPage)) { n = disprows - overlap; break; } // Forward half page? if(ek == 'd') { n = halfpage; break; } // Backward whole page? if(ek == 'b' || iscmd(ek,backPage)) { n = overlap - disprows; break; } // Backward half page? if(ek == 'u') { n = -halfpage; break; } // Forward a line? if(iscmd(ek,forwLine)) { n = 1; break; } // Backward a line? if(iscmd(ek,backLine)) { n = -1; break; } // First page? if(ek == 'g') { if(lpmax == NULL || lnp1 == lforw(bufp->b_hdrlnp)) n = -1; // Force beep. else { lnp1 = lforw(bufp->b_hdrlnp); n = 0; } break; } // Last page? if(ek == 'G') { if(lpmax == NULL || lnp1 == lpmax) n = 1; // Force beep. else { lnp1 = lpmax; n = 0; } break; } // Help? if(ek == '?') { StrList msg; // Get string list... if(vopen(&msg,NULL,false) != 0) return vrcset(); // build prompt... if(vputs(text202,&msg) != 0) // "(<SPC>,f" return vrcset(); if(hkey(&msg,forwPage,0) != SUCCESS) return rc.status; if(vputs(text203,&msg) != 0) // ") +page (b" return vrcset(); if(hkey(&msg,backPage,0) != SUCCESS) return rc.status; if(vputs(text204,&msg) != 0) // ") -page (d) +half (u) -half" return vrcset(); if(hkey(&msg,forwLine,'+') != SUCCESS || hkey(&msg,backLine,'-') != SUCCESS) return rc.status; if(vputs(text206,&msg) != 0) // " (g) first (G) last (ESC,q) quit (?) help: " return vrcset(); // and display it. if(vclose(&msg) != 0) return vrcset(); mlputs(MLHOME | MLFORCE,msg.sl_vp->v_strp); } else { // Other key. "Unget" the key for reprocessing and return. tungetc(ek); goto uexit; } } } uexit: uphard(); if(endprompt) mlerase(MLFORCE); return rc.status; }