sources-request@mirror.UUCP (08/27/86)
Submitted by: Alan Klietz <ihnp4!dicome!mn-at1!alan> Mod.sources: Volume 7, Issue 5 Archive-name: rvi/Part02 #!/bin/sh # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # Wrapped by mirror!rs on Wed Aug 27 00:09:58 EDT 1986 # Exit status; set to 1 on "wc" errors or if would overwrite. STATUS=0 # Contents: rv_insert.c rv_linecmd.c rv_misc.c rv_move.c # rv_openline.c rv_put.c rv_redraw.c rv_redraw_ln.c rv_scroll.c # rv_scroll_bk.c rv_search.c rv_shell.c rv_sync.c rv_undo.c echo x - rv_insert.c if test -f rv_insert.c ; then echo rv_insert.c exists, putting output in $$rv_insert.c OUT=$$rv_insert.c STATUS=1 else OUT=rv_insert.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_insert.c//' XX#include "rv.h" XX#include <ctype.h> XX#define ALLOC_LEN 64 /* Size of reallocation chunk */ XXboolean replace_flag; /* TRUE if R command */ XXboolean superquote; /* Set by rv_getchar if char is quoted by ^V */ XXextern INT autoindent; /* Physical autoindent, if opened_line */ XX char *fake_input; /* Set this to fake text into rv_getchar */ XXstatic char fake_buf[512]; /* Buffer for faked characters */ XXextern char *realloc(); XXvoid XXinsert() XX/* XX * Insert input at the current cursor position, replacing XX * text up to lastcol. If lastcol < cursor, no text replaced. XX */ XX{ XX register struct sc_screen *sc; XX register struct li_line *line; XX boolean quick_append; XX INT i; XX char *s, *indentbuf; XX void fake_chars(); XX file.fi_modified = TRUE; XX /* XX * sc_firstcol = first column of insertion. Fixed. XX * sc_lastcol = last column of insertion. Grows. XX * sc_column = current cursor position XX */ XXnextinsert: XX input_mode = TRUE; XX quick_append = FALSE; XX indentbuf = NULL; XX save_Undo(); XX sc = &screen; XX line = sc->sc_curline; XX if (!opened_line) { XX /* XX * Remember insertion for later undo XX */ XX undo.un_firstline = sc->sc_firstline; XX undo.un_lastline = sc->sc_lastline; XX undo.un_validcol = TRUE; XX undo.un_firstcol = sc->sc_firstcol; XX undo.un_inserted = TRUE; XX /* XX * Save overwritten text for later undo XX */ XX yank_cmd = ' '; XX if (sc->sc_lastcol >= sc->sc_column) { XX yank(); XX undo.un_deleted = TRUE; XX } XX } else if (autoindent > 0) { XX /* XX * Fake autoindented tabs and spaces into line XX */ XX fake_input = fake_buf; XX indentbuf = xalloc(autoindent+1); XX i = autoindent / set_tabstops; XX if (set_fortran) XX fake_chars(' ', i * set_tabstops); XX else XX fake_chars('\t', i); XX i = autoindent % set_tabstops; XX fake_chars(' ', i); XX fake_input = fake_buf; XX strcpy(indentbuf, fake_input); XX } XX if (sc->sc_lastcol >= sc->sc_column) XX /* XX * Append '$' to end of replaced text XX */ XX line->li_text[sc->sc_lastcol] = '$'; XX line->li_text = realloc(line->li_text, line->li_width + ALLOC_LEN + 1); XX /* XX * Get and process input chars XX */ XX for (;;) { XX INT ch; XX /* XX * Redisplay line XX * Append is a fast special case XX */ XX if (quick_append) XX quick_append = FALSE; XX else { XX redraw_curline(line->li_text); XX move_cursor(sc->sc_lineno, sc->sc_column); XX } XX ch = rv_getchar(); XX if (superquote) /* If quoted with ^V, skip all processing */ XX goto addchar; XX if (ch == erasechar() || ch == '\b') { XX /* XX * Delete a character if not blackslashed XX */ XX if (sc->sc_column == sc->sc_firstcol) { XX flash(); XX continue; XX } XX if (line->li_text[sc->sc_column-1] == '\\') XX line->li_text[sc->sc_column-1] = ch; XX else XX sc->sc_column--; XX continue; XX } XX if (ch == killchar() || ch == CTRL(X)) { XX /* XX * Delete line if not backslashed XX */ XX if (sc->sc_column == sc->sc_firstcol) { XX /* XX * Already at first column, error XX */ XX flash(); XX continue; XX } XX if (line->li_text[sc->sc_column-1] == '\\') XX line->li_text[sc->sc_column-1] = ch; XX else XX sc->sc_column = sc->sc_firstcol; XX continue; XX } XX switch (ch) { XXcase CTRL([): XXcase '\n': XXcase '\r': XX /* XX * Escape or newline - end insert XX */ XX if (replace_flag) { XX /* XX * Clean up replace mode XX */ XX if (sc->sc_column <= sc->sc_lastcol) { XX register i; XX /* XX * Replace backspaced chars from undo buffer XX */ XX for (i=sc->sc_column; i <= sc->sc_lastcol; ++i) XX if (i < sc->sc_origline.li_width) XX line->li_text[i] = XX sc->sc_origline.li_text[i]; XX } XX /* XX * Chop off backspaced chars at end of line XX */ XX if (sc->sc_lastcol == line->li_width-1 && XX sc->sc_lastcol >= 0) { XX line->li_width = sc->sc_column; XX line->li_text[line->li_width] = '\0'; XX } XX } else { /* insert mode */ XX if (sc->sc_lastcol >= sc->sc_column) { XX register char *s, *s2; XX /* XX * Close up backspaced text XX */ XX s = &line->li_text[sc->sc_column]; XX s2 = &line->li_text[sc->sc_lastcol+1]; XX while (*s++ = *s2++) XX ; XX line->li_width = strlen(line->li_text); XX } XX } XX /* XX * Collapse autoindent if line not altered by user XX */ XX if (opened_line && autoindent > 0 && indentbuf && XX strcmp(indentbuf, line->li_text) == 0) { XX redraw_curline(""); XX sc->sc_column = 0; XX i = autoindent; XX } else { XX redraw_curline(line->li_text); XX i = 0; XX } XX if (indentbuf) XX free(indentbuf); XX if (ch == CTRL([)) { XX input_mode = FALSE; XX replace_flag = FALSE; XX if (sc->sc_column > 0) XX sc->sc_column--; XX move_cursor(sc->sc_lineno, sc->sc_column); XX if (sc->sc_lastcol < sc->sc_firstcol) { XX if (!opened_line) XX undo.un_inserted = FALSE; XX } else XX undo.un_lastcol = sc->sc_column; XX return; XX } else { XX register char *s, *s2; XX /* XX * Continue input on new line XX */ XX s = s2 = &line->li_text[sc->sc_column]; XX toss_undo(); XX openline(1); XX if (i != 0) XX autoindent = i; XX if (*s != '\0') { /* if not at end of line */ XX /* XX * Split line XX */ XX undo.un_validcol = TRUE; XX undo.un_firstcol = 0; XX if (set_autoindent) XX while (isspace(*s)) XX ++s; XX redraw_curline(s); XX xmit_curline(); XX *s2 = '\0'; XX sc->sc_lineno--; XX sc->sc_curline--; XX redraw_curline(sc->sc_curline->li_text); XX save_Undo(); XX xmit_curline(); XX move_cursor(sc->sc_lineno+1, 0); XX save_Undo(); XX } XX goto nextinsert; /* quick recursion */ XX } XX break; XXcase CTRL(W): XX /* XX * Control-W - backspace 1 word XX */ XX /* Implementation deferred */ XX continue; XXcase '\t': XX /* XX * Tab XX */ XX if (set_fortran) { XX /* XX * Fortran source. Expand tab to spaces XX */ XX if (sc->sc_column < 6) { XX /* XX * First tab in fortran program, expand XX * to six spaces XX */ XX fake_input = fake_buf; XX fake_chars(' ', 6-sc->sc_column); XX fake_input = fake_buf; XX continue; XX } XX /* XX * Expand other tabs to shiftwidth spaces XX */ XX i = set_shiftwidth - (sc->sc_column % set_shiftwidth); XX fake_input = fake_buf; XX fake_chars(' ', i); XX fake_input = fake_buf; XX continue; XX } XX break; XXcase CTRL(D): XX /* XX * Backtab XX */ XX if (sc->sc_column == sc->sc_firstcol) { XX flash(); XX continue; XX } XX i = screen_column(line->li_text, sc->sc_column); XX i -= i % set_shiftwidth == 0 ? XX set_shiftwidth : i % set_shiftwidth; XX i = file_column(line->li_text, i); XX if (set_fortran && i < 6 && sc->sc_column > 6) XX i = 6; XX fake_input = fake_buf; XX fake_chars('\b', sc->sc_column - i); XX fake_input = fake_buf; XX continue; XX } /* End switch */ XX XX /* XX * Add character to line XX */ XXaddchar: XX /* XX * Check if line needs expansion XX */ XX if (sc->sc_lastcol < sc->sc_column) { XX if (!replace_flag || sc->sc_column >= line->li_width) { XX register char *s, *s2; XX /* XX * Expand line 1 character XX */ XX line->li_width++; XX /* XX * Expand line in chunks of ALLOC_LEN XX */ XX if (line->li_width % ALLOC_LEN == 0) XX line->li_text = realloc(line->li_text, XX line->li_width + ALLOC_LEN+1); XX if (sc->sc_column == line->li_width-1 && XX ch >= '@' && CURCOLUMN > 0) { XX /* XX * Fast special case - add char at XX * eol. No control chars, no char, XX * shifting, and no line shifting XX * required. XX */ XX quick_append = TRUE; XX addch(ch); XX line->li_text[line->li_width] = '\0'; XX#ifndef USG XX /* XX * KLUDGE - Handle VT100 brain damage XX * until Berkeley fixes up curses to XX * handle it. XX */ XX if (XN && CURCOLUMN==0) { XX addch(' '); XX refresh(); XX addch('\b'); XX } XX#endif XX } else { XX /* XX * Slide text beyond insert right XX */ XX s = &line->li_text[line->li_width-1]; XX s2 = &line->li_text[sc->sc_column]; XX while (s >= s2) { XX *(s+1) = *s; XX --s; XX } XX } XX } XX sc->sc_lastcol++; XX if (sc->sc_lastcol < sc->sc_firstcol) XX sc->sc_lastcol = sc->sc_firstcol; XX } XX /* XX * Insert character XX */ XX line->li_text[sc->sc_column++] = ch; XX } XX} XXINT XXrv_getchar() XX/* XX * Get a character from the keyboard. XX * Parse ^V as a super quote. XX */ XX{ XX INT ch; XX superquote = FALSE; XX /* XX * Check for fake input XX */ XX if (fake_input && *fake_input != '\0') XX return(*fake_input++); XX refresh(); XX while ((ch = getch()) == '\0') /* null is verboten */ XX ; XX if (ch == CTRL(V)) { XX raw(); /* Allow ^S, ^Q and interrupt keys */ XX insch('^'); XX /* XX * Get raw character, null is verboten. XX */ XX refresh(); XX while ((ch = getch()) == '\0') XX ; XX noraw(); XX#ifdef USG XX cbreak(); XX#else XX crmode(); XX#endif !USG XX superquote = (ch != '\n'); XX } XX if (ch == ERR || ch == EOF) XX quit(); XX return(ch); XX} XXvoid XXdup_insert(count) XX/* XX * Duplicate the text found between firstcol and column XX */ XXINT count; XX{ XX register struct sc_screen *sc; XX register struct li_line *line; XX register char *buf, *s, *s1, *s2; XX sc = &screen; XX line = sc->sc_curline; XX /* XX * Make sure duplicatable section exists XX */ XX if (count <= 1 || sc->sc_column < sc->sc_firstcol XX || sc->sc_lastcol < sc->sc_firstcol) XX return; XX sc->sc_column++; XX /* XX * Get buffer space XX */ XX buf = xalloc(strlen(line->li_text)+1 + (sc->sc_column - XX sc->sc_firstcol) * count); XX /* XX * Copy text up to duplicatable section XX */ XX s = buf; XX s1 = line->li_text; XX s2 = &line->li_text[sc->sc_column]; XX while (s1 < s2) XX *s++ = *s1++; XX /* XX * Duplicate section XX */ XX while (--count > 0) { XX s1 = &line->li_text[sc->sc_firstcol]; XX while (s1 < s2) XX *s++ = *s1++; XX } XX /* XX * Position cursor at last character of last duplicated section XX */ XX sc->sc_column = (s - buf) - 1; XX /* XX * Set up for undo XX */ XX if (!opened_line) { XX undo.un_inserted = TRUE; XX undo.un_validcol = TRUE; XX undo.un_firstline = undo.un_lastline = sc->sc_lineno; XX undo.un_firstcol = sc->sc_firstcol; XX undo.un_lastcol = sc->sc_column; XX } XX /* XX * Copy remainder of line XX */ XX while (*s++ = *s2++) XX ; XX redraw_curline(buf); XX free(buf); XX move_cursor(sc->sc_lineno, sc->sc_column); XX} XXvoid XXfake_chars(ch, count) XXchar ch; XXregister INT count; XX{ XX register char *s; XX s = fake_input; XX for (; count > 0; --count) XX *s++ = ch; XX *s = '\0'; XX fake_input = s; XX} @//E*O*F rv_insert.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_linecmd.c if test -f rv_linecmd.c ; then echo rv_linecmd.c exists, putting output in $$rv_linecmd.c OUT=$$rv_linecmd.c STATUS=1 else OUT=rv_linecmd.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_linecmd.c//' XX#include "rv.h" XX#include <ctype.h> XXboolean ed_undo; /* Set TRUE if last mod was direct ed cmd */ XXextern boolean did_botprint; /* used by botprint() */ XXstatic struct cm_cmdlist { /* Commands */ XX char cm_cmd[12]; XX INT cm_index; XX} cmdlist[] = { XX "E", 3, XX "Q", 2, XX "edit", 3, XX "file", 5, XX "next", 4, XX "quit", 2, XX "se", 1, XX "set", 1, XX "sh", 8, XX "shell",8, XX "w", 6, XX "wq", 7, XX "write", 6, XX "xit", 7, XX "z", 7, XX}; XXstatic struct op_oplist { /* Options */ XX char op_option[12]; XX INT op_index; XX} oplist[] = { XX "ai", 1, XX "all", 2, XX "autoindent", 1, XX "debug", 3, XX "fortran", 4, XX "list", 5, XX "scroll", 6, XX "shiftwidth", 7, XX "sw", 7, XX "tabstops", 8, XX "timeout", 10, XX "to", 10, XX "ts", 8, XX "wrapscan", 9, XX "ws", 9, XX}; XXvoid XXrv_linecmd(cmd) XX/* XX * Execute command line XX */ XXchar *cmd; XX{ XX register char *s, *s2; XX INT i, j; XX boolean flag; XX char buf[12]; XX XX if ((s2 = cmd) == NULL || *s2 == '\0') XX return; XX while (isalnum(*s2)) XX ++s2; XX j = *s2; XX *s2 = '\0'; XX i = binsearch(cmd, (char *) cmdlist, sizeof(struct cm_cmdlist), XX sizeof(cmdlist) / sizeof(struct cm_cmdlist)); XX if (i >= 0) XX i = cmdlist[i].cm_index; XX *s2 = j; XX xmit_curline(); XX switch(i) { XXcase 1: XX /* XX * Set XX */ XX if (*s2 == '\0') XX s2 = "all"; XX for (;;) { XX while (isspace(*s2) && *s2 != '\0') XX ++s2; XX if (*s2 == '\0') XX break; XX s = s2; XX while (isalnum(*s2)) XX ++s2; XX if (*s2 != '\0') XX *s2++ = '\0'; XX if (*s == 'n' && *(s+1) == 'o') { XX s += 2; XX flag = FALSE; XX } else XX flag = TRUE; XX i = binsearch(s, (char *) oplist, sizeof(struct op_oplist), XX sizeof(oplist) / sizeof(struct op_oplist)); XX if (i >= 0) XX i = oplist[i].op_index; XX switch (i) { XX case -2: XX botprint(TRUE, "\"%s\" is not unique\n", s); XX break; XX case -1: XX botprint(TRUE, "\"%s\": No such option - 'set all' gives all option values\n", s); XX return; XX case 1: /* autoindent */ XX set_autoindent = flag; XX break; XX XX case 2: /* all */ XX botprint(FALSE, "%sautoindent\n", set_autoindent ? XX "" : "no"); XX botprint(FALSE, "debug=%d\n", set_debug); XX botprint(FALSE, "%sfortran\n", set_fortran ? "" : XX "no"); XX botprint(FALSE, "%slist", set_list ? "" : "no"); XX botprint(FALSE, "scroll=%d\n", set_scroll); XX botprint(FALSE, "shiftwidth=%d\n", set_shiftwidth); XX botprint(FALSE, "tabstops=%d\n", set_tabstops); XX botprint(FALSE, "%stimeout", set_timeout ? "" : "no"); XX botprint(FALSE, "%swrapscan", set_wrapscan ? "" : "no"); XX break; XX case 3: /* debug */ XX set_debug = atoi(s2); XX while (isdigit(*s2)) XX ++s2; XX break; XX case 4: XX set_fortran = flag; XX break; XX case 5: set_list = flag; XX fetch_window(screen.sc_lineno-NUM_WINDOW_LINES/4- XX LINES-2+1, TRUE); XX break; XX case 6: /* scroll */ XX set_scroll = atoi(s2); XX while (isdigit(*s2)) XX ++s2; XX if (set_scroll <= 0) XX set_scroll = 1; XX break; XX case 7: /* shiftwidth */ XX set_shiftwidth = atoi(s2); XX while (isdigit(*s2)) XX ++s2; XX if (set_shiftwidth <= 0) XX set_shiftwidth = 1; XX else if (set_shiftwidth > 40) XX set_shiftwidth = 40; XX break; XX case 8: /* tabstops */ XX set_tabstops = atoi(s2); XX while (isdigit(*s2)) XX ++s2; XX if (set_tabstops <= 0) XX set_tabstops = 1; XX else if (set_tabstops > 40) XX set_tabstops = 40; XX break; XX case 9: /* wrapscan */ XX set_wrapscan = flag; XX break; XX case 10: /* timeout */ XX set_timeout = flag; XX#ifdef USG XX keypad(stdscr, flag ? 1 : 2); XX#endif XX break; XX default: XX botprint(FALSE, "That option is not yet implemented\n"); XX break; XX } XX } XX break; XXcase 2: /* quit */ XX if (file.fi_modified && *s2 != '!') { XX botprint(TRUE, "No write since last change (:q! overrides)"); XX return; XX } XX Quit(); XX break; XXcase 3: /* edit */ XX if (file.fi_modified && *s2 != '!') { XX botprint(TRUE, "No write since last change (:edit! overrides)"); XX return; XX } XX if (*s2 == '!') XX ++s2; XX while (isspace(*s2)) XX ++s2; XX edit(s2); XX break; XXcase 4: /* next */ XX if (file.fi_modified && *s2 != '!') { XX botprint(TRUE, "No write since last change (:next! overrides)"); XX return; XX } XX if (*s2 == '!') XX ++s2; XX while (isspace(*s2)) XX ++s2; XX if (*s2 == '\0' && *nextfile == '\0') { XX botprint(TRUE, "No more files to edit"); XX return; XX } XX edit(s2); XX break; XXcase 5: /* file */ XX while (isspace(*s2)) XX ++s2; XX if (*s2 == '\0') { XX sizemsg(); XX return; XX } XX xmit_ed("f %s\n", s2); XX strncpy(file.fi_name, s2, 126); XX xmit_sync(); XX (void) recv_sync(TRUE); XX sizemsg(); XX break; XXcase 6: /* write */ XX i = 0; XX if (*s2 == '!') { XX ++s2; XX i = 1; XX } XX while (isspace(*s2)) XX ++s2; XX if (*s2 == '\0' && file.fi_name[0] == '\0') { XX botprint(TRUE, "No current filename"); XX return; XX } XX if (i) XX xmit_ed("!rm -f %s\n", *s2 ? s2 : file.fi_name); XX if (*s2) XX xmit_ed("w %s\n", s2); XX else { XX xmit_ed("w\n"); XX s2 = file.fi_name; XX } XX xmit_sync(); XX botprint(FALSE, "\"%s\"", s2); XX hitcr_continue(); XX refresh(); XX if (recv_sync(TRUE)) { XX botprint(FALSE, "\"%s\" %d lines", s2, file.fi_numlines); XX if (strcmp(s2, file.fi_name) == 0) XX file.fi_modified = FALSE; XX } XX else XX hitcr_continue(); XX break; XXcase 7: /* wq */ XX if (file.fi_modified) XX rv_linecmd("w"); XX if (!file.fi_modified) XX rv_linecmd("q"); XX break; XXcase 8: /* shell */ XX rv_shell("sh -i"); XX break; XX XXdefault: XX if (*s2 == '!') { /* Shell escape */ XX if (strcmp(++s2, "sh") == 0) XX s2 = "sh -i"; XX else if (strcmp(s2, "csh") == 0) XX s2 = "csh -i"; XX rv_shell(s2); XX return; XX } XX did_botprint = TRUE; XX i = cmd[strlen(cmd)-1]; XX if (i == 'a' || i == 'c' || i == 'i' || i == 'H' || i == 'X' XX || i == 'P') { XX botprint(FALSE, "That command is reserved"); XX return; XX } XX toss_undo(); XX if (i == 'w') { XX ed_undo = FALSE; XX file.fi_modified = FALSE; XX } else XX ed_undo = TRUE; XX xmit_ed("%d\n", screen.sc_lineno); XX xmit_sync(); XX xmit_ed("%s\n", cmd); XX xmit_sync(); XX xmit_ed(".=\n"); XX (void) recv_sync(FALSE); XX (void) recv_sync(2); XX (void) fgets(buf, 10, file.fi_fpin); XX if ((i = atoi(buf)) <= 0) XX i = screen.sc_lineno; XX hitcr_continue(); XX fetch_window(i-NUM_WINDOW_LINES/4-LINES/2+1, TRUE); XX move_abs_cursor(i, COL_FIRST_NONWHITE); XX break; XX } XX} @//E*O*F rv_linecmd.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_misc.c if test -f rv_misc.c ; then echo rv_misc.c exists, putting output in $$rv_misc.c OUT=$$rv_misc.c STATUS=1 else OUT=rv_misc.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_misc.c//' XX#include "rv.h" XX/* XX * Miscellaneous subroutines XX */ XXchar *xalloc(n) XX/* XX * Allocate and zero n bytes XX */ XX{ XX char *s; XX char *malloc(); XX if ((s = malloc(n)) == NULL) { XX write(2, "Out of memory", 13); XX endwin(); XX exit(1); XX } XX zero(s, n); XX return s; XX} XXboolean did_botprint; /* True if botprint() was already called */ XXboolean scrolled; /* True if screen scrolled from a call */ XX/*VARARGS1*/ XXvoid XXbotprint(standout_flag, txt, arg1, arg2, arg3, arg4, arg5) XX/* XX * Printf line(s) on bottom of screen with the given attribute(s). XX */ XXINT standout_flag; XXchar *txt, *arg1, *arg2, *arg3, *arg4, *arg5; XX{ XX char buf[512]; XX INT oldrow, oldcol, l; XX oldrow = CURLINE; XX oldcol = CURCOLUMN; XX sprintf(buf, txt, arg1, arg2, arg3, arg4, arg5); XX l = strlen(buf); XX if (l > 0 && buf[l-1] == '\n') /* Remove trailing \n */ XX buf[--l] = '\0'; XX move(LINES-1, 0); XX if (did_botprint) { XX rv_fscroll(1); XX move(LINES-1, 0); XX scrolled = TRUE; XX } XX else XX clrtoeol(); XX if (standout_flag) XX standout(); XX addstr(buf); XX if (standout_flag) XX standend(); XX while (l > 0 && buf[l-1] == '\n') { XX buf[--l] = '\0'; XX /* scroll(stdscr); */ XX scrolled = TRUE; XX } XX did_botprint = TRUE; XX if (l >= COLS || l > CURCOLUMN) XX scrolled = TRUE; XX move(oldrow, oldcol); XX} XXhitcr_continue() XX{ XX INT oldrow, oldcol; XX INT c; XX if (scrolled) { XX /* XX * Screen scrolled. Redraw XX */ XX oldrow = CURLINE; XX oldcol = CURCOLUMN; XX move(LINES-1,0); XX rv_fscroll(1); XX move(LINES-1, 0); XX standout(); XX addstr("[Hit return to continue]"); XX standend(); XX refresh(); XX while ((c = getch()) != '\r' && c != '\n' && c != ' ') XX ; XX redraw_screen((struct li_line *) 0); XX move(oldrow, oldcol); XX scrolled = FALSE; XX } XX did_botprint = FALSE; XX} XXvoid XXpanic(msg) XX/* XX * Print msg and abort XX */ XXchar *msg; XX{ XX botprint(TRUE, "Fatal error: %s\n", msg); XX move(LINES-1, 0); XX rv_fscroll(1); XX move(LINES-1, 0); XX refresh(); XX endwin(); XX exit(1); XX} XXvoid XXsizemsg() XX{ XX if (file.fi_name[0] == '\0' || strcmp(file.fi_name, "/dev/null") == 0) XX botprint(0, "No file line %d of %d --%d%%--", XX screen.sc_lineno, file.fi_numlines, XX (screen.sc_lineno*100) / file.fi_numlines); XX else XX botprint(0, "\"%s\" %sline %d of %d --%d%%--", file.fi_name, XX file.fi_modified ? "[modified] " : "", XX screen.sc_lineno, file.fi_numlines, XX (screen.sc_lineno*100) / file.fi_numlines); XX} XXvoid XXrv_debug() XX{ XX botprint(FALSE, "Absolute:\n"); XX botprint(FALSE, "wi_topline=%d, wi_botline=%d\n", XX window.wi_topline - &line_array[0], XX window.wi_botline - &line_array[0]); XX botprint(FALSE, "sc_topline=%d, sc_botline=%d, sc_curline=%d\n", XX screen.sc_topline - &line_array[0], XX screen.sc_botline - &line_array[0], XX screen.sc_curline - &line_array[0]); XX botprint(FALSE, "sc_lineno=%d, fi_numlines=%d\n", XX screen.sc_lineno, file.fi_numlines); XX botprint(FALSE, "Relative to window:\n"); XX botprint(FALSE, "sc_topline=%d, sc_botline=%d, sc_curline=%d\n", XX screen.sc_topline - window.wi_topline, XX screen.sc_botline - window.wi_topline, XX screen.sc_curline - window.wi_topline); XX} @//E*O*F rv_misc.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_move.c if test -f rv_move.c ; then echo rv_move.c exists, putting output in $$rv_move.c OUT=$$rv_move.c STATUS=1 else OUT=rv_move.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_move.c//' XX#include "rv.h" XX#include <ctype.h> XX/* XX * rv_move.c - Cursor motion routines XX */ XXvoid XXmove_abs_cursor(lineno, column) XX/* XX * Move cursor to absolute position in file. Try to stay within the window XX * if possible. XX */ XXINT lineno, column; XX{ XX register INT seg; XX register struct li_line *line, *newline; XX register struct sc_screen *sc; XX register struct wi_window *wi; XX INT oldlineno, offset; XX struct fi_file *fi; XX void rv_scroll(), rv_scroll_backward(); XX sc = &screen; XX wi = &window; XX fi = &file; XX errflag = 0; XX /* XX * Boundary checks XX */ XX if (lineno < 1) { /* If past top of file */ XX errflag = 1; XX flash(); XX return; XX } else if (lineno > fi->fi_numlines) { /* If past bottom of file */ XX errflag = 1; XX flash(); XX return; XX } XX if (lineno < sc->sc_lineno - (sc->sc_curline-sc->sc_topline)) { XX /* XX * Past top of screen XX */ XX oldlineno = sc->sc_lineno; XX if (lineno < sc->sc_lineno - (sc->sc_curline-wi->wi_topline)) { XX /* XX * Past top of window, fetch more data XX */ XX fetch_window(lineno-NUM_WINDOW_LINES/4-LINES/2+1, XX FALSE); XX if (errflag) XX return; XX } XX newline = sc->sc_curline - (sc->sc_lineno - lineno); XX seg = 0; XX if (oldlineno == sc->sc_lineno) { /* If relatively close */ XX /* XX * Find distance, in segments, above top of screen XX */ XX for (line = newline; line < sc->sc_topline; ++line) XX seg += line->li_segments; XX if (seg <= LINES/3+1) { /* If very close */ XX /* XX * Scroll backwards XX */ XX rv_scroll_backward(sc->sc_topline - newline); XX move_cursor(lineno, column); XX return; XX } XX } XX /* XX * Newline is too far away for scrolling, XX * so we redraw the screen and deposit newline XX * in the center. XX */ XX /* XX * Set the top of the screen at LINES/2 segments above newline XX */ XX xmit_curline(); XX seg = LINES/2; XX for (line = newline; line >= wi->wi_topline && seg > 0; --line) XX seg -= line->li_segments; XX sc->sc_topline = line+1; XX sc->sc_curline = newline; XX sc->sc_lineno = lineno; XX sc->sc_abovetop = 0; XX /* XX * Compute bottom line XX */ XX line = sc->sc_topline; XX for (seg = line->li_segments; seg < LINES; XX seg += line->li_segments) { XX ++line; XX if (line > wi->wi_botline) XX break; XX } XX sc->sc_botline = line-1; XX /* XX * Update the screen to curses XX */ XX move_cursor(lineno, column); XX redraw_screen((struct li_line *)0); XX return; XX } /* End of past top of screen */ XX XX if (lineno > sc->sc_lineno + (sc->sc_botline - sc->sc_curline)) { XX /* XX * Past bottom of screen XX */ XX oldlineno = sc->sc_lineno; XX offset = sc->sc_botline - sc->sc_curline; XX if (lineno > sc->sc_lineno + (wi->wi_botline-sc->sc_curline)) { XX /* XX * Past bottom of window XX */ XX fetch_window(lineno-NUM_WINDOW_LINES/4-LINES/2+1, XX TRUE); XX if (errflag) XX return; XX } XX newline = sc->sc_curline + (lineno - sc->sc_lineno); XX seg = 0; XX if (oldlineno == sc->sc_lineno) { /* If relatively close */ XX /* XX * Find distance in segments past bottom of screen XX */ XX for (line = sc->sc_curline+offset+1; line <= newline; XX ++line) XX seg += line->li_segments; XX if (seg <= LINES/3+1 && newline >= sc->sc_botline) { XX /* XX * Scroll screen forwards XX */ XX rv_scroll(newline - sc->sc_botline); XX move_cursor(lineno, column); XX return; XX } XX } XX /* XX * Newline is too far away for scrolling, XX * so we redraw the screen and deposit newline XX * in the center. XX */ XX /* XX * Set the top of the screen at LINES/2 segments above newline XX */ XX xmit_curline(); XX seg = LINES/2; XX for (line = newline; line >= wi->wi_topline && seg > 0; --line) XX seg -= line->li_segments; XX sc->sc_abovetop = 0; XX sc->sc_topline = line+1; XX sc->sc_curline = newline; XX sc->sc_lineno = lineno; XX /* XX * Compute bottom line XX */ XX line = sc->sc_topline; XX for (seg = line->li_segments; seg < LINES; XX seg += line->li_segments) { XX ++line; XX if (line > wi->wi_botline) XX break; XX } XX sc->sc_botline = line-1; XX /* XX * Update the screen to curses XX */ XX move_cursor(lineno, column); XX redraw_screen((struct li_line *)0); XX return; XX } /* End of past bottom of screen */ XX XX /* XX * Otherwise, newline must already be on the screen XX */ XX move_cursor(lineno, column); XX return; XX} XXvoid XXmove_cursor(lineno, column) XX/* XX * Move cursor to position in file. Must already be on screen. XX */ XXINT lineno, column; XX{ XX register INT seg; XX register struct sc_screen *sc; XX register struct li_line *line, *newline; XX INT linewidth; XX static INT prev_column; XX errflag = 0; XX sc = &screen; XX newline = sc->sc_curline + (lineno - sc->sc_lineno); XX /* XX * Boundary checks XX */ XX if (newline < sc->sc_topline || newline > sc->sc_botline) { XX errflag = 1; XX botprint(TRUE,"move_cursor, lineno %d beyond screen\n", lineno); XX return; XX } XX if (column == COL_SAME) XX column = file_column(newline->li_text, prev_column); XX else { XX prev_column = -1; XX if (column == COL_FIRST_NONWHITE) { XX register char *s; XX s = newline->li_text; XX while (*s != '\0' && isspace(*s)) XX ++s; XX column = s - newline->li_text; XX } XX } XX XX if (column < 0) { /* If past left side of screen */ XX if (sc->sc_column == 0) { /* Already at left side? */ XX errflag = 1; XX flash(); XX return; XX } XX column = 0; XX } XX if (lineno != sc->sc_lineno && sc->sc_origline.li_text != NULL) XX xmit_curline(); XX /* XX * Compute screen column and segment # XX */ XX sc->sc_curline = newline; XX sc->sc_lineno = lineno; XX /* XX * Limit column to end of line (or line+1 if input mode) XX */ XX linewidth = newline->li_width + (input_mode ? 1 : 0); XX if (column >= linewidth && column > 0) { XX column = (linewidth == 0 ? 0 : linewidth-1); XX if (sc->sc_column >= column) /* If already at edge */ XX flash(); XX } XX sc->sc_column = column; XX column = screen_column(newline->li_text, column); XX if (prev_column < 0) XX prev_column = column; XX if (input_mode && sc->sc_column == linewidth-1 && sc->sc_column != 0) XX ++column; XX seg = 0; XX for (line=sc->sc_topline; line < newline; ++line) XX seg += line->li_segments; XX seg += column / COLS + sc->sc_abovetop; XX column %= COLS; XX if (seg >= LINES) { XX errflag = 1; XX botprint(TRUE, "move_cursor, seg %d beyond screen\n", seg); XX return; XX } XX /* XX * Update cursor to curses XX */ XX move(seg, column); XX} @//E*O*F rv_move.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_openline.c if test -f rv_openline.c ; then echo rv_openline.c exists, putting output in $$rv_openline.c OUT=$$rv_openline.c STATUS=1 else OUT=rv_openline.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_openline.c//' XX#include "rv.h" XX#include <ctype.h> XXboolean opened_line; /* Set TRUE if openline() called */ XXINT autoindent; /* Physical autoindent, used by insert() */ XXvoid XXopenline(direction) XX/* XX * Openline - Open new line. XX * XX * If direction < 0, open above current line, else XX * open below current line. XX */ XXINT direction; XX{ XX register struct li_line *line; XX register struct sc_screen *sc; XX register struct wi_window *wi; XX char *s; XX sc = &screen; XX wi = &window; XX file.fi_modified = TRUE; XX xmit_curline(); XX opened_line = TRUE; XX /* XX * Calculate autoindent XX */ XX autoindent = 0; XX if (set_autoindent) { XX s = sc->sc_curline->li_text; XX while (isspace(*s) && *s != '\0') XX if (*s++ == '\t') XX autoindent += set_tabstops; XX else XX autoindent++; XX } XX /* XX * Send blank line to ed XX */ XX if (direction >= 0) { XX xmit_ed("%da\n\n.\n", sc->sc_lineno); XX sc->sc_lineno++; XX sc->sc_curline++; XX } else XX xmit_ed("%di\n\n.\n", sc->sc_lineno); XX if (sc->sc_curline <= wi->wi_botline || XX wi->wi_botline < &line_array[NUM_WINDOW_LINES-1]) { XX /* XX * Case 1,2,3: Opening line at top of window, within window, XX * or bottom of expandable window XX */ XX /* XX * Scroll off bottom line of window if necessary XX */ XX if (wi->wi_botline >= &line_array[NUM_WINDOW_LINES-1]) { XX if (wi->wi_botline->li_text) XX free(wi->wi_botline->li_text); XX wi->wi_botline->li_text = NULL; XX wi->wi_botline--; XX } XX /* XX * Slide down window beyond line XX */ XX for (line = wi->wi_botline; line >= sc->sc_curline; --line) { XX (line+1)->li_width = line->li_width; XX (line+1)->li_segments = line->li_segments; XX (line+1)->li_text = line->li_text; XX } XX wi->wi_botline++; XX } else { XX /* XX * Case 4: Opening line beyond edge of unexpandable window XX */ XX sc->sc_curline--; XX /* XX * Scroll off topline of window if necessary XX */ XX if (wi->wi_topline <= &line_array[0]) { XX if (wi->wi_topline->li_text) XX free(wi->wi_topline->li_text); XX wi->wi_topline->li_text = NULL; XX wi->wi_topline++; XX } XX /* XX * Slide up window XX */ XX for (line = wi->wi_topline; line < sc->sc_curline; ++line) { XX (line-1)->li_width = line->li_width; XX (line-1)->li_segments = line->li_segments; XX (line-1)->li_text = line->li_text; XX } XX wi->wi_topline--; XX sc->sc_topline--; XX sc->sc_botline--; XX } XX /* XX * Create the empty line XX */ XX line = sc->sc_curline; XX line->li_width = 0; XX line->li_segments = 1; XX line->li_text = xalloc(1); XX line->li_text[0] = '\0'; XX if (line > wi->wi_botline) XX wi->wi_botline = line; XX file.fi_numlines++; XX /* XX * Set up for insert() XX */ XX sc->sc_firstcol = 0; XX sc->sc_lastcol = -1; XX /* XX * Remember opened line for later undo XX */ XX undo.un_validcol = FALSE; XX undo.un_firstline = sc->sc_lineno; XX undo.un_lastline = sc->sc_lineno; XX undo.un_inserted = TRUE; XX /* XX * Update line to curses XX */ XX if (line > sc->sc_botline) { XX redraw_screen(sc->sc_botline+1); XX move_cursor(sc->sc_lineno, 0); XX } else { XX move_cursor(sc->sc_lineno, 0); XX rv_finsertln(1); XX redraw_screen(sc->sc_botline); XX } XX} @//E*O*F rv_openline.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_put.c if test -f rv_put.c ; then echo rv_put.c exists, putting output in $$rv_put.c OUT=$$rv_put.c STATUS=1 else OUT=rv_put.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_put.c//' XX#include "rv.h" XXextern char *realloc(); XXvoid XXput(direction) XX/* XX * Put buffer at cursor. XX */ XXINT direction; /* Negative if above cursor */ XX{ XX register struct li_line *line; XX register struct ya_yank *yank; XX register struct sc_screen *sc; XX INT indx; XX sc = &screen; XX line = sc->sc_curline; XX indx = char_to_yank(yank_cmd); XX if (errflag) { XX flash(); XX return; XX } XX yank = &yank_array[indx]; XX file.fi_modified = TRUE; XX if (yank->ya_type == YANK_EMPTY) { XX errflag = 1; XX if (yank_cmd == ' ') XX flash(); XX else XX botprint(TRUE, "Register %c is empty", yank_cmd); XX return; XX } XX undo.un_inserted = TRUE; XX undo.un_firstline = undo.un_lastline = sc->sc_lineno; XX undo.un_validcol = FALSE; XX if (yank->ya_type == YANK_COLS) { XX /* XX * Put text within line XX */ XX register char *s, *s2, *s3; XX save_Undo(); XX undo.un_validcol = sc->sc_validcol = TRUE; XX undo.un_firstcol = sc->sc_firstcol = sc->sc_column+1; XX undo.un_lastcol = sc->sc_lastcol = sc->sc_column+yank->ya_width; XX line->li_text = realloc(line->li_text, line->li_width + XX yank->ya_width + 1); XX s = &line->li_text[sc->sc_firstcol]; XX s2 = &line->li_text[line->li_width]; XX s3 = &line->li_text[line->li_width + yank->ya_width]; XX while (s2 >= s) XX *s3-- = *s2--; XX s2 = yank->ya_text; XX while (*s2) XX *s++ = *s2++; XX redraw_curline(line->li_text); XX move_cursor(sc->sc_lineno, sc->sc_firstcol + yank->ya_width-1); XX if (set_fortran && line->li_width > 72) { XX botprint(FALSE, "Line is longer than 72 columns"); XX hitcr_continue(); XX } XX } XX else { /* Put text between lines */ XX sc->sc_validcol = FALSE; XX if (yank->ya_type == YANK_SINGLE) { XX /* XX * Simple case - put 1 line XX */ XX openline(direction); XX save_Undo(); XX redraw_curline(yank->ya_text); XX move_cursor(sc->sc_lineno, COL_FIRST_NONWHITE); XX } XX else { XX /* XX * put multiple lines XX */ XX xmit_curline(); XX xmit_ed("%dr /tmp/yk%d.%d\n", sc->sc_lineno - XX (direction >= 0 ? 0 : 1), getpid(), indx); XX undo.un_lastline = sc->sc_lineno + yank->ya_numlines-1; XX fetch_window(sc->sc_lineno - NUM_WINDOW_LINES/4 - XX LINES/2 + 1, TRUE); XX botprint(FALSE, "%d more lines", yank->ya_numlines); XX hitcr_continue(); XX } XX } XX} @//E*O*F rv_put.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_redraw.c if test -f rv_redraw.c ; then echo rv_redraw.c exists, putting output in $$rv_redraw.c OUT=$$rv_redraw.c STATUS=1 else OUT=rv_redraw.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_redraw.c//' XX#include "rv.h" XXvoid XXredraw_screen(firstline) XX/* XX * Regenerate the screen from firstline downwards to curses XX * XX * If firstline is NULL, the entire screen is redrawn. XX */ XXstruct li_line *firstline; XX{ XX register struct li_line *line; XX register struct sc_screen *sc; XX register struct wi_window *wi; XX INT saveline, savecol, seg; XX sc = &screen; XX wi = &window; XX if (firstline == (struct li_line *)0) XX firstline = sc->sc_topline; XX /* XX * Save cursor location XX */ XX saveline = CURLINE; XX savecol = CURCOLUMN; XX /* XX * Skip void line segments above topline XX */ XX if (firstline == sc->sc_topline) { XX sc->sc_abovetop = 0; /* Reset topline to real screen top */ XX seg = 0; XX } else XX seg = sc->sc_abovetop; XX /* XX * Skip lines above firstline XX */ XX for (line=sc->sc_topline; line < firstline; ++line) XX seg += line->li_segments; XX /* XX * Clear screen from firstline downward XX */ XX move(seg,0); XX clrtobot(); XX move(seg,0); /* Because clrtobot homes the cursor in 4bsd */ XX /* XX * Redraw remaining lines XX */ XX if (line <= wi->wi_botline) XX seg += line->li_segments; XX if (seg >= LINES && sc->sc_curline == line) { XX /* XX * Scroll XX */ XX sc->sc_botline = line-1; XX rv_scroll(1); XX redraw_screen(line+1); XX move(saveline, savecol); XX return; XX } XX XX while (seg < LINES) { XX if (line <= wi->wi_botline) { XX print_line(line->li_text); XX if (CURCOLUMN != 0 || line->li_text[0] == '\0') XX move(CURLINE+1, 0); XX ++line; XX } XX if (line > wi->wi_botline) { /* If past bottom of window */ XX if ((line - sc->sc_curline) + sc->sc_lineno > XX file.fi_numlines) /* If past eof */ XX break; XX /* XX * Fetch window & redraw everything XX */ XX if (set_debug > 1) XX fprintf(stderr, "Forced to redraw\n"); XX fetch_window(sc->sc_lineno - NUM_WINDOW_LINES/4 - XX LINES/2+1, TRUE); XX return; XX } XX seg += line->li_segments; XX } XX sc->sc_botline = line-1; XX /* XX * Append '~' or '@' lines to screen XX */ XX if ((seg = CURLINE) < LINES-1) XX if (file.fi_numlines > sc->sc_lineno + XX (sc->sc_botline - sc->sc_curline)) XX /* XX * Undisplayed lines XX */ XX while (seg < LINES-1) XX mvaddch(seg++, 0, '@'); XX else XX /* XX * End of file XX */ XX while (seg < LINES-1) XX mvaddch(seg++, 0, '~'); XX /* XX * Restore cursor XX */ XX move(saveline, savecol); XX} @//E*O*F rv_redraw.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_redraw_ln.c if test -f rv_redraw_ln.c ; then echo rv_redraw_ln.c exists, putting output in $$rv_redraw_ln.c OUT=$$rv_redraw_ln.c STATUS=1 else OUT=rv_redraw_ln.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_redraw_ln.c//' XX#include "rv.h" XXvoid XXredraw_curline(txt) XX/* XX * Redraw the current line using txt. XX * Update rest of screen as necessary XX */ XXchar *txt; XX{ XX register struct li_line *line; XX register struct li_line *line2; XX register struct sc_screen *sc; XX register INT seg, i; XX char *oldtxt; XX sc = &screen; XX line = sc->sc_curline; XX seg = line->li_segments; XX oldtxt = line->li_text; XX /* XX * Rebuild line internally XX */ XX line->li_width = strlen(txt); XX line->li_segments = 1 + (screen_column(txt, line->li_width-1) + XX set_list) / COLS; XX if (line->li_text != txt) { XX line->li_text = xalloc(line->li_width+1); XX strcpy(line->li_text, txt); XX if (oldtxt) XX free(oldtxt); XX } XX i = sc->sc_abovetop; XX for (line = sc->sc_topline; line < sc->sc_curline; ++line) XX i += line->li_segments; XX move(i, 0); XX if (CURLINE+line->li_segments >= LINES) { XX /* XX * Line overflowed screen XX */ XX redraw_screen(line); XX return; XX } XX /* XX * If grew, push down segs below this line XX */ XX if (line->li_segments > seg) { XX i = line->li_segments - seg; XX rv_finsertln(i); XX /* Redraw pushed off segs */ XX i = line->li_segments - seg; XX line2 = sc->sc_botline; XX while (i >= 0) { XX i -= line2->li_segments; XX --line2; XX } XX if (line2 <= line) XX line2 = line + 1; XX redraw_screen(line2); XX } XX /* XX * Clear segments and redraw XX */ XX clrtoeol(); XX for (i=line->li_segments; i > 1; --i) { XX move(CURLINE+1, 0); XX clrtoeol(); XX } XX /* XX * Move to first seg of line XX */ XX if (line->li_segments > 1) XX move(CURLINE-line->li_segments+1, 0); XX /* XX * Draw line XX */ XX i = CURLINE; XX print_line(line->li_text); XX if (seg <= line->li_segments) XX return; XX /* XX * Shrunk, delete surplus segs XX */ XX move(i+line->li_segments, 0); XX i = seg - line->li_segments; XX rv_fdeleteln(i); XX redraw_screen(sc->sc_botline+1); XX} @//E*O*F rv_redraw_ln.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_scroll.c if test -f rv_scroll.c ; then echo rv_scroll.c exists, putting output in $$rv_scroll.c OUT=$$rv_scroll.c STATUS=1 else OUT=rv_scroll.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_scroll.c//' XX#include "rv.h" XXvoid XXrv_scroll(n) XX/* XX * Scroll n lines XX * Must be within window XX * Cursor is set to last line XX */ XXregister INT n; XX{ XX register struct li_line *line, *oldline; XX register struct sc_screen *sc; XX register INT seg,newseg,i; XX register struct wi_window *wi; XX sc = &screen; XX wi = &window; XX /* XX * Set cursor to bottom line+1 XX */ XX newseg = 0; XX for (line = sc->sc_topline; line <= sc->sc_botline; ++line) XX newseg += line->li_segments; XX newseg += sc->sc_abovetop; XX move(newseg,0); XX clrtobot(); XX /* XX * Calculate number of segments to scroll in XX */ XX seg = 0; XX for (i=n; i > 0 && line <= wi->wi_botline; --i, ++line) XX seg += line->li_segments; XX seg -= LINES-newseg-1; XX move(LINES-1,0); XX rv_fscroll(seg); XX move(newseg-seg,0); XX /* XX * Scroll in new line(s) XX */ XX for (line = sc->sc_botline+1; n > 0; --n, ++line) { XX if (line > wi->wi_botline) { XX errflag = 1; XX botprint(TRUE, "rv_scroll - past bottom of window\n\n"); XX hitcr_continue(); XX return; XX } XX print_line(line->li_text); XX if (CURCOLUMN != 0 || line->li_text[0] == '\0') { XX if (CURLINE == LINES-1) { XX move(LINES-1, 0); XX } else XX move(CURLINE+1, 0); XX } XX } XX /* XX * Adjust screen params XX */ XX xmit_curline(); XX --line; XX sc->sc_lineno += (line - sc->sc_curline); XX sc->sc_botline = line; XX sc->sc_curline = line; XX sc->sc_column = 0; XX /* XX * Compute new top line XX */ XX for (seg = line->li_segments; seg < LINES; XX seg += line->li_segments) { XX --line; XX if (line < wi->wi_topline) XX break; XX } XX sc->sc_topline = line+1; XX /* XX * Compute # of displayed segs above top line XX */ XX if (line >= wi->wi_topline) XX sc->sc_abovetop = LINES-1 - (seg - line->li_segments); XX} @//E*O*F rv_scroll.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_scroll_bk.c if test -f rv_scroll_bk.c ; then echo rv_scroll_bk.c exists, putting output in $$rv_scroll_bk.c OUT=$$rv_scroll_bk.c STATUS=1 else OUT=rv_scroll_bk.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_scroll_bk.c//' XX#include "rv.h" XXvoid XXrv_scroll_backward(n) XX/* XX * Scroll n lines backward XX * Must be within window XX * Cursor location is undefined XX */ XXregister n; XX{ XX register struct li_line *line, *newline; XX register struct sc_screen *sc; XX register INT seg; XX register struct wi_window *wi; XX register struct fi_file *fi; XX sc = &screen; XX wi = &window; XX fi = &file; XX seg = 0; XX for (line = sc->sc_topline-1; n > 0; --n, --line) { XX if (line < wi->wi_topline) { XX errflag = 1; XX botprint(TRUE, XX "rv_scroll_backward - past top of window\n\n"); XX hitcr_continue(); XX return; XX } XX seg += line->li_segments; XX } XX ++line; XX move(0,0); XX seg -= sc->sc_abovetop; XX rv_finsertln(seg); XX move(0,0); XX for (newline = line; newline < sc->sc_topline; ++newline) { XX print_line(newline->li_text); XX if (CURCOLUMN != 0 || newline->li_text[0] == '\0') XX move(CURLINE+1, 0); XX } XX xmit_curline(); XX sc->sc_lineno = sc->sc_lineno - (sc->sc_curline - line); XX sc->sc_topline = line; XX sc->sc_curline = line; XX sc->sc_column = 0; XX sc->sc_abovetop = 0; XX /* XX * Compute bottom line XX */ XX for (seg = line->li_segments; seg < LINES; XX seg += line->li_segments) { XX ++line; XX if (line > wi->wi_botline) XX break; XX } XX sc->sc_botline = line-1; XX if (line <= wi->wi_botline) XX seg -= line->li_segments; XX move(seg, 0); XX clrtobot(); XX move(seg, 0); /* Because clrtobot homes the cursor in 4bsd */ XX /* XX * Append '~' or '@' lines to screen XX */ XX if (seg < LINES-1) XX if (fi->fi_numlines > sc->sc_lineno + XX (sc->sc_botline - sc->sc_curline)) XX /* XX * Undisplayed lines XX */ XX while (seg < LINES-1) XX mvaddch(seg++, 0, '@'); XX else XX /* XX * End of file XX */ XX while (seg < LINES-1) XX mvaddch(seg++, 0, '~'); XX move(0,0); XX} @//E*O*F rv_scroll_bk.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_search.c if test -f rv_search.c ; then echo rv_search.c exists, putting output in $$rv_search.c OUT=$$rv_search.c STATUS=1 else OUT=rv_search.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_search.c//' XX#include "rv.h" XX#include "regexp.h" XX#ifdef CRAY XX#define move_cursor_flag mc_flag XX#endif XXstatic char prev_search[256]; /* Buffer holding previous search string */ XXstatic char buf[256]; /* Buffer holding current search string */ XXstatic regexp *cmp; /* Compiled regular expression (RE) */ XXboolean XXsearch(direction, txt, move_cursor_flag) XX/* XX * Search file for match XX * XX * Scan current line using regexec() for txt XX * If not found, xmit search request to ed XX * Scan line that ed finds using regex() XX * Put cursor at new location, if move_cursor_flag XX */ XXINT direction; /* Direction of search (-1, 1) */ XXchar *txt; /* Regular expression to search for */ XXboolean move_cursor_flag; /* TRUE if cursor to be moved to match */ XX{ XX register struct sc_screen *sc; XX register char *s, *s2; XX register INT i, ch; XX struct li_line *line; XX INT offset = 0; XX char *found, numbuf[20]; XX sc = &screen; XX sc->sc_validcol = TRUE; XX sc->sc_firstcol = sc->sc_lastcol = sc->sc_column; XX sc->sc_firstline = sc->sc_lastline = sc->sc_lineno; XX if (txt == NULL) XX return FALSE; XX strcpy(buf, txt); XX if (direction >= 0) XX ch = '/'; XX else XX ch = '?'; XX s = buf; XX /* XX * Scan for first / or ? not preceeded by an odd number of backslashes XX */ XX i = 0; XX while (*s != '\0' && (*s != ch || i & 1)) { XX i = *s == '\\' ? i+1 : 0; XX ++s; XX } XX /* XX * Drop '\0' into matching / or ? XX */ XX if (*s != '\0') XX *s++ = '\0'; XX ch = *s; XX /* XX * Check for +/- offset XX */ XX if (ch == '+' || ch == '-') { XX offset = atoi(s); XX if (offset == 0 && *(s+1) != '0') XX offset = 1; XX if (*s == '-') XX offset = -offset; XX sc->sc_validcol = FALSE; XX } XX if (*buf == '\0') XX strcpy(buf, prev_search); XX if (*buf == '\0') { XX botprint(TRUE, "No remembered search string"); XX return FALSE; XX } XX /* XX * Compile RE XX */ XX if (cmp) XX free(cmp); XX if ((cmp = regcomp(buf)) == 0) { XX return FALSE; XX } XX strcpy(prev_search, buf); XX line = sc->sc_curline; XX s = &line->li_text[sc->sc_column]; XX found = NULL; XX if (direction >= 0) { XX /* XX * Search current line after cursor XX */ XX if (*buf != '^' && *++s != '\0') XX if (regexec(cmp, s) != 0) { XX found = cmp->startp[0]; XX sc->sc_lastcol = found - line->li_text - 1; XX } XX } else { XX /* XX * Search current line before cursor XX */ XX s2 = line->li_text; XX while (s2 < s) { XX if (regexec(cmp, s2) == 0 || cmp->startp[0] >= s) XX break; XX found = cmp->startp[0]; XX if (*buf == '^') /* If anchored */ XX break; XX s2 = cmp->startp[0]+1; XX } XX if (found) { XX sc->sc_lastcol--; XX sc->sc_firstcol = found - line->li_text; XX } XX } XX if (found) { XX /* XX * Found match on current line XX */ XX if (offset != 0) { XX /* XX * Line offset requested from current line (sigh) XX */ XX sc->sc_validcol = FALSE; XX if ((i = sc->sc_lineno + offset) < 1) { XX botprint(TRUE, "Negative address"); XX return FALSE; XX } XX if (i > file.fi_numlines) { XX botprint(TRUE, "Not that many lines in buffer"); XX return FALSE; XX } XX if (i < sc->sc_lineno) XX sc->sc_firstline = i; XX else if (i > sc->sc_lineno) XX sc->sc_lastline = i-1; XX if (move_cursor_flag) XX move_abs_cursor(i, COL_FIRST_NONWHITE); XX return TRUE; XX } XX if (move_cursor_flag) XX if (sc->sc_firstcol != sc->sc_column) XX move_cursor(sc->sc_lineno, sc->sc_firstcol); XX else XX move_cursor(sc->sc_lineno, sc->sc_lastcol+1); XX return TRUE; XX } XX sc->sc_validcol = FALSE; XX /* XX * Xmit search to ed XX */ XX xmit_curline(); XX i = sc->sc_lineno; XX if (direction >= 0) XX xmit_ed("%d\n/%s/\n", i, buf); XX else XX xmit_ed("%d\n?%s?\n", i, buf); XX xmit_sync(); XX xmit_ed(".=\n"); XX (void) recv_sync(FALSE); XX (void) fgets(numbuf, 18, file.fi_fpin); XX if ((i = atoi(numbuf)) == sc->sc_lineno) { XX botprint(TRUE, "Pattern not found"); XX return FALSE; XX } XX if (set_wrapscan == FALSE && XX ((direction > 0 && i < sc->sc_lineno) || XX (direction < 0 && i > sc->sc_lineno))) { /* If wrapped */ XX botprint(TRUE, "Address search hit %s without matching pattern", XX direction < 0 ? "TOP" : "BOTTOM"); XX return FALSE; XX } XX XX i += offset; XX if (i < 1) { XX botprint(TRUE, "Negative address"); XX return FALSE; XX } XX if (i > file.fi_numlines) { XX botprint(TRUE, "Not that many lines in buffer"); XX return FALSE; XX } XX if (i < sc->sc_lineno) XX sc->sc_firstline = i; XX else if (i > sc->sc_lineno) XX sc->sc_lastline = i-1; XX if (!move_cursor_flag) XX return TRUE; XX XX /* XX * Cursor movement requested XX */ XX /* XX * Move to line,col of match XX */ XX if (offset != 0) { XX move_abs_cursor(i, COL_FIRST_NONWHITE); XX return TRUE; XX } XX move_abs_cursor(i, 0); XX line = sc->sc_curline; XX if (direction >= 0) { XX if (regexec(cmp, line->li_text) != 0) XX sc->sc_column = cmp->startp[0] - line->li_text; XX } else { XX s2 = line->li_text; XX found = NULL; XX while (*s2 != '\0') { XX if (regexec(cmp, s2) == 0) XX break; XX found = cmp->startp[0]; XX if (*buf == '^') /* If anchored */ XX break; XX s2 = cmp->startp[0]+1; XX } XX if (found) XX sc->sc_column = found - line->li_text; XX } XX move_cursor(sc->sc_lineno, sc->sc_column); XX return TRUE; XX} @//E*O*F rv_search.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_shell.c if test -f rv_shell.c ; then echo rv_shell.c exists, putting output in $$rv_shell.c OUT=$$rv_shell.c STATUS=1 else OUT=rv_shell.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_shell.c//' XX#include "rv.h" XX#include <signal.h> XX#ifndef USG XX# define strchr index XX#endif XX/* XX * This entire module is a hack XX */ XXextern boolean scrolled; XXextern char *strchr(); XXrv_shell(cmd) XXchar *cmd; XX{ XX INT cpid, len, infd, outfd; XX char buf[513], *s; XX int (*prev_func)(); XX#ifdef USG XX struct termio tm; XX#endif XX XX xmit_sync(); XX (void) recv_sync(FALSE); XX xmit_ed("!sh -c '%s' ; echo '@''$''#'\n", cmd); XX fflush(file.fi_fpout); XX if (file.fi_modified) XX botprint(FALSE, "[No write since last change]"); XX move(LINES-1, 0); XX rv_fscroll(1); XX move(LINES-1, 0); XX refresh(); XX /* prev_func = signal(SIGINT, SIG_IGN); Use at your own risk */ XX if (use_linemode) { XX#ifdef USG XX nocbreak(); XX#else XX nocrmode(); XX#endif XX nl(); XX echo(); XX#ifdef TCGETA /* Echo doesn't in System V, sigh */ XX ioctl(0, TCGETA, &tm); XX tm.c_lflag |= ECHO; XX ioctl(0, TCSETA, &tm); XX#endif XX if (set_debug > 2) XX printf("Using line mode.\n"); XX } XX infd = atoi(Argv[1]); XX outfd = atoi(Argv[2]); XX if ((cpid = fork()) < 0) XX panic("Can't fork"); XX if (cpid == 0) { /* Child */ XX for (;;) { XX if ((len = read(0, buf, 512)) < 0) XX _exit(0); XX if (len == 0) XX write(outfd, "\004\n", 2); XX else XX write(outfd, buf, len); XX } XX /*NOTREACHED*/ XX } XX for (;;) { /* Parent */ XX if ((len = read(infd, buf, 512)) <= 0) XX panic("EOF on read from pipe"); XX if ((s = strchr(buf, '@')) != NULL) { XX if (s-buf+1 >= len) { XX write(1, buf, len); XX len = read(infd, buf, 512); XX s = buf; XX } XX if (*++s == '$') { XX if (s-buf+1 >= len) { XX write(1, buf, len); XX len = read(infd, buf, 512); XX s = buf; XX } XX if (*++s == '#') { XX if (s-buf >= 3) XX write(1, buf, s-buf-2); XX kill(cpid, 9); XX while (wait((int *)0) != cpid) XX ; XX break; XX } XX } XX } XX write(1, buf, len); XX } XX if (use_linemode) { XX#ifdef USG XX cbreak(); XX#else XX crmode(); XX#endif XX nonl(); XX noecho(); XX } XX /* (void) signal(SIGINT, prev_func); Use at your own risk */ XX refresh(); XX scrolled = TRUE; XX hitcr_continue(); XX clearok(curscr, TRUE); XX redraw_screen((struct li_line *)0); XX move_cursor(screen.sc_lineno, screen.sc_column); XX} @//E*O*F rv_shell.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_sync.c if test -f rv_sync.c ; then echo rv_sync.c exists, putting output in $$rv_sync.c OUT=$$rv_sync.c STATUS=1 else OUT=rv_sync.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_sync.c//' XX#include "rv.h" XX/* XX * Synchronize communication by sending a command XX * with a recognizable response. XX */ XXvoid XXxmit_sync() XX/* XX * Transmit sync XX * XX * A sync consists of transmitting two f commands followed XX * by an illegal command, and waiting to receive the file name echoed XX * twice followed by a question mark. XX */ XX{ XX if (fputs("f\nf\nzzz\n", file.fi_fpout) == NULL) XX panic("Error while writing to ed\n\n"); XX} XXboolean XXrecv_sync(disp_flag) XX/* XX * Wait for sync to come back XX * XX * Returns TRUE if no errors received prior to sync, else XX * displays errors if disp_flag is TRUE. XX */ XXboolean disp_flag; XX{ XX register char buf[512]; XX register INT i, namematch = 0, errcount = 0; XX INT old_alarm; XX extern alarmring(); XX old_alarm = alarm(RV_TIMEOUT); XX fflush(file.fi_fpout); XX for (;;) { XX if (fgets(buf, 511, file.fi_fpin) == NULL) XX panic("Error while reading from ed\n\n"); XX /* XX * Strip trailing \n XX */ XX if ((i = strlen(buf)) > 0 && buf[i-1] == '\n') XX buf[--i] = '\0'; XX if (buf[0] == '?') { XX if (namematch > 1) XX goto found; XX /* XX * Display error XX */ XX ++errcount; XX if (file.fi_sysv) { XX if (buf[1] != ' ' || XX file.fi_cray == FALSE) XX fgets(buf, 511, file.fi_fpin); XX if (disp_flag) XX botprint(TRUE, "%s", buf); XX } XX else XX if (disp_flag) XX botprint(TRUE, "Failed "); XX namematch = 0; XX continue; XX } XX /* XX * Look for file name echoed twice XX */ XX if (strcmp(buf, file.fi_name) == 0) XX ++namematch; XX else XX namematch = 0; XX if (namematch >= 2) { XX (void) fgets(buf, 511, file.fi_fpin); XX if ((i = strlen(buf)) > 0 && buf[i-1] == '\n') XX buf[--i] = '\0'; XX /* XX * Look for question mark XX */ XX if (buf[0] == '?') { XX found: XX if (file.fi_sysv && XX (buf[1] != ' ' || file.fi_cray == FALSE)) XX /* XX * Skip error msg XX */ XX fgets(buf, 511, file.fi_fpin); XX break; XX } XX else { XX if (disp_flag > 1) XX botprint(FALSE, "%s", file.fi_name); XX if (strcmp(buf, file.fi_name)) { XX if (disp_flag > 1) XX botprint(FALSE, "%s", file.fi_name); XX namematch = 0; XX } XX } XX } XX if (disp_flag > 1 && namematch == 0) XX botprint(FALSE, "%s", buf); XX } XX alarm(old_alarm); XX return (errcount == 0); XX} @//E*O*F rv_sync.c// chmod u=rw,g=rw,o=rw $OUT echo x - rv_undo.c if test -f rv_undo.c ; then echo rv_undo.c exists, putting output in $$rv_undo.c OUT=$$rv_undo.c STATUS=1 else OUT=rv_undo.c fi sed 's/^XX//' > $OUT <<'@//E*O*F rv_undo.c//' XX#include "rv.h" XXvoid XXrv_undo() XX/* XX * undo last change XX * XX * undo is accomplished by deleting the last inserted text, and XX * restoring the last deleted text, both of which are assumed XX * to start at the same row,col position. XX */ XX{ XX struct ya_yank *yank, *save_yank; XX boolean deleted; XX void rv_linecmd(); XX INT direction = -1; XX if (ed_undo) { XX rv_linecmd("u"); XX ed_undo = TRUE; XX return; XX } XX XX yank = &yank_array[0]; XX save_yank = &yank_array[NUM_YANK_BUFS-1]; XX /* XX * See if there is something to undo XX */ XX if (undo.un_deleted == FALSE && undo.un_inserted == FALSE) { XX flash(); XX errflag = 1; XX return; XX } XX /* XX * Save previous yanked (deleted) text XX */ XX copy((char *)save_yank, (char *)yank, sizeof(struct ya_yank)); XX if (yank->ya_text) { XX save_yank->ya_text = xalloc(strlen(yank->ya_text)+1); XX strcpy(save_yank->ya_text, yank->ya_text); XX } XX deleted = undo.un_deleted; XX undo.un_deleted = FALSE; XX if (undo.un_firstline > file.fi_numlines) { XX direction = 1; XX undo.un_firstline = file.fi_numlines; XX } XX move_abs_cursor(undo.un_firstline, 0); XX /* XX * Delete last inserted text XX */ XX if (undo.un_inserted) { XX register struct sc_screen *sc; XX sc = &screen; XX sc->sc_firstline = undo.un_firstline; XX sc->sc_lastline = undo.un_lastline; XX if (undo.un_validcol == FALSE) XX sc->sc_validcol = FALSE; XX else { XX sc->sc_validcol = TRUE; XX sc->sc_firstcol = undo.un_firstcol; XX sc->sc_lastcol = undo.un_lastcol; XX } XX undo.un_inserted = FALSE; XX delete(); XX } XX /* XX * Restore last deleted text XX */ XX if (deleted && save_yank->ya_type != YANK_EMPTY) { XX move_abs_cursor(undo.un_firstline, 0); XX if (save_yank->ya_type == YANK_COLS) XX screen.sc_column = undo.un_firstcol-1; XX yank_cmd = '$'; XX put(direction); XX } XX /* XX * Free saved yank text XX */ XX if (save_yank->ya_text) { XX free(save_yank->ya_text); XX save_yank->ya_text = NULL; XX } XX save_yank->ya_type = YANK_EMPTY; XX} XXvoid XXsave_Undo() XX/* XX * Save current line into Undo buffer XX */ XX{ XX register struct li_line *line; XX register struct sc_screen *sc; XX sc = &screen; XX line = sc->sc_curline; XX file.fi_modified = TRUE; XX if (sc->sc_origline.li_text == NULL) { XX /* XX * Copy line into Undo buffer XX */ XX sc->sc_origline.li_text = xalloc(line->li_width+1); XX sc->sc_origline.li_segments = line->li_segments; XX sc->sc_origline.li_width = line->li_width; XX strcpy(sc->sc_origline.li_text, line->li_text); XX } XX} XXvoid XXtoss_undo() XX/* XX * Forget last undo operation XX */ XX{ XX struct ya_yank *yank; XX yank = &yank_array[0]; XX undo.un_inserted = FALSE; XX undo.un_deleted = FALSE; XX undo.un_validcol = FALSE; XX if (yank->ya_text) { XX free(yank->ya_text); XX yank->ya_text = NULL; XX } XX yank->ya_type = YANK_EMPTY; XX ed_undo = FALSE; XX} @//E*O*F rv_undo.c// chmod u=rw,g=rw,o=rw $OUT echo Inspecting for damage in transit... temp=/tmp/sharin$$; dtemp=/tmp/sharout$$ trap "rm -f $temp $dtemp; exit" 0 1 2 3 15 cat > $temp <<\!!! 500 1357 10031 rv_insert.c 324 848 5971 rv_linecmd.c 153 375 3006 rv_misc.c 280 887 6189 rv_move.c 146 365 3019 rv_openline.c 91 256 2163 rv_put.c 107 315 2256 rv_redraw.c 95 238 1757 rv_redraw_ln.c 81 239 1642 rv_scroll.c 83 234 1684 rv_scroll_bk.c 230 748 4959 rv_search.c 112 298 2092 rv_shell.c 108 321 2191 rv_sync.c 137 326 2671 rv_undo.c 2447 6807 49631 total !!! wc $FILES | sed 's=[^ ]*/==' | diff -b $temp - >$dtemp if test -s $dtemp ; then echo "Ouch [diff of wc output]:" cat $dtemp STATUS=1 elif test $STATUS = 0 ; then echo "No problems found." else echo "WARNING -- PROBLEMS WERE FOUND..." fi exit $STATUS