/* * Extract the word at dot without changing dot position. */ int curtoken(int f, int n, char *token) { struct line *odotp; int odoto, tdoto, odotline, size, r; char c; /* Underscore character is to be treated as "inword" while * processing tokens unlike mg's default word traversal. Save * and restore it's cinfo value so that tag matching works for * identifier with underscore. */ c = cinfo['_']; cinfo['_'] = _MG_W; odotp = curwp->w_dotp; odoto = curwp->w_doto; odotline = curwp->w_dotline; /* Move backword unless we are at the beginning of a word or at * beginning of line. */ if (!atbow()) if ((r = backword(f, n)) == FALSE) goto cleanup; tdoto = curwp->w_doto; if ((r = forwword(f, n)) == FALSE) goto cleanup; /* strip away leading whitespace if any like emacs. */ while (ltext(curwp->w_dotp) && isspace(lgetc(curwp->w_dotp, tdoto))) tdoto++; size = curwp->w_doto - tdoto; if (size <= 0 || size >= MAX_TOKEN || ltext(curwp->w_dotp) == NULL) { r = FALSE; goto cleanup; } strncpy(token, ltext(curwp->w_dotp) + tdoto, size); token[size] = '\0'; r = TRUE; cleanup: cinfo['_'] = c; curwp->w_dotp = odotp; curwp->w_doto = odoto; curwp->w_dotline = odotline; return (r); }
/* * This function does the work of counting matching lines. */ int countmatches(int cond) { int error; int count = 0; struct line *clp; clp = curwp->w_dotp; if (curwp->w_doto == llength(clp)) /* Consider dot on next line */ clp = lforw(clp); while (clp != (curbp->b_headp)) { /* see if line matches */ regex_match[0].rm_so = 0; regex_match[0].rm_eo = llength(clp); error = regexec_new(&re_buff, ltext(clp), RE_NMATCH, regex_match, REG_STARTEND); /* Count line when appropriate */ if ((cond == FALSE && error) || (cond == TRUE && !error)) count++; clp = lforw(clp); } if (cond) ewprintf("Number of lines matching: %d", count); else ewprintf("Number of lines not matching: %d", count); return (TRUE); }
/* * Write a buffer to the already opened file. bp points to the * buffer. Return the status. */ int ffputbuf(FILE *ffp, struct buffer *bp) { struct line *lp, *lpend; lpend = bp->b_headp; for (lp = lforw(lpend); lp != lpend; lp = lforw(lp)) { if (fwrite(ltext(lp), 1, llength(lp), ffp) != llength(lp)) { dobeep(); ewprintf("Write I/O error"); return (FIOERR); } if (lforw(lp) != lpend) /* no implied \n on last line */ putc('\n', ffp); } /* * XXX should be variable controlled (once we have variables) */ if (llength(lback(lpend)) != 0) { if (eyorn("No newline at end of file, add one") == TRUE) { lnewline_at(lback(lpend), llength(lback(lpend))); putc('\n', ffp); } } return (FIOSUC); }
/* * This routine does the real work of a backward search. The pattern is sitting * in the external variable "re_pat". If found, dot is updated, the window * system is notified of the change, and TRUE is returned. If the string isn't * found, FALSE is returned. */ static int re_backsrch(void) { struct line *clp; int tbo; regmatch_t lastmatch; lastmatch.rm_eo = 0; clp = curwp->w_dotp; tbo = curwp->w_doto; /* Start search one position to the left of dot */ tbo = tbo - 1; if (tbo < 0) { /* must move up one line */ clp = lback(clp); tbo = llength(clp); } /* * Note this loop does not process the last line, but this editor * always makes the last line empty so this is good. */ while (clp != (curbp->b_headp)) { regex_match[0].rm_so = 0; regex_match[0].rm_eo = llength(clp); lastmatch.rm_so = -1; /* * Keep searching until we don't match any longer. Assumes a * non-match does not modify the regex_match array. We have to * do this character-by-character after the first match since * POSIX regexps don't give you a way to do reverse matches. */ while (!regexec_new(&re_buff, ltext(clp), RE_NMATCH, regex_match, REG_STARTEND) && regex_match[0].rm_so < tbo) { memcpy(&lastmatch, ®ex_match[0], sizeof(regmatch_t)); regex_match[0].rm_so++; regex_match[0].rm_eo = llength(clp); } if (lastmatch.rm_so == -1) { clp = lback(clp); tbo = llength(clp); } else { memcpy(®ex_match[0], &lastmatch, sizeof(regmatch_t)); curwp->w_doto = regex_match[0].rm_so; curwp->w_dotp = clp; curwp->w_rflag |= WFMOVE; return (TRUE); } } return (FALSE); }
/* * Search through each line of buffer for pattern. */ int searchpat(char *pat) { struct line *lp; int dotline; size_t plen; plen = strlen(pat); dotline = 1; lp = lforw(curbp->b_headp); while (lp != curbp->b_headp) { if (ltext(lp) != NULL && plen <= llength(lp) && (strncmp(pat, ltext(lp), plen) == 0)) { curwp->w_doto = 0; curwp->w_dotp = lp; curwp->w_dotline = dotline; return (TRUE); } else { lp = lforw(lp); dotline++; } } return (FALSE); }
/* ARGSUSED */ int evalbuffer(int f, int n) { struct line *lp; struct buffer *bp = curbp; int s; static char excbuf[128]; for (lp = bfirstlp(bp); lp != bp->b_headp; lp = lforw(lp)) { if (llength(lp) >= 128) return (FALSE); (void)strncpy(excbuf, ltext(lp), llength(lp)); /* make sure it's terminated */ excbuf[llength(lp)] = '\0'; if ((s = excline(excbuf)) != TRUE) return (s); } return (TRUE); }
/* * This function does the work of deleting matching lines. */ static int killmatches(int cond) { int s, error; int count = 0; struct line *clp; clp = curwp->w_dotp; if (curwp->w_doto == llength(clp)) /* Consider dot on next line */ clp = lforw(clp); while (clp != (curbp->b_headp)) { /* see if line matches */ regex_match[0].rm_so = 0; regex_match[0].rm_eo = llength(clp); error = regexec_new(&re_buff, ltext(clp), RE_NMATCH, regex_match, REG_STARTEND); /* Delete line when appropriate */ if ((cond == FALSE && error) || (cond == TRUE && !error)) { curwp->w_doto = 0; curwp->w_dotp = clp; count++; s = ldelete(llength(clp) + 1, KNONE); clp = curwp->w_dotp; curwp->w_rflag |= WFMOVE; if (s == FALSE) return (FALSE); } else clp = lforw(clp); } ewprintf("%d line(s) deleted", count); if (count > 0) curwp->w_rflag |= WFMOVE; return (TRUE); }
/* * This routine does the real work of a forward search. The pattern is * sitting in the external variable "pat". If found, dot is updated, the * window system is notified of the change, and TRUE is returned. If the * string isn't found, FALSE is returned. */ static int re_forwsrch(void) { int tbo, error; struct line *clp; clp = curwp->w_dotp; tbo = curwp->w_doto; if (tbo == clp->l_used) /* * Don't start matching past end of line -- must move to * beginning of next line, unless at end of file. */ if (clp != curbp->b_headp) { clp = lforw(clp); tbo = 0; } /* * Note this loop does not process the last line, but this editor * always makes the last line empty so this is good. */ while (clp != (curbp->b_headp)) { regex_match[0].rm_so = tbo; regex_match[0].rm_eo = llength(clp); error = regexec_new(&re_buff, ltext(clp), RE_NMATCH, regex_match, REG_STARTEND); if (error != 0) { clp = lforw(clp); tbo = 0; } else { curwp->w_doto = regex_match[0].rm_eo; curwp->w_dotp = clp; curwp->w_rflag |= WFMOVE; return (TRUE); } } return (FALSE); }
/* * excline - run a line from a load file or eval-expression. If FKEYS is * defined, duplicate functionality of dobind so function key values don't * have to fit in type char. */ int excline(char *line) { PF fp; struct line *lp, *np; int status, c, f, n; char *funcp, *tmp; char *argp = NULL; long nl; #ifdef FKEYS int bind; KEYMAP *curmap; #define BINDARG 0 /* this arg is key to bind (local/global set key) */ #define BINDNO 1 /* not binding or non-quoted BINDARG */ #define BINDNEXT 2 /* next arg " (define-key) */ #define BINDDO 3 /* already found key to bind */ #define BINDEXT 1 /* space for trailing \0 */ #else /* FKEYS */ #define BINDEXT 0 #endif /* FKEYS */ lp = NULL; if (macrodef || inmacro) { ewprintf("Not now!"); return (FALSE); } f = 0; n = 1; funcp = skipwhite(line); if (*funcp == '\0') return (TRUE); /* No error on blank lines */ line = parsetoken(funcp); if (*line != '\0') { *line++ = '\0'; line = skipwhite(line); if (ISDIGIT(*line) || *line == '-') { argp = line; line = parsetoken(line); } } if (argp != NULL) { f = FFARG; nl = strtol(argp, &tmp, 10); if (*tmp != '\0') return (FALSE); if (nl >= INT_MAX || nl <= INT_MIN) return (FALSE); n = (int)nl; } if ((fp = name_function(funcp)) == NULL) { ewprintf("Unknown function: %s", funcp); return (FALSE); } #ifdef FKEYS if (fp == bindtokey || fp == unbindtokey) { bind = BINDARG; curmap = fundamental_map; } else if (fp == localbind || fp == localunbind) { bind = BINDARG; curmap = curbp->b_modes[curbp->b_nmodes]->p_map; } else if (fp == redefine_key) bind = BINDNEXT; else bind = BINDNO; #endif /* FKEYS */ /* Pack away all the args now... */ if ((np = lalloc(0)) == FALSE) return (FALSE); np->l_fp = np->l_bp = maclcur = np; while (*line != '\0') { argp = skipwhite(line); if (*argp == '\0') break; line = parsetoken(argp); if (*argp != '"') { if (*argp == '\'') ++argp; if ((lp = lalloc((int) (line - argp) + BINDEXT)) == NULL) { status = FALSE; goto cleanup; } bcopy(argp, ltext(lp), (int)(line - argp)); #ifdef FKEYS /* don't count BINDEXT */ lp->l_used--; if (bind == BINDARG) bind = BINDNO; #endif /* FKEYS */ } else { /* quoted strings are special */ ++argp; #ifdef FKEYS if (bind != BINDARG) { #endif /* FKEYS */ lp = lalloc((int)(line - argp) + BINDEXT); if (lp == NULL) { status = FALSE; goto cleanup; } lp->l_used = 0; #ifdef FKEYS } else key.k_count = 0; #endif /* FKEYS */ while (*argp != '"' && *argp != '\0') { if (*argp != '\\') c = *argp++; else { switch (*++argp) { case 't': case 'T': c = CCHR('I'); break; case 'n': case 'N': c = CCHR('J'); break; case 'r': case 'R': c = CCHR('M'); break; case 'e': case 'E': c = CCHR('['); break; case '^': /* * split into two statements * due to bug in OSK cpp */ c = CHARMASK(*++argp); c = ISLOWER(c) ? CCHR(TOUPPER(c)) : CCHR(c); break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c = *argp - '0'; if (argp[1] <= '7' && argp[1] >= '0') { c <<= 3; c += *++argp - '0'; if (argp[1] <= '7' && argp[1] >= '0') { c <<= 3; c += *++argp - '0'; } } break; #ifdef FKEYS case 'f': case 'F': c = *++argp - '0'; if (ISDIGIT(argp[1])) { c *= 10; c += *++argp - '0'; } c += KFIRST; break; #endif /* FKEYS */ default: c = CHARMASK(*argp); break; } argp++; } #ifdef FKEYS if (bind == BINDARG) key.k_chars[key.k_count++] = c; else #endif /* FKEYS */ lp->l_text[lp->l_used++] = c; } if (*line) line++; } #ifdef FKEYS switch (bind) { case BINDARG: bind = BINDDO; break; case BINDNEXT: lp->l_text[lp->l_used] = '\0'; if ((curmap = name_map(lp->l_text)) == NULL) { ewprintf("No such mode: %s", lp->l_text); status = FALSE; free(lp); goto cleanup; } free(lp); bind = BINDARG; break; default: #endif /* FKEYS */ lp->l_fp = np->l_fp; lp->l_bp = np; np->l_fp = lp; np = lp; #ifdef FKEYS } #endif /* FKEYS */ } #ifdef FKEYS switch (bind) { default: ewprintf("Bad args to set key"); status = FALSE; break; case BINDDO: if (fp != unbindtokey && fp != localunbind) { lp->l_text[lp->l_used] = '\0'; status = bindkey(&curmap, lp->l_text, key.k_chars, key.k_count); } else status = bindkey(&curmap, NULL, key.k_chars, key.k_count); break; case BINDNO: #endif /* FKEYS */ inmacro = TRUE; maclcur = maclcur->l_fp; status = (*fp)(f, n); inmacro = FALSE; #ifdef FKEYS } #endif /* FKEYS */ cleanup: lp = maclcur->l_fp; while (lp != maclcur) { np = lp->l_fp; free(lp); lp = np; } free(lp); return (status); }
int insertfile(char *fname, char *newname, int replacebuf) { struct buffer *bp; struct line *lp1, *lp2; struct line *olp; /* line we started at */ struct mgwin *wp; int nbytes, s, nline = 0, siz, x, x2; int opos; /* offset we started at */ int oline; /* original line number */ char *dp; if (replacebuf == TRUE) x = undo_enable(FFRAND, 0); else x = undo_enabled(); lp1 = NULL; if (line == NULL) { line = malloc(NLINE); if (line == NULL) panic("out of memory"); linesize = NLINE; } /* cheap */ bp = curbp; if (newname != NULL) { (void)strlcpy(bp->b_fname, newname, sizeof(bp->b_fname)); dp = xdirname(newname); (void)strlcpy(bp->b_cwd, dp, sizeof(bp->b_cwd)); (void)strlcat(bp->b_cwd, "/", sizeof(bp->b_cwd)); free(dp); } /* hard file open */ if ((s = ffropen(fname, (replacebuf == TRUE) ? bp : NULL)) == FIOERR) goto out; if (s == FIOFNF) { /* file not found */ if (newname != NULL) ewprintf("(New file)"); else ewprintf("(File not found)"); goto out; } else if (s == FIODIR) { /* file was a directory */ if (replacebuf == FALSE) { ewprintf("Cannot insert: file is a directory, %s", fname); goto cleanup; } killbuffer(bp); if ((bp = dired_(fname)) == NULL) return (FALSE); undo_enable(FFRAND, x); curbp = bp; return (showbuffer(bp, curwp, WFFULL | WFMODE)); } else { dp = xdirname(fname); (void)strlcpy(bp->b_cwd, dp, sizeof(bp->b_cwd)); (void)strlcat(bp->b_cwd, "/", sizeof(bp->b_cwd)); free(dp); } opos = curwp->w_doto; oline = curwp->w_dotline; /* * Open a new line at dot and start inserting after it. * We will delete this newline after insertion. * Disable undo, as we create the undo record manually. */ x2 = undo_enable(FFRAND, 0); (void)lnewline(); olp = lback(curwp->w_dotp); undo_enable(FFRAND, x2); nline = 0; siz = 0; while ((s = ffgetline(line, linesize, &nbytes)) != FIOERR) { retry: siz += nbytes + 1; switch (s) { case FIOSUC: /* FALLTHRU */ case FIOEOF: ++nline; if ((lp1 = lalloc(nbytes)) == NULL) { /* keep message on the display */ s = FIOERR; undo_add_insert(olp, opos, siz - nbytes - 1 - 1); goto endoffile; } bcopy(line, <ext(lp1)[0], nbytes); lp2 = lback(curwp->w_dotp); lp2->l_fp = lp1; lp1->l_fp = curwp->w_dotp; lp1->l_bp = lp2; curwp->w_dotp->l_bp = lp1; if (s == FIOEOF) { undo_add_insert(olp, opos, siz - 1); goto endoffile; } break; case FIOLONG: { /* a line too long to fit in our buffer */ char *cp; int newsize; newsize = linesize * 2; if (newsize < 0 || (cp = malloc(newsize)) == NULL) { ewprintf("Could not allocate %d bytes", newsize); s = FIOERR; goto endoffile; } bcopy(line, cp, linesize); free(line); line = cp; s = ffgetline(line + linesize, linesize, &nbytes); nbytes += linesize; linesize = newsize; if (s == FIOERR) goto endoffile; goto retry; } default: ewprintf("Unknown code %d reading file", s); s = FIOERR; break; } } endoffile: /* ignore errors */ ffclose(NULL); /* don't zap an error */ if (s == FIOEOF) { if (nline == 1) ewprintf("(Read 1 line)"); else ewprintf("(Read %d lines)", nline); } /* set mark at the end of the text */ curwp->w_dotp = curwp->w_markp = lback(curwp->w_dotp); curwp->w_marko = llength(curwp->w_markp); curwp->w_markline = oline + nline + 1; /* * if we are at the end of the file, ldelnewline is a no-op, * but we still need to decrement the line and markline counts * as we've accounted for this fencepost in our arithmetic */ if (lforw(curwp->w_dotp) == curwp->w_bufp->b_headp) { curwp->w_bufp->b_lines--; curwp->w_markline--; } else (void)ldelnewline(); curwp->w_dotp = olp; curwp->w_doto = opos; curwp->w_dotline = oline; if (olp == curbp->b_headp) curwp->w_dotp = lforw(olp); if (newname != NULL) bp->b_flag |= BFCHG | BFBAK; /* Need a backup. */ else bp->b_flag |= BFCHG; /* * If the insert was at the end of buffer, set lp1 to the end of * buffer line, and lp2 to the beginning of the newly inserted text. * (Otherwise lp2 is set to NULL.) This is used below to set * pointers in other windows correctly if they are also at the end of * buffer. */ lp1 = bp->b_headp; if (curwp->w_markp == lp1) { lp2 = curwp->w_dotp; } else { /* delete extraneous newline */ (void)ldelnewline(); out: lp2 = NULL; } for (wp = wheadp; wp != NULL; wp = wp->w_wndp) { if (wp->w_bufp == curbp) { wp->w_flag |= WFMODE | WFEDIT; if (wp != curwp && lp2 != NULL) { if (wp->w_dotp == lp1) wp->w_dotp = lp2; if (wp->w_markp == lp1) wp->w_markp = lp2; if (wp->w_linep == lp1) wp->w_linep = lp2; } } } bp->b_lines += nline; cleanup: undo_enable(FFRAND, x); /* return FALSE if error */ return (s != FIOERR); }
/*ARGSUSED */ int diffbuffer(int f, int n) { struct buffer *bp; struct line *lp, *lpend; size_t len; int ret; char *text, *ttext; char * const argv[] = {DIFFTOOL, "-u", "-p", curbp->b_fname, "-", (char *)NULL}; len = 0; /* C-u is not supported */ if (n > 1) return (ABORT); if (access(DIFFTOOL, X_OK) != 0) { dobeep(); ewprintf("%s not found or not executable.", DIFFTOOL); return (FALSE); } if (curbp->b_fname[0] == 0) { dobeep(); ewprintf("Cannot diff buffer not associated with any files."); return (FALSE); } lpend = curbp->b_headp; for (lp = lforw(lpend); lp != lpend; lp = lforw(lp)) { len+=llength(lp); if (lforw(lp) != lpend) /* no implied \n on last line */ len++; } if ((text = calloc(len + 1, sizeof(char))) == NULL) { dobeep(); ewprintf("Cannot allocate memory."); return (FALSE); } ttext = text; for (lp = lforw(lpend); lp != lpend; lp = lforw(lp)) { if (llength(lp) != 0) { memcpy(ttext, ltext(lp), llength(lp)); ttext += llength(lp); } if (lforw(lp) != lpend) /* no implied \n on last line */ *ttext++ = '\n'; } bp = bfind("*Diff*", TRUE); bp->b_flag |= BFREADONLY; if (bclear(bp) != TRUE) { free(text); return (FALSE); } ret = pipeio(DIFFTOOL, argv, text, len, bp); if (ret == TRUE) { eerase(); if (lforw(bp->b_headp) == bp->b_headp) addline(bp, "Diff finished (no differences)."); } free(text); return (ret); }
static void _std getlog(log_header *log, void *extptr) { getloginfo *pli = (getloginfo*)extptr; int puretext = (pli->flags&(LOGTF_DATE|LOGTF_TIME|LOGTF_LEVEL))==0; if (puretext) { spstr ltext; while (log->offset) { if ((log->flags&LOGIF_USED)!=0 && ((pli->flags&LOGTF_LEVEL)==0 || (pli->flags&LOGTF_LEVELMASK)>=(log->flags&LOGIF_LEVELMASK))) { ltext+=(char*)(log+1); } log+=log->offset; } if (pli->flags&LOGTF_DOSTEXT) ltext.replace("\n","\r\n"); // make copy a bit faster pli->rc = (char*)malloc(ltext.length()+1); memcpy(pli->rc, ltext(), ltext.length()); pli->rc[ltext.length()] = 0; } else { TStrings lst; struct tm dt; u32t pdtme = 0; time_t ptme; while (log->offset) { if ((log->flags&LOGIF_USED)!=0 && ((pli->flags&LOGTF_LEVEL)==0 || (pli->flags&LOGTF_LEVELMASK)>=(log->flags&LOGIF_LEVELMASK))) { if (pdtme!=log->dostime) { dostimetotm(pdtme=log->dostime,&dt); ptme = mktime(&dt); } spstr estr, astr; if (pli->flags&LOGTF_DATE) estr.sprintf("%02d.%02d.%02d ",dt.tm_mday,dt.tm_mon+1,dt.tm_year-100); if (pli->flags&LOGTF_TIME) { int sec = dt.tm_sec; if (log->flags&LOGIF_SECOND) sec++; astr.sprintf("%02d:%02d:%02d ",dt.tm_hour, dt.tm_min, sec); estr+=astr; } if (pli->flags&LOGTF_LEVEL) { if (pli->flags&LOGTF_FLAGS) astr.sprintf("[%c%d%c] ",log->flags&LOGIF_REALMODE?'r':' ', log->flags&LOGIF_LEVELMASK,log->flags&LOGIF_DELAY?'d':' '); else astr.sprintf("[%d] ",log->flags&LOGIF_LEVELMASK); estr+=astr; } estr+=(char*)(log+1); if (estr.lastchar()=='\n') estr.dellast(); lst.AddObject(estr,ptme); } log+=log->offset; } int ii,jj; const char *eol = pli->flags&LOGTF_DOSTEXT?"\r\n":"\n"; log_it(2, "%d lines of log queried\n", lst.Count()); for (ii=1;ii<lst.Count();ii++) // we`re can`t fill entire log for 3 seconds if (lst.Objects(ii-1)-lst.Objects(ii)>3) break; // re-order cyclic added lines if (ii<lst.Count()) { spstr t1 = lst.GetTextToStr(eol,ii), t2 = lst.GetTextToStr(eol,0,ii); pli->rc = (char*)malloc(t1.length()+t2.length()+1); memcpy(pli->rc, t1(), t1.length()); memcpy(pli->rc+t1.length(), t2(), t2.length()+1); } else pli->rc = lst.GetText(eol); } }
// 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; }