allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc) (08/20/89)
Posting-number: Volume 8, Issue 4 Submitted-by: tony@cs.utexas.edu@wldrdg.UUCP (Tony Andrews) Archive-name: stevie3.68/part02 #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # help.c # hexchars.c # keymap.h # linefunc.c # main.c # mark.c # misccmds.c # This archive created: Sun Aug 13 11:45:56 1989 export PATH; PATH=/bin:$PATH echo shar: extracting "'help.c'" '(8540 characters)' if test -f 'help.c' then echo shar: will not over-write existing file "'help.c'" else sed 's/^X//' << \HE_HATES_THESE_CANS > 'help.c' X/* $Header: /nw/tony/src/stevie/src/RCS/help.c,v 1.9 89/08/06 09:50:09 tony Exp $ X * X * Routine to display a command summary. X */ X X#include "stevie.h" X Xextern char *Version; X Xstatic int helprow; X X#ifdef HELP X Xstatic void longline(); X Xbool_t Xhelp() X{ X X/*********************************************************************** X * First Screen: Positioning within file, Adjusting the Screen X ***********************************************************************/ X X outstr(T_ED); X windgoto(helprow = 0, 0); X Xlongline("\ X Positioning within file\n\ X =======================\n\ X ^F Forward screenfull Developed by:\n\ X ^B Backward screenfull Tony Andrews\n"); Xlongline("\ X ^D scroll down half screen\n\ X ^U scroll up half screen Based on a program by:\n"); Xlongline("\ X G Goto line (end default) Tim Thompson\n\ X ]] next function\n\ X [[ previous function\n\ X /re next occurence of regular expression 're'\n"); Xlongline("\ X ?re prior occurence of regular expression 're'\n\ X n repeat last / or ?\n\ X N reverse last / or ?\n\ X % find matching (, ), {, }, [, or ]\n"); Xlongline("\ X\n\ X Adjusting the screen\n\ X ====================\n\ X ^L Redraw the screen\n\ X ^E scroll window down 1 line\n\ X ^Y scroll window up 1 line\n"); Xlongline("\ X z<RETURN> redraw, current line at top\n\ X z- ... at bottom\n\ X z. ... at center\n"); X X windgoto(0, 52); X longline(Version); X X windgoto(helprow = Rows-2, 47); X longline("<Press space bar to continue>\n"); X windgoto(helprow = Rows-1, 47); X longline("<Any other key will quit>"); X X if ( vgetc() != ' ' ) X return TRUE; X X/*********************************************************************** X * Second Screen: Character positioning X ***********************************************************************/ X X outstr(T_ED); X windgoto(helprow = 0, 0); X Xlongline("\ X Character Positioning\n\ X =====================\n\ X ^ first non-white\n\ X 0 beginning of line\n\ X $ end of line\n\ X h backward\n"); Xlongline("\ X l forward\n\ X ^H same as h\n\ X space same as l\n\ X fx find 'x' forward\n"); Xlongline("\ X Fx find 'x' backward\n\ X tx upto 'x' forward\n\ X Tx upto 'x' backward\n\ X ; Repeat last f, F, t, or T\n"); Xlongline("\ X , inverse of ;\n\ X | to specified column\n\ X % find matching (, ), {, }, [, or ]\n"); X X windgoto(helprow = Rows-2, 47); X longline("<Press space bar to continue>\n"); X windgoto(helprow = Rows-1, 47); X longline("<Any other key will quit>"); X X if ( vgetc() != ' ' ) X return TRUE; X X/*********************************************************************** X * Third Screen: Line Positioning, Marking and Returning X ***********************************************************************/ X X outstr(T_ED); X windgoto(helprow = 0, 0); X Xlongline("\ X Line Positioning\n\ X ================\n\ X H home window line\n\ X L last window line\n\ X M middle window line\n"); Xlongline("\ X + next line, at first non-white\n\ X - previous line, at first non-white\n\ X CR return, same as +\n\ X j next line, same column\n\ X k previous line, same column\n"); X Xlongline("\ X\n\ X Marking and Returning\n\ X =====================\n\ X `` previous context\n\ X '' ... at first non-white in line\n"); Xlongline("\ X mx mark position with letter 'x'\n\ X `x to mark 'x'\n\ X 'x ... at first non-white in line\n"); X Xlongline("\n\ X Undo & Redo\n\ X =============\n\ X u undo last change\n\ X U restore current line\n\ X . repeat last change\n"); X X windgoto(helprow = Rows-2, 47); X longline("<Press space bar to continue>\n"); X windgoto(helprow = Rows-1, 47); X longline("<Any other key will quit>"); X X if ( vgetc() != ' ' ) X return TRUE; X/*********************************************************************** X * Fourth Screen: Insert & Replace, X ***********************************************************************/ X X outstr(T_ED); X windgoto(helprow = 0, 0); X Xlongline("\ X Insert and Replace\n\ X ==================\n\ X a append after cursor\n\ X i insert before cursor\n\ X A append at end of line\n\ X I insert before first non-blank\n"); Xlongline("\ X o open line below\n\ X O open line above\n\ X rx replace single char with 'x'\n\ X R replace characters\n"); X Xlongline("\ X\n\ X Words, sentences, paragraphs\n\ X ============================\n\ X w word forward\n\ X b back word\n\ X e end of word\n\ X ) to next sentence (not yet)\n\ X } to next paragraph (not yet)\n"); Xlongline("\ X ( back sentence (not yet)\n\ X { back paragraph (not yet)\n\ X W blank delimited word\n\ X B back W\n\ X E to end of W\n"); X X windgoto(helprow = Rows-2, 47); X longline("<Press space bar to continue>\n"); X windgoto(helprow = Rows-1, 47); X longline("<Any other key will quit>"); X X if ( vgetc() != ' ' ) X return TRUE; X X/*********************************************************************** X * Fifth Screen: Misc. operations, X ***********************************************************************/ X X outstr(T_ED); X windgoto(helprow = 0, 0); X Xlongline("\ X Miscellaneous Commands\n\ X ======================\n"); Xlongline("\ X :w write back changes\n\ X :wq write and quit\n\ X :x write if modified, and quit\n\ X :q quit\n\ X :q! quit, discard changes\n\ X :e name edit file 'name'\n"); Xlongline("\ X :e! reedit, discard changes\n\ X :e # edit alternate file\n\ X :w name write file 'name'\n"); Xlongline("\ X :n edit next file in arglist\n\ X :N edit prior file in arglist\n\ X :n args specify new arglist (not yet)\n\ X :rew rewind arglist\n\ X :f show current file and lines\n"); Xlongline("\ X :f file change current file name\n\ X :g/pat/p|d global command (print or delete only)\n\ X :s/p1/p2/ text substitution (trailing 'g' optional)\n\ X"); Xlongline("\ X :ta tag to tag file entry 'tag'\n\ X ^] :ta, current word is tag\n\ X :sh run an interactive shell\n\ X :!cmd execute a shell command\n\ X"); X X windgoto(helprow = Rows-2, 47); X longline("<Press space bar to continue>\n"); X windgoto(helprow = Rows-1, 47); X longline("<Any other key will quit>"); X X if ( vgetc() != ' ' ) X return TRUE; X X/*********************************************************************** X * Sixth Screen: Operators, Misc. operations, Yank & Put X ***********************************************************************/ X X outstr(T_ED); X windgoto(helprow = 0, 0); X Xlongline("\ X Operators (double to affect lines)\n\ X ==================================\n\ X d delete\n\ X c change\n"); Xlongline("\ X < left shift\n\ X > right shift\n\ X y yank to buffer\n\ X ! filter lines\n"); X Xlongline("\n\ X Miscellaneous operations\n\ X ========================\n\ X C change rest of line\n\ X D delete rest of line\n\ X s substitute chars\n"); Xlongline("\ X S substitute lines (not yet)\n\ X J join lines\n\ X x delete characters\n\ X X ... before cursor\n"); X Xlongline("\n\ X Yank and Put\n\ X ============\n\ X p put back text\n\ X P put before\n\ X Y yank lines"); X X windgoto(helprow = Rows-1, 47); X longline("<Press any key>"); X X (void) vgetc(); X X return TRUE; X} X Xstatic void Xlongline(p) Xchar *p; X{ X register char *s; X X for ( s = p; *s ;s++ ) { X if ( *s == '\n' ) X windgoto(++helprow, 0); X else X outchar(*s); X } X} X#else X Xbool_t Xhelp() X{ X msg("Sorry, help not configured"); X return FALSE; X} X#endif HE_HATES_THESE_CANS if test 8540 -ne "`wc -c < 'help.c'`" then echo shar: error transmitting "'help.c'" '(should have been 8540 characters)' fi fi # end of overwriting check echo shar: extracting "'hexchars.c'" '(3109 characters)' if test -f 'hexchars.c' then echo shar: will not over-write existing file "'hexchars.c'" else sed 's/^X//' << \HE_HATES_THESE_CANS > 'hexchars.c' X/* $Header: /nw/tony/src/stevie/src/RCS/hexchars.c,v 1.4 89/03/11 22:42:27 tony Exp $ X * X * Contains information concerning the representation of characters for X * visual output by the editor. X */ X X#include "stevie.h" X X/* X * This file shows how to display characters on the screen. This is X * approach is something of an overkill. It's a remnant from the X * original code that isn't worth messing with for now. TABS are X * special-cased depending on the value of the "list" parameter. X */ X Xstruct charinfo chars[] = { X /* 000 */ 1, NULL, X /* 001 */ 2, "^A", X /* 002 */ 2, "^B", X /* 003 */ 2, "^C", X /* 004 */ 2, "^D", X /* 005 */ 2, "^E", X /* 006 */ 2, "^F", X /* 007 */ 2, "^G", X /* 010 */ 2, "^H", X /* 011 */ 2, "^I", X /* 012 */ 7, "[ERROR]", /* shouldn't occur */ X /* 013 */ 2, "^K", X /* 014 */ 2, "^L", X /* 015 */ 2, "^M", X /* 016 */ 2, "^N", X /* 017 */ 2, "^O", X /* 020 */ 2, "^P", X /* 021 */ 2, "^Q", X /* 022 */ 2, "^R", X /* 023 */ 2, "^S", X /* 024 */ 2, "^T", X /* 025 */ 2, "^U", X /* 026 */ 2, "^V", X /* 027 */ 2, "^W", X /* 030 */ 2, "^X", X /* 031 */ 2, "^Y", X /* 032 */ 2, "^Z", X /* 033 */ 2, "^[", X /* 034 */ 2, "^\\", X /* 035 */ 2, "^]", X /* 036 */ 2, "^^", X /* 037 */ 2, "^_", X /* 040 */ 1, NULL, X /* 041 */ 1, NULL, X /* 042 */ 1, NULL, X /* 043 */ 1, NULL, X /* 044 */ 1, NULL, X /* 045 */ 1, NULL, X /* 046 */ 1, NULL, X /* 047 */ 1, NULL, X /* 050 */ 1, NULL, X /* 051 */ 1, NULL, X /* 052 */ 1, NULL, X /* 053 */ 1, NULL, X /* 054 */ 1, NULL, X /* 055 */ 1, NULL, X /* 056 */ 1, NULL, X /* 057 */ 1, NULL, X /* 060 */ 1, NULL, X /* 061 */ 1, NULL, X /* 062 */ 1, NULL, X /* 063 */ 1, NULL, X /* 064 */ 1, NULL, X /* 065 */ 1, NULL, X /* 066 */ 1, NULL, X /* 067 */ 1, NULL, X /* 070 */ 1, NULL, X /* 071 */ 1, NULL, X /* 072 */ 1, NULL, X /* 073 */ 1, NULL, X /* 074 */ 1, NULL, X /* 075 */ 1, NULL, X /* 076 */ 1, NULL, X /* 077 */ 1, NULL, X /* 100 */ 1, NULL, X /* 101 */ 1, NULL, X /* 102 */ 1, NULL, X /* 103 */ 1, NULL, X /* 104 */ 1, NULL, X /* 105 */ 1, NULL, X /* 106 */ 1, NULL, X /* 107 */ 1, NULL, X /* 110 */ 1, NULL, X /* 111 */ 1, NULL, X /* 112 */ 1, NULL, X /* 113 */ 1, NULL, X /* 114 */ 1, NULL, X /* 115 */ 1, NULL, X /* 116 */ 1, NULL, X /* 117 */ 1, NULL, X /* 120 */ 1, NULL, X /* 121 */ 1, NULL, X /* 122 */ 1, NULL, X /* 123 */ 1, NULL, X /* 124 */ 1, NULL, X /* 125 */ 1, NULL, X /* 126 */ 1, NULL, X /* 127 */ 1, NULL, X /* 130 */ 1, NULL, X /* 131 */ 1, NULL, X /* 132 */ 1, NULL, X /* 133 */ 1, NULL, X /* 134 */ 1, NULL, X /* 135 */ 1, NULL, X /* 136 */ 1, NULL, X /* 137 */ 1, NULL, X /* 140 */ 1, NULL, X /* 141 */ 1, NULL, X /* 142 */ 1, NULL, X /* 143 */ 1, NULL, X /* 144 */ 1, NULL, X /* 145 */ 1, NULL, X /* 146 */ 1, NULL, X /* 147 */ 1, NULL, X /* 150 */ 1, NULL, X /* 151 */ 1, NULL, X /* 152 */ 1, NULL, X /* 153 */ 1, NULL, X /* 154 */ 1, NULL, X /* 155 */ 1, NULL, X /* 156 */ 1, NULL, X /* 157 */ 1, NULL, X /* 160 */ 1, NULL, X /* 161 */ 1, NULL, X /* 162 */ 1, NULL, X /* 163 */ 1, NULL, X /* 164 */ 1, NULL, X /* 165 */ 1, NULL, X /* 166 */ 1, NULL, X /* 167 */ 1, NULL, X /* 170 */ 1, NULL, X /* 171 */ 1, NULL, X /* 172 */ 1, NULL, X /* 173 */ 1, NULL, X /* 174 */ 1, NULL, X /* 175 */ 1, NULL, X /* 176 */ 1, NULL, X /* 177 */ 2, "^?", X}; HE_HATES_THESE_CANS if test 3109 -ne "`wc -c < 'hexchars.c'`" then echo shar: error transmitting "'hexchars.c'" '(should have been 3109 characters)' fi fi # end of overwriting check echo shar: extracting "'keymap.h'" '(936 characters)' if test -f 'keymap.h' then echo shar: will not over-write existing file "'keymap.h'" else sed 's/^X//' << \HE_HATES_THESE_CANS > 'keymap.h' X/* X * $Header: /nw/tony/src/stevie/src/RCS/keymap.h,v 1.2 89/03/11 22:42:30 tony Exp $ X * X * Keycode definitions for special keys X * X * On systems that have any of these keys, the routine 'inchar' in the X * machine-dependent code should return one of the codes here. X */ X X#define K_HELP 0x80 X#define K_UNDO 0x81 X#define K_INSERT 0x82 X#define K_HOME 0x83 X#define K_UARROW 0x84 X#define K_DARROW 0x85 X#define K_LARROW 0x86 X#define K_RARROW 0x87 X#define K_CGRAVE 0x88 /* control grave accent */ X X#define K_F1 0x91 /* function keys */ X#define K_F2 0x92 X#define K_F3 0x93 X#define K_F4 0x94 X#define K_F5 0x95 X#define K_F6 0x96 X#define K_F7 0x97 X#define K_F8 0x98 X#define K_F9 0x99 X#define K_F10 0x9a X X#define K_SF1 0xa1 /* shifted function keys */ X#define K_SF2 0xa2 X#define K_SF3 0xa3 X#define K_SF4 0xa4 X#define K_SF5 0xa5 X#define K_SF6 0xa6 X#define K_SF7 0xa7 X#define K_SF8 0xa8 X#define K_SF9 0xa9 X#define K_SF10 0xaa HE_HATES_THESE_CANS if test 936 -ne "`wc -c < 'keymap.h'`" then echo shar: error transmitting "'keymap.h'" '(should have been 936 characters)' fi fi # end of overwriting check echo shar: extracting "'linefunc.c'" '(1583 characters)' if test -f 'linefunc.c' then echo shar: will not over-write existing file "'linefunc.c'" else sed 's/^X//' << \HE_HATES_THESE_CANS > 'linefunc.c' X/* $Header: /nw/tony/src/stevie/src/RCS/linefunc.c,v 1.2 89/03/11 22:42:32 tony Exp $ X * X * Basic line-oriented motions. X */ X X#include "stevie.h" X X/* X * nextline(curr) X * X * Return a pointer to the beginning of the next line after the one X * referenced by 'curr'. Return NULL if there is no next line (at EOF). X */ X XLPTR * Xnextline(curr) XLPTR *curr; X{ X static LPTR next; X X if (curr->linep->next != Fileend->linep) { X next.index = 0; X next.linep = curr->linep->next; X return &next; X } X return (LPTR *) NULL; X} X X/* X * prevline(curr) X * X * Return a pointer to the beginning of the line before the one X * referenced by 'curr'. Return NULL if there is no prior line. X */ X XLPTR * Xprevline(curr) XLPTR *curr; X{ X static LPTR prev; X X if (curr->linep->prev != Filetop->linep) { X prev.index = 0; X prev.linep = curr->linep->prev; X return &prev; X } X return (LPTR *) NULL; X} X X/* X * coladvance(p,col) X * X * Try to advance to the specified column, starting at p. X */ X XLPTR * Xcoladvance(p, col) XLPTR *p; Xregister int col; X{ X static LPTR lp; X register int c, in; X X lp.linep = p->linep; X lp.index = p->index; X X /* If we're on a blank ('\n' only) line, we can't do anything */ X if (lp.linep->s[lp.index] == '\0') X return &lp; X /* try to advance to the specified column */ X for ( c=0; col-- > 0; c++ ) { X /* Count a tab for what it's worth (if list mode not on) */ X if ( gchar(&lp) == TAB && !P(P_LS) ) { X in = ((P(P_TS)-1) - c%P(P_TS)); X col -= in; X c += in; X } X /* Don't go past the end of */ X /* the file or the line. */ X if (inc(&lp)) { X dec(&lp); X break; X } X } X return &lp; X} HE_HATES_THESE_CANS if test 1583 -ne "`wc -c < 'linefunc.c'`" then echo shar: error transmitting "'linefunc.c'" '(should have been 1583 characters)' fi fi # end of overwriting check echo shar: extracting "'main.c'" '(7199 characters)' if test -f 'main.c' then echo shar: will not over-write existing file "'main.c'" else sed 's/^X//' << \HE_HATES_THESE_CANS > 'main.c' X/* $Header: /nw/tony/src/stevie/src/RCS/main.c,v 1.12 89/08/02 19:53:27 tony Exp $ X * X * The main routine and routines to deal with the input buffer. X */ X X#include "stevie.h" X Xint Rows; /* Number of Rows and Columns */ Xint Columns; /* in the current window. */ X Xchar *Realscreen = NULL; /* What's currently on the screen, a single */ X /* array of size Rows*Columns. */ Xchar *Nextscreen = NULL; /* What's to be put on the screen. */ X Xchar *Filename = NULL; /* Current file name */ X XLPTR *Filemem; /* Pointer to the first line of the file */ X XLPTR *Filetop; /* Line 'above' the start of the file */ X XLPTR *Fileend; /* Pointer to the end of the file in Filemem. */ X /* (It points to the byte AFTER the last byte.) */ X XLPTR *Topchar; /* Pointer to the byte in Filemem which is */ X /* in the upper left corner of the screen. */ X XLPTR *Botchar; /* Pointer to the byte in Filemem which is */ X /* just off the bottom of the screen. */ X XLPTR *Curschar; /* Pointer to byte in Filemem at which the */ X /* cursor is currently placed. */ X Xint Cursrow, Curscol; /* Current position of cursor */ X Xint Cursvcol; /* Current virtual column, the column number of */ X /* the file's actual line, as opposed to the */ X /* column number we're at on the screen. This */ X /* makes a difference on lines that span more */ X /* than one screen line. */ X Xint Curswant = 0; /* The column we'd like to be at. This is used */ X /* try to stay in the same column through up/down */ X /* cursor motions. */ X Xbool_t set_want_col; /* If set, then update Curswant the next time */ X /* through cursupdate() to the current virtual */ X /* column. */ X Xint State = NORMAL; /* This is the current state of the command */ X /* interpreter. */ X Xint Prenum = 0; /* The (optional) number before a command. */ X XLPTR *Insstart; /* This is where the latest insert/append */ X /* mode started. */ X Xbool_t Changed = 0; /* Set to 1 if something in the file has been */ X /* changed and not written out. */ X Xchar Redobuff[1024]; /* Each command should stuff characters into this */ X /* buffer that will re-execute itself. */ X Xchar Insbuff[1024]; /* Each insertion gets stuffed into this buffer. */ X Xint Ninsert = 0; /* Number of characters in the current insertion. */ Xchar *Insptr = NULL; X Xbool_t got_int=FALSE; /* set to TRUE when an interrupt occurs (if possible) */ X Xbool_t interactive = FALSE; /* set TRUE when main() is ready to roll */ X Xchar **files; /* list of input files */ Xint numfiles; /* number of input files */ Xint curfile; /* number of the current file */ X Xstatic void Xusage() X{ X fprintf(stderr, "usage: stevie [file ...]\n"); X fprintf(stderr, " stevie -t tag\n"); X fprintf(stderr, " stevie +[num] file\n"); X fprintf(stderr, " stevie +/pat file\n"); X exit(1); X} X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ X char *initstr, *getenv(); /* init string from the environment */ X char *tag = NULL; /* tag from command line */ X char *pat = NULL; /* pattern from command line */ X int line = -1; /* line number from command line */ X X /* X * Process the command line arguments. X */ X if (argc > 1) { X switch (argv[1][0]) { X X case '-': /* -t tag */ X if (argv[1][1] != 't') X usage(); X X if (argv[2] == NULL) X usage(); X X Filename = NULL; X tag = argv[2]; X numfiles = 1; X break; X X case '+': /* +n or +/pat */ X if (argv[1][1] == '/') { X if (argv[2] == NULL) X usage(); X Filename = strsave(argv[2]); X pat = &(argv[1][1]); X numfiles = 1; X X } else if (isdigit(argv[1][1]) || argv[1][1] == NUL) { X if (argv[2] == NULL) X usage(); X Filename = strsave(argv[2]); X numfiles = 1; X X line = (isdigit(argv[1][1])) ? X atoi(&(argv[1][1])) : 0; X } else X usage(); X X break; X X default: /* must be a file name */ X Filename = strsave(argv[1]); X files = &(argv[1]); X numfiles = argc - 1; X break; X } X } else { X Filename = NULL; X numfiles = 1; X } X curfile = 0; X X if (numfiles > 1) X fprintf(stderr, "%d files to edit\n", numfiles); X X windinit(); X X /* X * Allocate LPTR structures for all the various position pointers X */ X if ((Filemem = (LPTR *) malloc(sizeof(LPTR))) == NULL || X (Filetop = (LPTR *) malloc(sizeof(LPTR))) == NULL || X (Fileend = (LPTR *) malloc(sizeof(LPTR))) == NULL || X (Topchar = (LPTR *) malloc(sizeof(LPTR))) == NULL || X (Botchar = (LPTR *) malloc(sizeof(LPTR))) == NULL || X (Curschar = (LPTR *) malloc(sizeof(LPTR))) == NULL || X (Insstart = (LPTR *) malloc(sizeof(LPTR))) == NULL ) { X fprintf(stderr, "Can't allocate data structures\n"); X windexit(0); X } X X screenalloc(); X filealloc(); /* Initialize Filemem, Filetop, and Fileend */ X X screenclear(); X X if ((initstr = getenv("EXINIT")) != NULL) { X char *lp, buf[128]; X X if ((lp = getenv("LINES")) != NULL) { X sprintf(buf, "%s lines=%s", initstr, lp); X docmdln(buf); X } else X docmdln(initstr); X } X X if (Filename != NULL) { X if (readfile(Filename, Filemem, FALSE)) X filemess("[New File]"); X } else if (tag == NULL) X msg("Empty Buffer"); X X setpcmark(); X X if (tag) { X stuffin(":ta "); X stuffin(tag); X stuffin("\n"); X X } else if (pat) { X stuffin(pat); X stuffin("\n"); X X } else if (line >= 0) { X if (line > 0) X stuffnum(line); X stuffin("G"); X } X X interactive = TRUE; X X edit(); X X windexit(0); X X return 1; /* shouldn't be reached */ X} X X#define RBSIZE 1024 Xstatic char getcbuff[RBSIZE]; Xstatic char *getcnext = NULL; X Xvoid Xstuffin(s) Xchar *s; X{ X if (s == NULL) { /* clear the stuff buffer */ X getcnext = NULL; X return; X } X X if (getcnext == NULL) { X strcpy(getcbuff,s); X getcnext = getcbuff; X } else X strcat(getcbuff,s); X} X Xvoid Xstuffnum(n) Xint n; X{ X char buf[32]; X X sprintf(buf, "%d", n); X stuffin(buf); X} X Xint Xvgetc() X{ X register int c; X X /* X * inchar() may map special keys by using stuffin(). If it does X * so, it returns -1 so we know to loop here to get a real char. X */ X do { X if ( getcnext != NULL ) { X int nextc = *getcnext++; X if ( *getcnext == NUL ) { X *getcbuff = NUL; X getcnext = NULL; X } X return(nextc); X } X c = inchar(); X } while (c == -1); X X return c; X} X X/* X * anyinput X * X * Return non-zero if input is pending. X */ X Xbool_t Xanyinput() X{ X return (getcnext != NULL); X} X X/* X * do_mlines() - process mode lines for the current file X * X * Returns immediately if the "ml" parameter isn't set. X */ X#define NMLINES 5 /* no. of lines at start/end to check for modelines */ X Xvoid Xdo_mlines() X{ X void chk_mline(); X int i; X register LPTR *p; X X if (!P(P_ML)) X return; X X p = Filemem; X for (i=0; i < NMLINES ;i++) { X chk_mline(p->linep->s); X if ((p = nextline(p)) == NULL) X break; X } X X if ((p = prevline(Fileend)) == NULL) X return; X X for (i=0; i < NMLINES ;i++) { X chk_mline(p->linep->s); X if ((p = prevline(p)) == NULL) X break; X } X} X X/* X * chk_mline() - check a single line for a mode string X */ Xstatic void Xchk_mline(s) Xregister char *s; X{ X register char *cs; /* local copy of any modeline found */ X register char *e; X X for (; *s != NUL ;s++) { X if (strncmp(s, "vi:", 3) == 0 || strncmp(s, "ex:", 3) == 0) { X cs = strsave(s+3); X if ((e = strchr(cs, ':')) != NULL) { X *e = NUL; X stuffin(mkstr(CTRL('o'))); X docmdln(cs); X } X free(cs); X } X } X} HE_HATES_THESE_CANS if test 7199 -ne "`wc -c < 'main.c'`" then echo shar: error transmitting "'main.c'" '(should have been 7199 characters)' fi fi # end of overwriting check echo shar: extracting "'mark.c'" '(2186 characters)' if test -f 'mark.c' then echo shar: will not over-write existing file "'mark.c'" else sed 's/^X//' << \HE_HATES_THESE_CANS > 'mark.c' X/* $Header: /nw/tony/src/stevie/src/RCS/mark.c,v 1.3 89/03/11 22:42:39 tony Exp $ X * X * Routines to save and retrieve marks. X */ X X#include "stevie.h" X X#define NMARKS 10 /* max. # of marks that can be saved */ X Xstruct mark { X char name; X LPTR pos; X}; X Xstatic struct mark mlist[NMARKS]; Xstatic struct mark pcmark; /* previous context mark */ Xstatic bool_t pcvalid = FALSE; /* true if pcmark is valid */ X X/* X * setmark(c) - set mark 'c' at current cursor position X * X * Returns TRUE on success, FALSE if no room for mark or bad name given. X */ Xbool_t Xsetmark(c) Xregister char c; X{ X register int i; X X if (!isalpha(c)) X return FALSE; X X /* X * If there is already a mark of this name, then just use the X * existing mark entry. X */ X for (i=0; i < NMARKS ;i++) { X if (mlist[i].name == c) { X mlist[i].pos = *Curschar; X return TRUE; X } X } X X /* X * There wasn't a mark of the given name, so find a free slot X */ X for (i=0; i < NMARKS ;i++) { X if (mlist[i].name == NUL) { /* got a free one */ X mlist[i].name = c; X mlist[i].pos = *Curschar; X return TRUE; X } X } X return FALSE; X} X X/* X * setpcmark() - set the previous context mark to the current position X */ Xvoid Xsetpcmark() X{ X pcmark.pos = *Curschar; X pcvalid = TRUE; X} X X/* X * getmark(c) - find mark for char 'c' X * X * Return pointer to LPTR or NULL if no such mark. X */ XLPTR * Xgetmark(c) Xregister char c; X{ X register int i; X X if (c == '\'' || c == '`') /* previous context mark */ X return pcvalid ? &(pcmark.pos) : (LPTR *) NULL; X X for (i=0; i < NMARKS ;i++) { X if (mlist[i].name == c) X return &(mlist[i].pos); X } X return (LPTR *) NULL; X} X X/* X * clrall() - clear all marks X * X * Used mainly when trashing the entire buffer during ":e" type commands X */ Xvoid Xclrall() X{ X register int i; X X for (i=0; i < NMARKS ;i++) X mlist[i].name = NUL; X pcvalid = FALSE; X} X X/* X * clrmark(line) - clear any marks for 'line' X * X * Used any time a line is deleted so we don't have marks pointing to X * non-existent lines. X */ Xvoid Xclrmark(line) Xregister LINE *line; X{ X register int i; X X for (i=0; i < NMARKS ;i++) { X if (mlist[i].pos.linep == line) X mlist[i].name = NUL; X } X if (pcvalid && (pcmark.pos.linep == line)) X pcvalid = FALSE; X} HE_HATES_THESE_CANS if test 2186 -ne "`wc -c < 'mark.c'`" then echo shar: error transmitting "'mark.c'" '(should have been 2186 characters)' fi fi # end of overwriting check echo shar: extracting "'misccmds.c'" '(9492 characters)' if test -f 'misccmds.c' then echo shar: will not over-write existing file "'misccmds.c'" else sed 's/^X//' << \HE_HATES_THESE_CANS > 'misccmds.c' X/* $Header: /nw/tony/src/stevie/src/RCS/misccmds.c,v 1.14 89/08/06 09:50:17 tony Exp $ X * X * Various routines to perform specific editing operations or return X * useful information about the file. X */ X X#include "stevie.h" X Xstatic void openfwd(), openbwd(); X Xextern bool_t did_ai; X X/* X * opencmd X * X * Add a blank line above or below the current line. X */ X Xvoid Xopencmd(dir, can_ai) Xint dir; Xint can_ai; /* if true, consider auto-indent */ X{ X if (dir == FORWARD) X openfwd(can_ai); X else X openbwd(can_ai); X} X Xstatic void Xopenfwd(can_ai) Xint can_ai; X{ X register LINE *l; X LPTR *next; X register char *s; /* string to be moved to new line, if any */ X int newindex = 0; /* index of the cursor on the new line */ X X /* X * If we're in insert mode, we need to move the remainder of the X * current line onto the new line. Otherwise the new line is left X * blank. X */ X if (State == INSERT || State == REPLACE) X s = &Curschar->linep->s[Curschar->index]; X else X s = ""; X X if ((next = nextline(Curschar)) == NULL) /* open on last line */ X next = Fileend; X X /* X * By asking for as much space as the prior line had we make sure X * that we'll have enough space for any auto-indenting. X */ X if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) X return; X X if (*s != NUL) X strcpy(l->s, s); /* copy string to new line */ X X else if (can_ai && P(P_AI) && !anyinput()) { X char *p; X X /* X * Copy prior line, and truncate after white space X */ X strcpy(l->s, Curschar->linep->s); X X for (p = l->s; *p == ' ' || *p == TAB ;p++) X ; X *p = NUL; X newindex = p - l->s; X X /* X * If we just did an auto-indent, then we didn't type X * anything on the prior line, and it should be truncated. X */ X if (did_ai) X Curschar->linep->s[0] = NUL; X X did_ai = TRUE; X } X X /* truncate current line at cursor */ X if (State == INSERT || State == REPLACE) X *s = NUL; X X X Curschar->linep->next = l; /* link neighbors to new line */ X next->linep->prev = l; X X l->prev = Curschar->linep; /* link new line to neighbors */ X l->next = next->linep; X X if (next == Fileend) /* new line at end */ X l->num = Curschar->linep->num + LINEINC; X X else if ((l->prev->num) + 1 == l->next->num) /* no gap, renumber */ X renum(); X X else { /* stick it in the middle */ X unsigned long lnum; X lnum = ((long)l->prev->num + (long)l->next->num) / 2; X l->num = lnum; X } X X /* X * Get the cursor to the start of the line, so that 'Cursrow' X * gets set to the right physical line number for the stuff X * that follows... X */ X Curschar->index = 0; X cursupdate(); X X /* X * If we're doing an open on the last logical line, then X * go ahead and scroll the screen up. Otherwise, just insert X * a blank line at the right place. We use calls to plines() X * in case the cursor is resting on a long line. X */ X if (Cursrow + plines(Curschar) == (Rows - 1)) X scrollup(1); X else X s_ins(Cursrow+plines(Curschar), 1); X X *Curschar = *nextline(Curschar); /* cursor moves down */ X Curschar->index = newindex; X X updatescreen(); /* because Botchar is now invalid... */ X X cursupdate(); /* update Cursrow before insert */ X} X Xstatic void Xopenbwd(can_ai) Xint can_ai; X{ X register LINE *l; X LINE *prev; X int newindex = 0; X X prev = Curschar->linep->prev; X X if ((l = newline(strlen(Curschar->linep->s) + SLOP)) == NULL) X return; X X Curschar->linep->prev = l; /* link neighbors to new line */ X prev->next = l; X X l->next = Curschar->linep; /* link new line to neighbors */ X l->prev = prev; X X if (can_ai && P(P_AI) && !anyinput()) { X char *p; X X /* X * Copy current line, and truncate after white space X */ X strcpy(l->s, Curschar->linep->s); X X for (p = l->s; *p == ' ' || *p == TAB ;p++) X ; X *p = NUL; X newindex = p - l->s; X X did_ai = TRUE; X } X X Curschar->linep = Curschar->linep->prev; X Curschar->index = newindex; X X if (prev == Filetop->linep) /* new start of file */ X Filemem->linep = l; X X renum(); /* keep it simple - we don't do this often */ X X cursupdate(); /* update Cursrow before insert */ X if (Cursrow != 0) X s_ins(Cursrow, 1); /* insert a physical line */ X X updatescreen(); X} X Xint Xcntllines(pbegin,pend) Xregister LPTR *pbegin, *pend; X{ X register LINE *lp; X int lnum = 1; X X for (lp = pbegin->linep; lp != pend->linep ;lp = lp->next) X lnum++; X X return(lnum); X} X X/* X * plines(p) - return the number of physical screen lines taken by line 'p' X */ Xint Xplines(p) XLPTR *p; X{ X register int col = 0; X register char *s; X X s = p->linep->s; X X if (*s == NUL) /* empty line */ X return 1; X X for (; *s != NUL ;s++) { X if ( *s == TAB && !P(P_LS)) X col += P(P_TS) - (col % P(P_TS)); X else X col += chars[(unsigned)(*s & 0xff)].ch_size; X } X X /* X * If list mode is on, then the '$' at the end of X * the line takes up one extra column. X */ X if (P(P_LS)) X col += 1; X /* X * If 'number' mode is on, add another 8. X */ X if (P(P_NU)) X col += 8; X X return ((col + (Columns-1)) / Columns); X} X Xvoid Xfileinfo() X{ X extern int numfiles, curfile; X register long l1, l2; X X if (bufempty()) { X l1 = 0; X l2 = 1; /* don't div by zero */ X } else { X l1 = cntllines(Filemem, Curschar); X l2 = cntllines(Filemem, Fileend) - 1; X } X X if (numfiles > 1) X smsg("\"%s\"%s line %ld of %ld -- %ld %% -- (file %d of %d)", X (Filename != NULL) ? Filename : "No File", X Changed ? " [Modified]" : "", X l1, l2, (l1 * 100)/l2, X curfile+1, numfiles); X else X smsg("\"%s\"%s line %ld of %ld -- %ld %% --", X (Filename != NULL) ? Filename : "No File", X Changed ? " [Modified]" : "", X l1, l2, (l1 * 100)/l2); X} X X/* X * gotoline(n) - return a pointer to line 'n' X * X * Returns a pointer to the last line of the file if n is zero, or X * beyond the end of the file. X */ XLPTR * Xgotoline(n) Xregister int n; X{ X static LPTR l; X X l.index = 0; X X if ( n == 0 ) X l = *prevline(Fileend); X else { X LPTR *p; X X for (l = *Filemem; --n > 0 ;l = *p) X if ((p = nextline(&l)) == NULL) X break; X } X return &l; X} X Xvoid Xinschar(c) Xint c; X{ X register char *p, *pend; X X /* make room for the new char. */ X if ( ! canincrease(1) ) X return; X X if (State != REPLACE) { X p = &Curschar->linep->s[strlen(Curschar->linep->s) + 1]; X pend = &Curschar->linep->s[Curschar->index]; X X for (; p > pend ;p--) X *p = *(p-1); X X *p = c; X X } else { /* replace mode */ X /* X * Once we reach the end of the line, we are effectively X * inserting new text, so make sure the string terminator X * stays out there. X */ X if (gchar(Curschar) == NUL) X Curschar->linep->s[Curschar->index+1] = NUL; X pchar(Curschar, c); X } X X /* X * If we're in insert mode and showmatch mode is set, then X * check for right parens and braces. If there isn't a match, X * then beep. If there is a match AND it's on the screen, then X * flash to it briefly. If it isn't on the screen, don't do anything. X */ X if (P(P_SM) && State == INSERT && (c == ')' || c == '}' || c == ']')) { X LPTR *lpos, csave; X X if ((lpos = showmatch()) == NULL) /* no match, so beep */ X beep(); X else if (LINEOF(lpos) >= LINEOF(Topchar)) { X updatescreen(); /* show the new char first */ X csave = *Curschar; X *Curschar = *lpos; /* move to matching char */ X cursupdate(); X windgoto(Cursrow, Curscol); X delay(); /* brief pause */ X *Curschar = csave; /* restore cursor position */ X cursupdate(); X } X } X X inc(Curschar); X CHANGED; X} X Xbool_t Xdelchar(fixpos) Xbool_t fixpos; /* if TRUE, fix the cursor position when done */ X{ X register int i; X X /* Check for degenerate case; there's nothing in the file. */ X if (bufempty()) X return FALSE; X X if (lineempty()) /* can't do anything */ X return FALSE; X X /* Delete the char. at Curschar by shifting everything */ X /* in the line down. */ X for ( i=Curschar->index+1; i < Curschar->linep->size ;i++) X Curschar->linep->s[i-1] = Curschar->linep->s[i]; X X /* If we just took off the last character of a non-blank line, */ X /* we don't want to end up positioned at the newline. */ X if (fixpos) { X if (gchar(Curschar)==NUL && Curschar->index>0 && State!=INSERT) X Curschar->index--; X } X CHANGED; X X return TRUE; X} X X Xvoid Xdelline(nlines, can_update) Xint nlines; Xbool_t can_update; X{ X register LINE *p, *q; X int doscreen; /* if true, update the screen */ X X doscreen = can_update; X /* X * There's no point in keeping the screen updated if we're X * deleting more than a screen's worth of lines. X */ X if (nlines > (Rows - 1) && can_update) { X doscreen = FALSE; X s_del(Cursrow, Rows-1); /* flaky way to clear rest of screen */ X } X X while ( nlines-- > 0 ) { X X if (bufempty()) /* nothing to delete */ X break; X X if (buf1line()) { /* just clear the line */ X Curschar->linep->s[0] = NUL; X Curschar->index = 0; X break; X } X X p = Curschar->linep->prev; X q = Curschar->linep->next; X X if (p == Filetop->linep) { /* first line of file so... */ X Filemem->linep = q; /* adjust start of file */ X Topchar->linep = q; /* and screen */ X } X p->next = q; X q->prev = p; X X clrmark(Curschar->linep); /* clear marks for the line */ X X /* X * Delete the correct number of physical lines on the screen X */ X if (doscreen) X s_del(Cursrow, plines(Curschar)); X X /* X * If deleting the top line on the screen, adjust Topchar X */ X if (Topchar->linep == Curschar->linep) X Topchar->linep = q; X X free(Curschar->linep->s); X free((char *) Curschar->linep); X X Curschar->linep = q; X Curschar->index = 0; /* is this right? */ X CHANGED; X X /* If we delete the last line in the file, back up */ X if ( Curschar->linep == Fileend->linep) { X Curschar->linep = Curschar->linep->prev; X /* and don't try to delete any more lines */ X break; X } X } X} HE_HATES_THESE_CANS if test 9492 -ne "`wc -c < 'misccmds.c'`" then echo shar: error transmitting "'misccmds.c'" '(should have been 9492 characters)' fi fi # end of overwriting check # End of shell archive exit 0 --