/* * 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; } }
// 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] = '$'; }
// 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); }
// 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(); }
// 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; }