aboutsummaryrefslogtreecommitdiff
path: root/editors/vi.c
diff options
context:
space:
mode:
authorGlenn L McGrath <bug1@ihug.co.nz>2002-12-02 21:18:10 +0000
committerGlenn L McGrath <bug1@ihug.co.nz>2002-12-02 21:18:10 +0000
commit09adaca37d6bd67745c1c81c598ba25006f990b4 (patch)
tree7393efda99ebc952755c2a92360c4f6c873d000a /editors/vi.c
parent06b1aeaf0ad1748a6e355df3e0e8052d613aa158 (diff)
downloadbusybox-09adaca37d6bd67745c1c81c598ba25006f990b4.tar.gz
last_patch_69, 8 bit clean and other fixes from Vladimir N. Oleynik
Diffstat (limited to 'editors/vi.c')
-rw-r--r--editors/vi.c859
1 files changed, 450 insertions, 409 deletions
diff --git a/editors/vi.c b/editors/vi.c
index 835adb62e..8e9ecc925 100644
--- a/editors/vi.c
+++ b/editors/vi.c
@@ -19,7 +19,7 @@
*/
static const char vi_Version[] =
- "$Id: vi.c,v 1.25 2002/11/28 11:27:23 aaronl Exp $";
+ "$Id: vi.c,v 1.26 2002/12/02 21:18:08 bug1 Exp $";
/*
* To compile for standalone use:
@@ -87,6 +87,12 @@ static const char vi_Version[] =
#include "busybox.h"
#endif /* STANDALONE */
+#ifdef CONFIG_LOCALE_SUPPORT
+#define Isprint(c) isprint((c))
+#else
+#define Isprint(c) ( (c) >= ' ' && (c) != 127 && (c) != ((unsigned char)'\233') )
+#endif
+
#ifndef TRUE
#define TRUE ((int)1)
#define FALSE ((int)0)
@@ -116,6 +122,22 @@ static const char vi_Version[] =
#define VI_K_FUN11 147 // Function Key F11
#define VI_K_FUN12 148 // Function Key F12
+/* vt102 typical ESC sequence */
+/* terminal standout start/normal ESC sequence */
+static const char SOs[] = "\033[7m";
+static const char SOn[] = "\033[0m";
+/* terminal bell sequence */
+static const char bell[] = "\007";
+/* Clear-end-of-line and Clear-end-of-screen ESC sequence */
+static const char Ceol[] = "\033[0K";
+static const char Ceos [] = "\033[0J";
+/* Cursor motion arbitrary destination ESC sequence */
+static const char CMrc[] = "\033[%d;%dH";
+/* Cursor motion up and down ESC sequence */
+static const char CMup[] = "\033[A";
+static const char CMdown[] = "\n";
+
+
static const int YANKONLY = FALSE;
static const int YANKDEL = TRUE;
static const int FORWARD = 1; // code depends on "1" for array index
@@ -131,27 +153,29 @@ static const int S_END_ALNUM = 5; // used in skip_thing() for moving "dot"
typedef unsigned char Byte;
+static int vi_setops;
+#define VI_AUTOINDENT 1
+#define VI_SHOWMATCH 2
+#define VI_IGNORECASE 4
+#define VI_ERR_METHOD 8
+#define autoindent (vi_setops & VI_AUTOINDENT)
+#define showmatch (vi_setops & VI_SHOWMATCH )
+#define ignorecase (vi_setops & VI_IGNORECASE)
+/* indicate error with beep or flash */
+#define err_method (vi_setops & VI_ERR_METHOD)
+
static int editing; // >0 while we are editing a file
static int cmd_mode; // 0=command 1=insert
static int file_modified; // buffer contents changed
-static int err_method; // indicate error with beep or flash
static int fn_start; // index of first cmd line file name
static int save_argc; // how many file names on cmd line
static int cmdcnt; // repetition count
static fd_set rfds; // use select() for small sleeps
static struct timeval tv; // use select() for small sleeps
-static char erase_char; // the users erase character
static int rows, columns; // the terminal screen is this size
static int crow, ccol, offset; // cursor is on Crow x Ccol with Horz Ofset
-static char *SOs, *SOn; // terminal standout start/normal ESC sequence
-static char *bell; // terminal bell sequence
-static char *Ceol, *Ceos; // Clear-end-of-line and Clear-end-of-screen ESC sequence
-static char *CMrc; // Cursor motion arbitrary destination ESC sequence
-static char *CMup, *CMdown; // Cursor motion up and down ESC sequence
static Byte *status_buffer; // mesages to the user
-static Byte last_input_char; // last char read from user
-static Byte last_forward_char; // last char searched for with 'f'
static Byte *cfn; // previous, current, and next file name
static Byte *text, *end, *textend; // pointers to the user data in memory
static Byte *screen; // pointer to the virtual screen buffer
@@ -160,6 +184,9 @@ static Byte *screenbegin; // index into text[], of top line on the screen
static Byte *dot; // where all the action takes place
static int tabstop;
static struct termios term_orig, term_vi; // remember what the cooked mode was
+static Byte erase_char; // the users erase character
+static Byte last_input_char; // last char read from user
+static Byte last_forward_char; // last char searched for with 'f'
#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
static int last_row; // where the cursor was last moved to
@@ -167,6 +194,9 @@ static int last_row; // where the cursor was last moved to
#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
static jmp_buf restart; // catch_sig()
#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */
+#if defined(CONFIG_FEATURE_VI_USE_SIGNALS) || defined(CONFIG_FEATURE_VI_CRASHME)
+static int my_pid;
+#endif
#ifdef CONFIG_FEATURE_VI_WIN_RESIZE
static struct winsize winsize; // remember the window size
#endif /* CONFIG_FEATURE_VI_WIN_RESIZE */
@@ -181,11 +211,6 @@ static Byte *modifying_cmds; // cmds that modify text[]
#ifdef CONFIG_FEATURE_VI_READONLY
static int vi_readonly, readonly;
#endif /* CONFIG_FEATURE_VI_READONLY */
-#ifdef CONFIG_FEATURE_VI_SETOPTS
-static int autoindent;
-static int showmatch;
-static int ignorecase;
-#endif /* CONFIG_FEATURE_VI_SETOPTS */
#ifdef CONFIG_FEATURE_VI_YANKMARK
static Byte *reg[28]; // named register a-z, "D", and "U" 0-25,26,27
static int YDreg, Ureg; // default delete register and orig line for "U"
@@ -202,7 +227,6 @@ static void do_cmd(Byte); // execute a command
static void sync_cursor(Byte *, int *, int *); // synchronize the screen cursor to dot
static Byte *begin_line(Byte *); // return pointer to cur line B-o-l
static Byte *end_line(Byte *); // return pointer to cur line E-o-l
-extern inline Byte *dollar_line(Byte *); // return pointer to just before NL
static Byte *prev_line(Byte *); // return pointer to prev line B-o-l
static Byte *next_line(Byte *); // return pointer to next line B-o-l
static Byte *end_screen(void); // get pointer to last char on screen
@@ -232,13 +256,12 @@ static Byte *text_hole_delete(Byte *, Byte *); // at "p", delete a 'size' byte h
static Byte *text_hole_make(Byte *, int); // at "p", make a 'size' byte hole
static Byte *yank_delete(Byte *, Byte *, int, int); // yank text[] into register then delete
static void show_help(void); // display some help info
-extern inline void print_literal(Byte *, Byte *); // copy s to buf, convert unprintable
static void rawmode(void); // set "raw" mode on tty
static void cookmode(void); // return to "cooked" mode on tty
static int mysleep(int); // sleep for 'h' 1/100 seconds
static Byte readit(void); // read (maybe cursor) key from stdin
static Byte get_one_char(void); // read 1 char from stdin
-static int file_size(Byte *); // what is the byte size of "fn"
+static int file_size(const Byte *); // what is the byte size of "fn"
static int file_insert(Byte *, Byte *, int);
static int file_write(Byte *, Byte *, Byte *);
static void place_cursor(int, int, int);
@@ -248,17 +271,18 @@ static void clear_to_eos(void);
static void standout_start(void); // send "start reverse video" sequence
static void standout_end(void); // send "end reverse video" sequence
static void flash(int); // flash the terminal screen
-static void beep(void); // beep the terminal
-static void indicate_error(char); // use flash or beep to indicate error
static void show_status_line(void); // put a message on the bottom line
-static void psb(char *, ...); // Print Status Buf
-static void psbs(char *, ...); // Print Status Buf in standout mode
+static void psb(const char *, ...); // Print Status Buf
+static void psbs(const char *, ...); // Print Status Buf in standout mode
static void ni(Byte *); // display messages
static void edit_status(void); // show file status on status line
static void redraw(int); // force a full screen refresh
static void format_line(Byte*, Byte*, int);
static void refresh(int); // update the terminal from screen[]
+static void Indicate_Error(void); // use flash or beep to indicate error
+#define indicate_error(c) Indicate_Error()
+
#ifdef CONFIG_FEATURE_VI_SEARCH
static Byte *char_search(Byte *, Byte *, int, int); // search for pattern starting at p
static int mycmp(Byte *, Byte *, int); // string cmp based in "ignorecase"
@@ -269,12 +293,10 @@ static Byte *get_one_address(Byte *, int *); // get colon addr, if present
static Byte *get_address(Byte *, int *, int *); // get two colon addrs, if present
static void colon(Byte *); // execute the "colon" mode cmds
#endif /* CONFIG_FEATURE_VI_COLON */
-static Byte *get_input_line(Byte *); // get input line- use "status line"
#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
static void winch_sig(int); // catch window size changes
static void suspend_sig(int); // catch ctrl-Z
-static void alarm_sig(int); // catch alarm time-outs
-static void catch_sig(int); // catch ctrl-C
+static void catch_sig(int); // catch ctrl-C and alarm time-outs
static void core_sig(int); // catch a core dump signal
#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */
#ifdef CONFIG_FEATURE_VI_DOT_CMD
@@ -296,7 +318,6 @@ static Byte *string_insert(Byte *, Byte *); // insert the string at 'p'
static Byte *text_yank(Byte *, Byte *, int); // save copy of "p" into a register
static Byte what_reg(void); // what is letter of current YDreg
static void check_context(Byte); // remember context for '' command
-extern inline Byte *swap_context(Byte *); // goto new context for '' command
#endif /* CONFIG_FEATURE_VI_YANKMARK */
#ifdef CONFIG_FEATURE_VI_CRASHME
static void crash_dummy();
@@ -305,26 +326,28 @@ static int crashme = 0;
#endif /* CONFIG_FEATURE_VI_CRASHME */
+static void write1(const char *out)
+{
+ fputs(out, stdout);
+}
+
extern int vi_main(int argc, char **argv)
{
int c;
+ RESERVE_CONFIG_BUFFER(STATUS_BUFFER, 200);
#ifdef CONFIG_FEATURE_VI_YANKMARK
int i;
#endif /* CONFIG_FEATURE_VI_YANKMARK */
-
- CMrc= "\033[%d;%dH"; // Terminal Crusor motion ESC sequence
- CMup= "\033[A"; // move cursor up one line, same col
- CMdown="\n"; // move cursor down one line, same col
- Ceol= "\033[0K"; // Clear from cursor to end of line
- Ceos= "\033[0J"; // Clear from cursor to end of screen
- SOs = "\033[7m"; // Terminal standout mode on
- SOn = "\033[0m"; // Terminal standout mode off
- bell= "\007"; // Terminal bell sequence
+#if defined(CONFIG_FEATURE_VI_USE_SIGNALS) || defined(CONFIG_FEATURE_VI_CRASHME)
+ my_pid = getpid();
+#endif
#ifdef CONFIG_FEATURE_VI_CRASHME
- (void) srand((long) getpid());
+ (void) srand((long) my_pid);
#endif /* CONFIG_FEATURE_VI_CRASHME */
- status_buffer = (Byte *) xmalloc(200); // hold messages to user
+
+ status_buffer = STATUS_BUFFER;
+
#ifdef CONFIG_FEATURE_VI_READONLY
vi_readonly = readonly = FALSE;
if (strncmp(argv[0], "view", 4) == 0) {
@@ -332,11 +355,7 @@ extern int vi_main(int argc, char **argv)
vi_readonly = TRUE;
}
#endif /* CONFIG_FEATURE_VI_READONLY */
-#ifdef CONFIG_FEATURE_VI_SETOPTS
- autoindent = 1;
- ignorecase = 1;
- showmatch = 1;
-#endif /* CONFIG_FEATURE_VI_SETOPTS */
+ vi_setops = VI_AUTOINDENT | VI_SHOWMATCH | VI_IGNORECASE | VI_ERR_METHOD;
#ifdef CONFIG_FEATURE_VI_YANKMARK
for (i = 0; i < 28; i++) {
reg[i] = 0;
@@ -395,11 +414,10 @@ extern int vi_main(int argc, char **argv)
static void edit_file(Byte * fn)
{
- char c;
+ Byte c;
int cnt, size, ch;
#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
- char *msg;
int sig;
#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */
#ifdef CONFIG_FEATURE_VI_YANKMARK
@@ -435,33 +453,20 @@ static void edit_file(Byte * fn)
mark[26] = mark[27] = text; // init "previous context"
#endif /* CONFIG_FEATURE_VI_YANKMARK */
- err_method = 1; // flash
last_forward_char = last_input_char = '\0';
crow = 0;
ccol = 0;
edit_status();
#ifdef CONFIG_FEATURE_VI_USE_SIGNALS
- signal(SIGHUP, catch_sig);
- signal(SIGINT, catch_sig);
- signal(SIGALRM, alarm_sig);
- signal(SIGTERM, catch_sig);
- signal(SIGQUIT, core_sig);
- signal(SIGILL, core_sig);
- signal(SIGTRAP, core_sig);
- signal(SIGIOT, core_sig);
- signal(SIGABRT, core_sig);
- signal(SIGFPE, core_sig);
- signal(SIGBUS, core_sig);
- signal(SIGSEGV, core_sig);
-#ifdef SIGSYS
- signal(SIGSYS, core_sig);
-#endif
+ catch_sig(0);
+ core_sig(0);
signal(SIGWINCH, winch_sig);
signal(SIGTSTP, suspend_sig);
sig = setjmp(restart);
if (sig != 0) {
- msg = "";
+ const char *msg = "";
+
if (sig == SIGWINCH)
msg = "(window resize)";
if (sig == SIGHUP)
@@ -496,6 +501,7 @@ static void edit_file(Byte * fn)
#endif /* CONFIG_FEATURE_VI_DOT_CMD */
redraw(FALSE); // dont force every col re-draw
show_status_line();
+ fflush(stdout);
//------This is the main Vi cmd handling loop -----------------------
while (editing > 0) {
@@ -549,212 +555,6 @@ static void edit_file(Byte * fn)
cookmode();
}
-static Byte readbuffer[BUFSIZ];
-
-#ifdef CONFIG_FEATURE_VI_CRASHME
-static int totalcmds = 0;
-static int Mp = 85; // Movement command Probability
-static int Np = 90; // Non-movement command Probability
-static int Dp = 96; // Delete command Probability
-static int Ip = 97; // Insert command Probability
-static int Yp = 98; // Yank command Probability
-static int Pp = 99; // Put command Probability
-static int M = 0, N = 0, I = 0, D = 0, Y = 0, P = 0, U = 0;
-char chars[20] = "\t012345 abcdABCD-=.$";
-char *words[20] = { "this", "is", "a", "test",
- "broadcast", "the", "emergency", "of",
- "system", "quick", "brown", "fox",
- "jumped", "over", "lazy", "dogs",
- "back", "January", "Febuary", "March"
-};
-char *lines[20] = {
- "You should have received a copy of the GNU General Public License\n",
- "char c, cm, *cmd, *cmd1;\n",
- "generate a command by percentages\n",
- "Numbers may be typed as a prefix to some commands.\n",
- "Quit, discarding changes!\n",
- "Forced write, if permission originally not valid.\n",
- "In general, any ex or ed command (such as substitute or delete).\n",
- "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n",
- "Please get w/ me and I will go over it with you.\n",
- "The following is a list of scheduled, committed changes.\n",
- "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n",
- "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n",
- "Any question about transactions please contact Sterling Huxley.\n",
- "I will try to get back to you by Friday, December 31.\n",
- "This Change will be implemented on Friday.\n",
- "Let me know if you have problems accessing this;\n",
- "Sterling Huxley recently added you to the access list.\n",
- "Would you like to go to lunch?\n",
- "The last command will be automatically run.\n",
- "This is too much english for a computer geek.\n",
-};
-char *multilines[20] = {
- "You should have received a copy of the GNU General Public License\n",
- "char c, cm, *cmd, *cmd1;\n",
- "generate a command by percentages\n",
- "Numbers may be typed as a prefix to some commands.\n",
- "Quit, discarding changes!\n",
- "Forced write, if permission originally not valid.\n",
- "In general, any ex or ed command (such as substitute or delete).\n",
- "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n",
- "Please get w/ me and I will go over it with you.\n",
- "The following is a list of scheduled, committed changes.\n",
- "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n",
- "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n",
- "Any question about transactions please contact Sterling Huxley.\n",
- "I will try to get back to you by Friday, December 31.\n",
- "This Change will be implemented on Friday.\n",
- "Let me know if you have problems accessing this;\n",
- "Sterling Huxley recently added you to the access list.\n",
- "Would you like to go to lunch?\n",
- "The last command will be automatically run.\n",
- "This is too much english for a computer geek.\n",
-};
-
-// create a random command to execute
-static void crash_dummy()
-{
- static int sleeptime; // how long to pause between commands
- char c, cm, *cmd, *cmd1;
- int i, cnt, thing, rbi, startrbi, percent;
-
- // "dot" movement commands
- cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL";
-
- // is there already a command running?
- if (strlen((char *) readbuffer) > 0)
- goto cd1;
- cd0:
- startrbi = rbi = 0;
- sleeptime = 0; // how long to pause between commands
- memset(readbuffer, '\0', BUFSIZ - 1); // clear the read buffer
- // generate a command by percentages
- percent = (int) lrand48() % 100; // get a number from 0-99
- if (percent < Mp) { // Movement commands
- // available commands
- cmd = cmd1;
- M++;
- } else if (percent < Np) { // non-movement commands
- cmd = "mz<>\'\""; // available commands
- N++;
- } else if (percent < Dp) { // Delete commands
- cmd = "dx"; // available commands
- D++;
- } else if (percent < Ip) { // Inset commands
- cmd = "iIaAsrJ"; // available commands
- I++;
- } else if (percent < Yp) { // Yank commands
- cmd = "yY"; // available commands
- Y++;
- } else if (percent < Pp) { // Put commands
- cmd = "pP"; // available commands
- P++;
- } else {
- // We do not know how to handle this command, try again
- U++;
- goto cd0;
- }
- // randomly pick one of the available cmds from "cmd[]"
- i = (int) lrand48() % strlen(cmd);
- cm = cmd[i];
- if (strchr(":\024", cm))
- goto cd0; // dont allow colon or ctrl-T commands
- readbuffer[rbi++] = cm; // put cmd into input buffer
-
- // now we have the command-
- // there are 1, 2, and multi char commands
- // find out which and generate the rest of command as necessary
- if (strchr("dmryz<>\'\"", cm)) { // 2-char commands
- cmd1 = " \n\r0$^-+wWeEbBhjklHL";
- if (cm == 'm' || cm == '\'' || cm == '\"') { // pick a reg[]
- cmd1 = "abcdefghijklmnopqrstuvwxyz";
- }
- thing = (int) lrand48() % strlen(cmd1); // pick a movement command
- c = cmd1[thing];
- readbuffer[rbi++] = c; // add movement to input buffer
- }
- if (strchr("iIaAsc", cm)) { // multi-char commands
- if (cm == 'c') {
- // change some thing
- thing = (int) lrand48() % strlen(cmd1); // pick a movement command
- c = cmd1[thing];
- readbuffer[rbi++] = c; // add movement to input buffer
- }
- thing = (int) lrand48() % 4; // what thing to insert
- cnt = (int) lrand48() % 10; // how many to insert
- for (i = 0; i < cnt; i++) {
- if (thing == 0) { // insert chars
- readbuffer[rbi++] = chars[((int) lrand48() % strlen(chars))];
- } else if (thing == 1) { // insert words
- strcat((char *) readbuffer, words[(int) lrand48() % 20]);
- strcat((char *) readbuffer, " ");
- sleeptime = 0; // how fast to type
- } else if (thing == 2) { // insert lines
- strcat((char *) readbuffer, lines[(int) lrand48() % 20]);
- sleeptime = 0; // how fast to type
- } else { // insert multi-lines
- strcat((char *) readbuffer, multilines[(int) lrand48() % 20]);
- sleeptime = 0; // how fast to type
- }
- }
- strcat((char *) readbuffer, "\033");
- }
- cd1:
- totalcmds++;
- if (sleeptime > 0)
- (void) mysleep(sleeptime); // sleep 1/100 sec
-}
-
-// test to see if there are any errors
-static void crash_test()
-{
- static time_t oldtim;
- time_t tim;
- char d[2], buf[BUFSIZ], msg[BUFSIZ];
-
- msg[0] = '\0';
- if (end < text) {
- strcat((char *) msg, "end<text ");
- }
- if (end > textend) {
- strcat((char *) msg, "end>textend ");
- }
- if (dot < text) {
- strcat((char *) msg, "dot<text ");
- }
- if (dot > end) {
- strcat((char *) msg, "dot>end ");
- }
- if (screenbegin < text) {
- strcat((char *) msg, "screenbegin<text ");
- }
- if (screenbegin > end - 1) {
- strcat((char *) msg, "screenbegin>end-1 ");
- }
-
- if (strlen(msg) > 0) {
- alarm(0);
- sprintf(buf, "\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s",
- totalcmds, last_input_char, msg, SOs, SOn);
- write(1, buf, strlen(buf));
- while (read(0, d, 1) > 0) {
- if (d[0] == '\n' || d[0] == '\r')
- break;
- }
- alarm(3);
- }
- tim = (time_t) time((time_t *) 0);
- if (tim >= (oldtim + 3)) {
- sprintf((char *) status_buffer,
- "Tot=%d: M=%d N=%d I=%d D=%d Y=%d P=%d U=%d size=%d",
- totalcmds, M, N, I, D, Y, P, U, end - text + 1);
- oldtim = tim;
- }
- return;
-}
-#endif /* CONFIG_FEATURE_VI_CRASHME */
-
//----- The Colon commands -------------------------------------
#ifdef CONFIG_FEATURE_VI_COLON
static Byte *get_one_address(Byte * p, int *addr) // get colon addr, if present
@@ -848,6 +648,23 @@ ga0:
return (p);
}
+#ifdef CONFIG_FEATURE_VI_SETOPTS
+static void setops(const Byte *args, const char *opname, int flg_no,
+ const char *short_opname, int opt)
+{
+ const char *a = (char *) args + flg_no;
+ int l = strlen(opname) - 1; /* opname have + ' ' */
+
+ if (strncasecmp(a, opname, l) == 0 ||
+ strncasecmp(a, short_opname, 2) == 0) {
+ if(flg_no)
+ vi_setops &= ~opt;
+ else
+ vi_setops |= opt;
+ }
+}
+#endif
+
static void colon(Byte * buf)
{
Byte c, *orig_buf, *buf1, *q, *r;
@@ -1065,19 +882,27 @@ static void colon(Byte * buf)
}
place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen
clear_to_eol(); // clear the line
- write(1, "\r\n", 2);
+ puts("\r");
for (; q <= r; q++) {
+ int c_is_no_print;
+
c = *q;
- if (c > '~')
+ c_is_no_print = c > 127 && !Isprint(c);
+ if (c_is_no_print) {
+ c = '.';
standout_start();
+ }
if (c == '\n') {
- write(1, "$\r", 2);
- } else if (*q < ' ') {
- write(1, "^", 1);
+ write1("$\r");
+ } else if (c < ' ' || c == 127) {
+ putchar('^');
+ if(c == 127)
+ c = '?';
+ else
c += '@';
}
- write(1, &c, 1);
- if (c > '~')
+ putchar(c);
+ if (c_is_no_print)
standout_end();
}
#ifdef CONFIG_FEATURE_VI_SET
@@ -1185,23 +1010,11 @@ static void colon(Byte * buf)
if (strncasecmp((char *) args, "no", 2) == 0)
i = 2; // ":set noautoindent"
#ifdef CONFIG_FEATURE_VI_SETOPTS
- if (strncasecmp((char *) args + i, "autoindent", 10) == 0 ||
- strncasecmp((char *) args + i, "ai", 2) == 0) {
- autoindent = (i == 2) ? 0 : 1;
- }
- if (strncasecmp((char *) args + i, "flash", 5) == 0 ||
- strncasecmp((char *) args + i, "fl", 2) == 0) {
- err_method = (i == 2) ? 0 : 1;
- }
- if (strncasecmp((char *) args + i, "ignorecase", 10) == 0 ||
- strncasecmp((char *) args + i, "ic", 2) == 0) {
- ignorecase = (i == 2) ? 0 : 1;
- }
- if (strncasecmp((char *) args + i, "showmatch", 9) == 0 ||
- strncasecmp((char *) args + i, "sm", 2) == 0) {
- showmatch = (i == 2) ? 0 : 1;
- }
- if (strncasecmp((char *) args + i, "tabstop", 7) == 0) {
+ setops(args, "autoindent ", i, "ai", VI_AUTOINDENT);
+ setops(args, "flash ", i, "fl", VI_ERR_METHOD);
+ setops(args, "ignorecase ", i, "ic", VI_IGNORECASE);
+ setops(args, "showmatch ", i, "ic", VI_SHOWMATCH);
+ if (strncasecmp((char *) args + i, "tabstop=%d ", 7) == 0) {
sscanf(strchr((char *) args + i, '='), "=%d", &ch);
if (ch > 0 && ch < columns - 1)
tabstop = ch;
@@ -1318,9 +1131,7 @@ static void colon(Byte * buf)
#ifdef CONFIG_FEATURE_VI_SEARCH
colon_s_fail:
psb(":s expression missing delimiters");
- return;
#endif
-
}
static void Hit_Return(void)
@@ -1328,7 +1139,7 @@ static void Hit_Return(void)
char c;
standout_start(); // start reverse video
- write(1, "[Hit return to continue]", 24);
+ write1("[Hit return to continue]");
standout_end(); // end reverse video
while ((c = get_one_char()) != '\n' && c != '\r') /*do nothing */
;
@@ -1392,7 +1203,7 @@ static void sync_cursor(Byte * d, int *row, int *col)
if (*tp == '\t') {
// 7 - (co % 8 )
co += ((tabstop - 1) - (co % tabstop));
- } else if (*tp < ' ') {
+ } else if (*tp < ' ' || *tp == 127) {
co++; // display as ^X, use 2 columns
}
} while (tp++ < d && ++co);
@@ -1442,7 +1253,7 @@ static Byte *end_line(Byte * p) // return pointer to NL of cur line line
return (p);
}
-extern inline Byte *dollar_line(Byte * p) // return pointer to just before NL line
+static inline Byte *dollar_line(Byte * p) // return pointer to just before NL line
{
while (p < end - 1 && *p != '\n')
p++; // go to cur line E-o-l
@@ -1547,7 +1358,7 @@ static Byte *move_to_col(Byte * p, int l)
if (*p == '\t') {
// 7 - (co % 8 )
co += ((tabstop - 1) - (co % tabstop));
- } else if (*p < ' ') {
+ } else if (*p < ' ' || *p == 127) {
co++; // display as ^X, use 2 columns
}
} while (++co <= l && p++ < end);
@@ -1787,7 +1598,7 @@ static Byte *char_insert(Byte * p, Byte c) // insert the char c at 'p'
p = text_hole_delete(p, p); // shrink buffer 1 char
#ifdef CONFIG_FEATURE_VI_DOT_CMD
// also rmove char from last_modifying_cmd
- if (strlen((char *) last_modifying_cmd) > 0) {
+ if (last_modifying_cmd != 0 && strlen((char *) last_modifying_cmd) > 0) {
Byte *q;
q = last_modifying_cmd;
@@ -2130,7 +1941,7 @@ static void show_help(void)
);
}
-extern inline void print_literal(Byte * buf, Byte * s) // copy s to buf, convert unprintable
+static inline void print_literal(Byte * buf, Byte * s) // copy s to buf, convert unprintable
{
Byte c, b[2];
@@ -2139,19 +1950,25 @@ extern inline void print_literal(Byte * buf, Byte * s) // copy s to buf, convert
if (strlen((char *) s) <= 0)
s = (Byte *) "(NULL)";
for (; *s > '\0'; s++) {
+ int c_is_no_print;
+
c = *s;
- if (*s > '~') {
- strcat((char *) buf, SOs);
- c = *s - 128;
+ c_is_no_print = c > 127 && !Isprint(c);
+ if (c_is_no_print) {
+ strcat((char *) buf, SOn);
+ c = '.';
}
- if (*s < ' ') {
+ if (c < ' ' || c == 127) {
strcat((char *) buf, "^");
+ if(c == 127)
+ c = '?';
+ else
c += '@';
}
b[0] = c;
strcat((char *) buf, (char *) b);
- if (*s > '~')
- strcat((char *) buf, SOn);
+ if (c_is_no_print)
+ strcat((char *) buf, SOs);
if (*s == '\n') {
strcat((char *) buf, "$");
}
@@ -2259,7 +2076,7 @@ static void check_context(Byte cmd)
return;
}
-extern inline Byte *swap_context(Byte * p) // goto new context for '' command make this the current context
+static inline Byte *swap_context(Byte * p) // goto new context for '' command make this the current context
{
Byte *tmp;
@@ -2301,6 +2118,7 @@ static void rawmode(void)
static void cookmode(void)
{
+ fflush(stdout);
tcsetattr(0, TCSANOW, &term_orig);
}
@@ -2348,7 +2166,7 @@ static void cont_sig(int sig)
signal(SIGTSTP, suspend_sig);
signal(SIGCONT, SIG_DFL);
- kill(getpid(), SIGCONT);
+ kill(my_pid, SIGCONT);
}
//----- Come here when we get a Suspend signal -------------------
@@ -2360,7 +2178,7 @@ static void suspend_sig(int sig)
signal(SIGCONT, cont_sig);
signal(SIGTSTP, SIG_DFL);
- kill(getpid(), SIGTSTP);
+ kill(my_pid, SIGTSTP);
}
//----- Come here when we get a signal ---------------------------
@@ -2369,12 +2187,8 @@ static void catch_sig(int sig)
signal(SIGHUP, catch_sig);
signal(SIGINT, catch_sig);
signal(SIGTERM, catch_sig);
- longjmp(restart, sig);
-}
-
-static void alarm_sig(int sig)
-{
signal(SIGALRM, catch_sig);
+ if(sig)
longjmp(restart, sig);
}
@@ -2393,15 +2207,18 @@ static void core_sig(int sig)
signal(SIGSYS, core_sig);
#endif
+ if(sig) { // signaled
dot = bound_dot(dot); // make sure "dot" is valid
longjmp(restart, sig);
+ }
}
#endif /* CONFIG_FEATURE_VI_USE_SIGNALS */
static int mysleep(int hund) // sleep for 'h' 1/100 seconds
{
// Don't hang- Wait 5/100 seconds- 1 Sec= 1000000
+ fflush(stdout);
FD_ZERO(&rfds);
FD_SET(0, &rfds);
tv.tv_sec = 0;
@@ -2410,60 +2227,66 @@ static int mysleep(int hund) // sleep for 'h' 1/100 seconds
return (FD_ISSET(0, &rfds));
}
+static Byte readbuffer[BUFSIZ];
+static int readed_for_parse;
+
//----- IO Routines --------------------------------------------
static Byte readit(void) // read (maybe cursor) key from stdin
{
Byte c;
- int i, bufsiz, cnt, cmdindex;
+ int n;
struct esc_cmds {
- Byte *seq;
+ const char *seq;
Byte val;
};
- static struct esc_cmds esccmds[] = {
- {(Byte *) "OA", (Byte) VI_K_UP}, // cursor key Up
- {(Byte *) "OB", (Byte) VI_K_DOWN}, // cursor key Down
- {(Byte *) "OC", (Byte) VI_K_RIGHT}, // Cursor Key Right
- {(Byte *) "OD", (Byte) VI_K_LEFT}, // cursor key Left
- {(Byte *) "OH", (Byte) VI_K_HOME}, // Cursor Key Home
- {(Byte *) "OF", (Byte) VI_K_END}, // Cursor Key End
- {(Byte *) "", (Byte) VI_K_UP}, // cursor key Up
- {(Byte *) "", (Byte) VI_K_DOWN}, // cursor key Down
- {(Byte *) "", (Byte) VI_K_RIGHT}, // Cursor Key Right
- {(Byte *) "", (Byte) VI_K_LEFT}, // cursor key Left
- {(Byte *) "", (Byte) VI_K_HOME}, // Cursor Key Home
- {(Byte *) "", (Byte) VI_K_END}, // Cursor Key End
- {(Byte *) "[2~", (Byte) VI_K_INSERT}, // Cursor Key Insert
- {(Byte *) "[5~", (Byte) VI_K_PAGEUP}, // Cursor Key Page Up
- {(Byte *) "[6~", (Byte) VI_K_PAGEDOWN}, // Cursor Key Page Down
- {(Byte *) "OP", (Byte) VI_K_FUN1}, // Function Key F1
- {(Byte *) "OQ", (Byte) VI_K_FUN2}, // Function Key F2
- {(Byte *) "OR", (Byte) VI_K_FUN3}, // Function Key F3
- {(Byte *) "OS", (Byte) VI_K_FUN4}, // Function Key F4
- {(Byte *) "[15~", (Byte) VI_K_FUN5}, // Function Key F5
- {(Byte *) "[17~", (Byte) VI_K_FUN6}, // Function Key F6
- {(Byte *) "[18~", (Byte) VI_K_FUN7}, // Function Key F7
- {(Byte *) "[19~", (Byte) VI_K_FUN8}, // Function Key F8
- {(Byte *) "[20~", (Byte) VI_K_FUN9}, // Function Key F9
- {(Byte *) "[21~", (Byte) VI_K_FUN10}, // Function Key F10
- {(Byte *) "[23~", (Byte) VI_K_FUN11}, // Function Key F11
- {(Byte *) "[24~", (Byte) VI_K_FUN12}, // Function Key F12
- {(Byte *) "[11~", (Byte) VI_K_FUN1}, // Function Key F1
- {(Byte *) "[12~", (Byte) VI_K_FUN2}, // Function Key F2
- {(Byte *) "[13~", (Byte) VI_K_FUN3}, // Function Key F3
- {(Byte *) "[14~", (Byte) VI_K_FUN4}, // Function Key F4
+ static const struct esc_cmds esccmds[] = {
+ {"OA", (Byte) VI_K_UP}, // cursor key Up
+ {"OB", (Byte) VI_K_DOWN}, // cursor key Down
+ {"OC", (Byte) VI_K_RIGHT}, // Cursor Key Right
+ {"OD", (Byte) VI_K_LEFT}, // cursor key Left
+ {"OH", (Byte) VI_K_HOME}, // Cursor Key Home
+ {"OF", (Byte) VI_K_END}, // Cursor Key End
+ {"[A", (Byte) VI_K_UP}, // cursor key Up
+ {"[B", (Byte) VI_K_DOWN}, // cursor key Down
+ {"[C", (Byte) VI_K_RIGHT}, // Cursor Key Right
+ {"[D", (Byte) VI_K_LEFT}, // cursor key Left
+ {"[H", (Byte) VI_K_HOME}, // Cursor Key Home
+ {"[F", (Byte) VI_K_END}, // Cursor Key End
+ {"[1~", (Byte) VI_K_HOME}, // Cursor Key Home
+ {"[2~", (Byte) VI_K_INSERT}, // Cursor Key Insert
+ {"[4~", (Byte) VI_K_END}, // Cursor Key End
+ {"[5~", (Byte) VI_K_PAGEUP}, // Cursor Key Page Up
+ {"[6~", (Byte) VI_K_PAGEDOWN}, // Cursor Key Page Down
+ {"OP", (Byte) VI_K_FUN1}, // Function Key F1
+ {"OQ", (Byte) VI_K_FUN2}, // Function Key F2
+ {"OR", (Byte) VI_K_FUN3}, // Function Key F3
+ {"OS", (Byte) VI_K_FUN4}, // Function Key F4
+ {"[15~", (Byte) VI_K_FUN5}, // Function Key F5
+ {"[17~", (Byte) VI_K_FUN6}, // Function Key F6
+ {"[18~", (Byte) VI_K_FUN7}, // Function Key F7
+ {"[19~", (Byte) VI_K_FUN8}, // Function Key F8
+ {"[20~", (Byte) VI_K_FUN9}, // Function Key F9
+ {"[21~", (Byte) VI_K_FUN10}, // Function Key F10
+ {"[23~", (Byte) VI_K_FUN11}, // Function Key F11
+ {"[24~", (Byte) VI_K_FUN12}, // Function Key F12
+ {"[11~", (Byte) VI_K_FUN1}, // Function Key F1
+ {"[12~", (Byte) VI_K_FUN2}, // Function Key F2
+ {"[13~", (Byte) VI_K_FUN3}, // Function Key F3
+ {"[14~", (Byte) VI_K_FUN4}, // Function Key F4
};
#define ESCCMDS_COUNT (sizeof(esccmds)/sizeof(struct esc_cmds))
(void) alarm(0); // turn alarm OFF while we wait for input
+ fflush(stdout);
+ n = readed_for_parse;
// get input from User- are there already input chars in Q?
- bufsiz = strlen((char *) readbuffer);
- if (bufsiz <= 0) {
+ if (n <= 0) {
ri0:
// the Q is empty, wait for a typed char
- bufsiz = read(0, readbuffer, BUFSIZ - 1);
- if (bufsiz < 0) {
+ n = read(0, readbuffer, BUFSIZ - 1);
+ if (n < 0) {
if (errno == EINTR)
goto ri0; // interrupted sys call
if (errno == EBADF)
@@ -2475,14 +2298,10 @@ static Byte readit(void) // read (maybe cursor) key from stdin
if (errno == EIO)
editing = 0;
errno = 0;
- bufsiz = 0;
}
- readbuffer[bufsiz] = '\0';
- }
- // return char if it is not part of ESC sequence
- if (readbuffer[0] != 27)
- goto ri1;
-
+ if(n <= 0)
+ return 0; // error
+ if (readbuffer[0] == 27) {
// This is an ESC char. Is this Esc sequence?
// Could be bare Esc key. See if there are any
// more chars to read after the ESC. This would
@@ -2493,34 +2312,44 @@ static Byte readit(void) // read (maybe cursor) key from stdin
tv.tv_usec = 50000; // Wait 5/100 seconds- 1 Sec=1000000
// keep reading while there are input chars and room in buffer
- while (select(1, &rfds, NULL, NULL, &tv) > 0 && bufsiz <= (BUFSIZ - 5)) {
+ while (select(1, &rfds, NULL, NULL, &tv) > 0 && n <= (BUFSIZ - 5)) {
// read the rest of the ESC string
- i = read(0, (void *) (readbuffer + bufsiz), BUFSIZ - bufsiz);
- if (i > 0) {
- bufsiz += i;
- readbuffer[bufsiz] = '\0'; // Terminate the string
+ int r = read(0, (void *) (readbuffer + n), BUFSIZ - n);
+ if (r > 0) {
+ n += r;
+ }
+ }
}
+ readed_for_parse = n;
}
+ c = readbuffer[0];
+ if(c == 27 && n > 1) {
// Maybe cursor or function key?
- for (cmdindex = 0; cmdindex < ESCCMDS_COUNT; cmdindex++) {
- cnt = strlen((char *) esccmds[cmdindex].seq);
- i = strncmp((char *) esccmds[cmdindex].seq, (char *) readbuffer, cnt);
- if (i == 0) {
+ const struct esc_cmds *eindex;
+
+ for (eindex = esccmds; eindex < &esccmds[ESCCMDS_COUNT]; eindex++) {
+ int cnt = strlen(eindex->seq);
+
+ if(n <= cnt)
+ continue;
+ if(strncmp(eindex->seq, (char *) readbuffer + 1, cnt))
+ continue;
// is a Cursor key- put derived value back into Q
- readbuffer[0] = esccmds[cmdindex].val;
- // squeeze out the ESC sequence
- for (i = 1; i < cnt; i++) {
- memmove(readbuffer + 1, readbuffer + 2, BUFSIZ - 2);
- readbuffer[BUFSIZ - 1] = '\0';
- }
+ c = eindex->val;
+ // for squeeze out the ESC sequence
+ n = cnt + 1;
break;
}
+ if(eindex == &esccmds[ESCCMDS_COUNT]) {
+ /* defined ESC sequence not found, set only one ESC */
+ n = 1;
}
- ri1:
- c = readbuffer[0];
- // remove one char from Q
- memmove(readbuffer, readbuffer + 1, BUFSIZ - 1);
- readbuffer[BUFSIZ - 1] = '\0';
+ } else {
+ n = 1;
+ }
+ // remove key sequence from Q
+ readed_for_parse -= n;
+ memmove(readbuffer, readbuffer + n, BUFSIZ - n);
(void) alarm(3); // we are done waiting for input, turn alarm ON
return (c);
}
@@ -2561,7 +2390,6 @@ static Byte get_one_char()
// add new char to q
last_modifying_cmd[len] = c;
}
-
}
}
#else /* CONFIG_FEATURE_VI_DOT_CMD */
@@ -2581,7 +2409,7 @@ static Byte *get_input_line(Byte * prompt) // get input line- use "status line"
*status_buffer = '\0'; // clear the status buffer
place_cursor(rows - 1, 0, FALSE); // go to Status line, bottom of screen
clear_to_eol(); // clear the line
- write(1, prompt, strlen((char *) prompt)); // write out the :, /, or ? prompt
+ write1(prompt); // write out the :, /, or ? prompt
for (i = strlen((char *) buf); i < BUFSIZ;) {
c = get_one_char(); // read user input
@@ -2591,14 +2419,14 @@ static Byte *get_input_line(Byte * prompt) // get input line- use "status line"
i--; // backup to prev char
buf[i] = '\0'; // erase the char
buf[i + 1] = '\0'; // null terminate buffer
- write(1, " ", 3); // erase char on screen
+ write1("\b \b"); // erase char on screen
if (i <= 0) { // user backs up before b-o-l, exit
break;
}
} else {
buf[i] = c; // save char in buffer
buf[i + 1] = '\0'; // make sure buffer is null terminated
- write(1, buf + i, 1); // echo the char back to user
+ putchar(c); // echo the char back to user
i++;
}
}
@@ -2608,7 +2436,7 @@ static Byte *get_input_line(Byte * prompt) // get input line- use "status line"
return (obufp);
}
-static int file_size(Byte * fn) // what is the byte size of "fn"
+static int file_size(const Byte * fn) // what is the byte size of "fn"
{
struct stat st_buf;
int cnt, sr;
@@ -2729,7 +2557,6 @@ static void place_cursor(int row, int col, int opti)
{
char cm1[BUFSIZ];
char *cm;
- int l;
#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
char cm2[BUFSIZ];
Byte *screenp;
@@ -2784,32 +2611,31 @@ static void place_cursor(int row, int col, int opti)
} */
#endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
pc0:
- l= strlen(cm);
- if (l) write(1, cm, l); // move the cursor
+ write1(cm); // move the cursor
}
//----- Erase from cursor to end of line -----------------------
static void clear_to_eol()
{
- write(1, Ceol, strlen(Ceol)); // Erase from cursor to end of line
+ write1(Ceol); // Erase from cursor to end of line
}
//----- Erase from cursor to end of screen -----------------------
static void clear_to_eos()
{
- write(1, Ceos, strlen(Ceos)); // Erase from cursor to end of screen
+ write1(Ceos); // Erase from cursor to end of screen
}
//----- Start standout mode ------------------------------------
static void standout_start() // send "start reverse video" sequence
{
- write(1, SOs, strlen(SOs)); // Start reverse video mode
+ write1(SOs); // Start reverse video mode
}
//----- End standout mode --------------------------------------
static void standout_end() // send "end reverse video" sequence
{
- write(1, SOn, strlen(SOn)); // End reverse video mode
+ write1(SOn); // End reverse video mode
}
//----- Flash the screen --------------------------------------
@@ -2822,19 +2648,14 @@ static void flash(int h)
redraw(TRUE);
}
-static void beep()
-{
- write(1, bell, strlen(bell)); // send out a bell character
-}
-
-static void indicate_error(char c)
+static void Indicate_Error(void)
{
#ifdef CONFIG_FEATURE_VI_CRASHME
if (crashme > 0)
return; // generate a random command
#endif /* CONFIG_FEATURE_VI_CRASHME */
- if (err_method == 0) {
- beep();
+ if (!err_method) {
+ write1(bell); // send out a bell character
} else {
flash(10);
}
@@ -2859,7 +2680,7 @@ static void show_status_line(void)
if (cnt > 0 && last_cksum != cksum) {
last_cksum= cksum; // remember if we have seen this line
place_cursor(rows - 1, 0, FALSE); // put cursor on status line
- write(1, status_buffer, cnt);
+ write1(status_buffer);
clear_to_eol();
place_cursor(crow, ccol, FALSE); // put cursor back in correct place
}
@@ -2867,7 +2688,7 @@ static void show_status_line(void)
//----- format the status buffer, the bottom line of screen ------
// print status buffer, with STANDOUT mode
-static void psbs(char *format, ...)
+static void psbs(const char *format, ...)
{
va_list args;
@@ -2882,7 +2703,7 @@ static void psbs(char *format, ...)
}
// print status buffer
-static void psb(char *format, ...)
+static void psb(const char *format, ...)
{
va_list args;
@@ -2954,7 +2775,10 @@ static void format_line(Byte *dest, Byte *src, int li)
}
if (c == '\n')
break;
- if (c < ' ' || c > '~') {
+ if (c > 127 && !Isprint(c)) {
+ c = '.';
+ }
+ if (c < ' ' || c == 127) {
if (c == '\t') {
c = ' ';
// co % 8 != 7
@@ -2963,8 +2787,10 @@ static void format_line(Byte *dest, Byte *src, int li)
}
} else {
dest[co++] = '^';
- c |= '@'; // make it visible
- c &= 0x7f; // get rid of hi bit
+ if(c == 127)
+ c = '?';
+ else
+ c += '@'; // make it visible
}
}
// the co++ is done here so that the column will
@@ -3067,7 +2893,15 @@ static void refresh(int full_screen)
}
// write line out to terminal
- write(1, sp+cs, ce-cs+1);
+ {
+ int nic = ce-cs+1;
+ char *out = sp+cs;
+
+ while(nic-- > 0) {
+ putchar(*out);
+ out++;
+ }
+ }
#ifdef CONFIG_FEATURE_VI_OPTIMIZE_CURSOR
last_row = li;
#endif /* CONFIG_FEATURE_VI_OPTIMIZE_CURSOR */
@@ -3131,12 +2965,14 @@ static void do_cmd(Byte c)
}
if (cmd_mode == 2) {
+ // flip-flop Insert/Replace mode
+ if (c == VI_K_INSERT) goto dc_i;
// we are 'R'eplacing the current *dot with new char
if (*dot == '\n') {
// don't Replace past E-o-l
cmd_mode = 1; // convert to insert
} else {
- if (1 <= c && c <= 127) { // only ASCII chars
+ if (1 <= c || Isprint(c)) {
if (c != 27)
dot = yank_delete(dot, dot, 0, YANKDEL); // delete char
dot = char_insert(dot, c); // insert new char
@@ -3148,8 +2984,8 @@ static void do_cmd(Byte c)
// hitting "Insert" twice means "R" replace mode
if (c == VI_K_INSERT) goto dc5;
// insert the char c at "dot"
- if (1 <= c && c <= 127) {
- dot = char_insert(dot, c); // only ASCII chars
+ if (1 <= c || Isprint(c)) {
+ dot = char_insert(dot, c);
}
goto dc1;
}
@@ -3202,7 +3038,7 @@ key_cmd_mode:
default: // unrecognised command
buf[0] = c;
buf[1] = '\0';
- if (c <= ' ') {
+ if (c < ' ') {
buf[0] = '^';
buf[1] = c + '@';
buf[2] = '\0';
@@ -3953,3 +3789,208 @@ key_cmd_mode:
if (*dot == '\n' && cnt > 0 && cmd_mode == 0)
dot--;
}
+
+#ifdef CONFIG_FEATURE_VI_CRASHME
+static int totalcmds = 0;
+static int Mp = 85; // Movement command Probability
+static int Np = 90; // Non-movement command Probability
+static int Dp = 96; // Delete command Probability
+static int Ip = 97; // Insert command Probability
+static int Yp = 98; // Yank command Probability
+static int Pp = 99; // Put command Probability
+static int M = 0, N = 0, I = 0, D = 0, Y = 0, P = 0, U = 0;
+char chars[20] = "\t012345 abcdABCD-=.$";
+char *words[20] = { "this", "is", "a", "test",
+ "broadcast", "the", "emergency", "of",
+ "system", "quick", "brown", "fox",
+ "jumped", "over", "lazy", "dogs",
+ "back", "January", "Febuary", "March"
+};
+char *lines[20] = {
+ "You should have received a copy of the GNU General Public License\n",
+ "char c, cm, *cmd, *cmd1;\n",
+ "generate a command by percentages\n",
+ "Numbers may be typed as a prefix to some commands.\n",
+ "Quit, discarding changes!\n",
+ "Forced write, if permission originally not valid.\n",
+ "In general, any ex or ed command (such as substitute or delete).\n",
+ "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n",
+ "Please get w/ me and I will go over it with you.\n",
+ "The following is a list of scheduled, committed changes.\n",
+ "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n",
+ "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n",
+ "Any question about transactions please contact Sterling Huxley.\n",
+ "I will try to get back to you by Friday, December 31.\n",
+ "This Change will be implemented on Friday.\n",
+ "Let me know if you have problems accessing this;\n",
+ "Sterling Huxley recently added you to the access list.\n",
+ "Would you like to go to lunch?\n",
+ "The last command will be automatically run.\n",
+ "This is too much english for a computer geek.\n",
+};
+char *multilines[20] = {
+ "You should have received a copy of the GNU General Public License\n",
+ "char c, cm, *cmd, *cmd1;\n",
+ "generate a command by percentages\n",
+ "Numbers may be typed as a prefix to some commands.\n",
+ "Quit, discarding changes!\n",
+ "Forced write, if permission originally not valid.\n",
+ "In general, any ex or ed command (such as substitute or delete).\n",
+ "I have tickets available for the Blazers vs LA Clippers for Monday, Janurary 1 at 1:00pm.\n",
+ "Please get w/ me and I will go over it with you.\n",
+ "The following is a list of scheduled, committed changes.\n",
+ "1. Launch Norton Antivirus (Start, Programs, Norton Antivirus)\n",
+ "Reminder....Town Meeting in Central Perk cafe today at 3:00pm.\n",
+ "Any question about transactions please contact Sterling Huxley.\n",
+ "I will try to get back to you by Friday, December 31.\n",
+ "This Change will be implemented on Friday.\n",
+ "Let me know if you have problems accessing this;\n",
+ "Sterling Huxley recently added you to the access list.\n",
+ "Would you like to go to lunch?\n",
+ "The last command will be automatically run.\n",
+ "This is too much english for a computer geek.\n",
+};
+
+// create a random command to execute
+static void crash_dummy()
+{
+ static int sleeptime; // how long to pause between commands
+ char c, cm, *cmd, *cmd1;
+ int i, cnt, thing, rbi, startrbi, percent;
+
+ // "dot" movement commands
+ cmd1 = " \n\r\002\004\005\006\025\0310^$-+wWeEbBhjklHL";
+
+ // is there already a command running?
+ if (readed_for_parse > 0)
+ goto cd1;
+ cd0:
+ startrbi = rbi = 0;
+ sleeptime = 0; // how long to pause between commands
+ memset(readbuffer, '\0', BUFSIZ); // clear the read buffer
+ // generate a command by percentages
+ percent = (int) lrand48() % 100; // get a number from 0-99
+ if (percent < Mp) { // Movement commands
+ // available commands
+ cmd = cmd1;
+ M++;
+ } else if (percent < Np) { // non-movement commands
+ cmd = "mz<>\'\""; // available commands
+ N++;
+ } else if (percent < Dp) { // Delete commands
+ cmd = "dx"; // available commands
+ D++;
+ } else if (percent < Ip) { // Inset commands
+ cmd = "iIaAsrJ"; // available commands
+ I++;
+ } else if (percent < Yp) { // Yank commands
+ cmd = "yY"; // available commands
+ Y++;
+ } else if (percent < Pp) { // Put commands
+ cmd = "pP"; // available commands
+ P++;
+ } else {
+ // We do not know how to handle this command, try again
+ U++;
+ goto cd0;
+ }
+ // randomly pick one of the available cmds from "cmd[]"
+ i = (int) lrand48() % strlen(cmd);
+ cm = cmd[i];
+ if (strchr(":\024", cm))
+ goto cd0; // dont allow colon or ctrl-T commands
+ readbuffer[rbi++] = cm; // put cmd into input buffer
+
+ // now we have the command-
+ // there are 1, 2, and multi char commands
+ // find out which and generate the rest of command as necessary
+ if (strchr("dmryz<>\'\"", cm)) { // 2-char commands
+ cmd1 = " \n\r0$^-+wWeEbBhjklHL";
+ if (cm == 'm' || cm == '\'' || cm == '\"') { // pick a reg[]
+ cmd1 = "abcdefghijklmnopqrstuvwxyz";
+ }
+ thing = (int) lrand48() % strlen(cmd1); // pick a movement command
+ c = cmd1[thing];
+ readbuffer[rbi++] = c; // add movement to input buffer
+ }
+ if (strchr("iIaAsc", cm)) { // multi-char commands
+ if (cm == 'c') {
+ // change some thing
+ thing = (int) lrand48() % strlen(cmd1); // pick a movement command
+ c = cmd1[thing];
+ readbuffer[rbi++] = c; // add movement to input buffer
+ }
+ thing = (int) lrand48() % 4; // what thing to insert
+ cnt = (int) lrand48() % 10; // how many to insert
+ for (i = 0; i < cnt; i++) {
+ if (thing == 0) { // insert chars
+ readbuffer[rbi++] = chars[((int) lrand48() % strlen(chars))];
+ } else if (thing == 1) { // insert words
+ strcat((char *) readbuffer, words[(int) lrand48() % 20]);
+ strcat((char *) readbuffer, " ");
+ sleeptime = 0; // how fast to type
+ } else if (thing == 2) { // insert lines
+ strcat((char *) readbuffer, lines[(int) lrand48() % 20]);
+ sleeptime = 0; // how fast to type
+ } else { // insert multi-lines
+ strcat((char *) readbuffer, multilines[(int) lrand48() % 20]);
+ sleeptime = 0; // how fast to type
+ }
+ }
+ strcat((char *) readbuffer, "\033");
+ }
+ readed_for_parse = strlen(readbuffer);
+ cd1:
+ totalcmds++;
+ if (sleeptime > 0)
+ (void) mysleep(sleeptime); // sleep 1/100 sec
+}
+
+// test to see if there are any errors
+static void crash_test()
+{
+ static time_t oldtim;
+ time_t tim;
+ char d[2], buf[BUFSIZ], msg[BUFSIZ];
+
+ msg[0] = '\0';
+ if (end < text) {
+ strcat((char *) msg, "end<text ");
+ }
+ if (end > textend) {
+ strcat((char *) msg, "end>textend ");
+ }
+ if (dot < text) {
+ strcat((char *) msg, "dot<text ");
+ }
+ if (dot > end) {
+ strcat((char *) msg, "dot>end ");
+ }
+ if (screenbegin < text) {
+ strcat((char *) msg, "screenbegin<text ");
+ }
+ if (screenbegin > end - 1) {
+ strcat((char *) msg, "screenbegin>end-1 ");
+ }
+
+ if (strlen(msg) > 0) {
+ alarm(0);
+ printf(buf, "\n\n%d: \'%c\' %s\n\n\n%s[Hit return to continue]%s",
+ totalcmds, last_input_char, msg, SOs, SOn);
+ fflush(stdout);
+ while (read(0, d, 1) > 0) {
+ if (d[0] == '\n' || d[0] == '\r')
+ break;
+ }
+ alarm(3);
+ }
+ tim = (time_t) time((time_t *) 0);
+ if (tim >= (oldtim + 3)) {
+ sprintf((char *) status_buffer,
+ "Tot=%d: M=%d N=%d I=%d D=%d Y=%d P=%d U=%d size=%d",
+ totalcmds, M, N, I, D, Y, P, U, end - text + 1);
+ oldtim = tim;
+ }
+ return;
+}
+#endif /* CONFIG_FEATURE_VI_CRASHME */