From: Joshua Kwan Date: Wed, 31 Dec 2003 19:47:49 +0000 (+0000) Subject: I can't stand it anymore, reindenting with 2 spaces, X-Git-Tag: v1.6.1-roc-dev~674 X-Git-Url: https://skyeroc.xyz/gitweb/?a=commitdiff_plain;h=8b0af2e9aa758d22769954d8a084d7fefc3e93d0;p=dgamelaunch I can't stand it anymore, reindenting with 2 spaces, also add a dgl-banner file that has a $VERSION token that one can put anywhere, replace VER[1-7] and VERLINES git-svn-id: svn://katsu.triplehelix.org/dgamelaunch/trunk@24 db0b04b0-f4d1-0310-9a6d-de3e77497b0e --- diff --git a/Makefile b/Makefile index e651fef..0e67661 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ clean: install: cp dgamelaunch /usr/sbin indent: - indent -ts2 *.c *.h + indent -nut -ts2 *.c *.h rm *~ dist: clean indent diff --git a/dgamelaunch.c b/dgamelaunch.c index ee26229..752b086 100644 --- a/dgamelaunch.c +++ b/dgamelaunch.c @@ -37,31 +37,22 @@ * even keep the line the same altogether. I'm probably happy * to make any changes you need. */ -#define VERLINES 7 /* number of lines in this vanity text */ -#define VER1 "## dgamelaunch - network console game launcher\n" -#define VER2 "## version " VERSION "\n" -#define VER3 "## \n" -#define VER4 "## (c)2001-3 M. Drew Streib. This program's source is released under the GPL.\n" -#define VER5 "## Send mail to for details or a copy of the source code.\n" -#define VER6 "## ** Games on this server are recorded for in-progress viewing and playback!\n" -#define VER7 "## Server info is at http://alt.org/nethack/" - /* ************************************************************* */ /* ************************************************************* */ /* ************************************************************* */ /* program stuff */ -#define _XOPEN_SOURCE /* grantpt, etc. */ -#define _BSD_SOURCE /* setenv */ +#define _XOPEN_SOURCE /* grantpt, etc. */ +#define _BSD_SOURCE /* setenv */ #include #include #include #include -#include /* for flock() */ +#include /* for flock() */ #include -#include /* ttyrec */ +#include /* ttyrec */ #include #include #include @@ -101,6 +92,7 @@ char *chosen_name; int f_num = 0; struct dg_user **users = NULL; struct dg_user *me = NULL; +struct dg_banner banner; /* ************************************************************* */ /* for ttyrec */ @@ -108,12 +100,12 @@ struct dg_user *me = NULL; void ttyrec_getmaster () { - (void) tcgetattr (0, &tt); - (void) ioctl (0, TIOCGWINSZ, (char *) &win); - if ((master = open ("/dev/ptmx", O_RDWR)) < 0) - { - exit (62); - } + (void) tcgetattr (0, &tt); + (void) ioctl (0, TIOCGWINSZ, (char *) &win); + if ((master = open ("/dev/ptmx", O_RDWR)) < 0) + { + exit (62); + } } /* ************************************************************* */ @@ -121,15 +113,15 @@ ttyrec_getmaster () void gen_ttyrec_filename () { - time_t rawtime; - struct tm *ptm; - - /* append time to filename */ - time (&rawtime); - ptm = gmtime (&rawtime); - snprintf (ttyrec_filename, 100, "%04i-%02i-%02i.%02i:%02i:%02i.ttyrec", - ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, - ptm->tm_hour, ptm->tm_min, ptm->tm_sec); + time_t rawtime; + struct tm *ptm; + + /* append time to filename */ + time (&rawtime); + ptm = gmtime (&rawtime); + snprintf (ttyrec_filename, 100, "%04i-%02i-%02i.%02i:%02i:%02i.ttyrec", + ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday, + ptm->tm_hour, ptm->tm_min, ptm->tm_sec); } /* ************************************************************* */ @@ -137,15 +129,15 @@ gen_ttyrec_filename () void gen_inprogress_lock () { - char lockfile[130]; - int fd; + char lockfile[130]; + int fd; - snprintf (lockfile, 130, "%s%s:%s", LOC_INPROGRESSDIR, - me->username, ttyrec_filename); + snprintf (lockfile, 130, "%s%s:%s", LOC_INPROGRESSDIR, + me->username, ttyrec_filename); - fd = open (lockfile, O_WRONLY | O_CREAT, 0644); - if (flock (fd, LOCK_EX)) - exit (68); + fd = open (lockfile, O_WRONLY | O_CREAT, 0644); + if (flock (fd, LOCK_EX)) + exit (68); } /* ************************************************************* */ @@ -153,127 +145,210 @@ gen_inprogress_lock () void catch_sighup () { - caught_sighup = 1; - if (pid_game) - { - sleep (10); - kill (pid_game, SIGHUP); - sleep (5); - } - exit (2); + caught_sighup = 1; + if (pid_game) + { + sleep (10); + kill (pid_game, SIGHUP); + sleep (5); + } + exit (2); } /* ************************************************************* */ +void +loadbanner (struct dg_banner *ban) +{ + FILE *banfile; + char buf[80]; + + memset (buf, 0, 80); + + banfile = fopen ("/dgl-banner", "r"); + + if (!banfile) + { + ban->len = 2; + ban->lines = malloc (sizeof (char *)); + ban->lines[0] = + strdup ("### dgamelaunch " VERSION + " - network console game launcher"); + ban->lines[1] = + strdup + ("### NOTE: administrator has not installed a /dgl-banner file"); + return; + } + + ban->len = 0; + + while (fgets (buf, 80, banfile) != NULL) + { + char *loc; + + ban->len++; + ban->lines = realloc (ban->lines, sizeof (char *) * ban->len); + + if ((loc = strstr (buf, "$VERSION")) != NULL) + { + char bufnew[80]; + char *b = buf; + int i; + + memset (bufnew, 0, 80); + + for (i = 0; i < 80; i++) + { + if (loc != b) + bufnew[i] = *(b++); + else + { + strncat (bufnew, VERSION, 80 - i); + b += 8; /* skip the whole $VERSION string */ + i += sizeof (VERSION) / sizeof (VERSION[0]); + } + + if (strlen (b) == 0) + break; + } + + ban->lines[ban->len - 1] = strdup (bufnew); + } + else + ban->lines[ban->len - 1] = strdup (buf); + + memset (buf, 0, 80); + } +} + +void +drawbanner (unsigned int start_line, unsigned int howmany) +{ + static short loaded_banner = 0; + unsigned int i; + + if (!loaded_banner) + { + loadbanner (&banner); + loaded_banner = 1; + } + + if (howmany > banner.len || howmany == 0) + howmany = banner.len; + + for (i = 0; i < howmany; i++) + mvaddstr (start_line + i, 1, banner.lines[i]); +} + void inprogressmenu () { - int i; - DIR *pdir; - struct dirent *pdirent; - int fd; - struct stat pstat; - char fullname[130]; - char ttyrecname[130]; - char *replacestr; - char *games[15]; - char m_name[26], m_date[11], m_time[9]; - int m_namelen; - time_t ctime; - int menuchoice; - - - do - { - clear (); - mvaddstr (1, 1, VER1); - mvprintw (3, 1, - "During playback, hit 'q' to return here%s.", - loggedin ? ", 'm' to contact the player" : ""); - mvaddstr (4, 1, - "(Use capital letter of selection to strip DEC graphics, VERY experimental!)"); - mvaddstr (5, 1, "The following games are in progress:"); - - /* clean old games and list good ones */ - i = 0; - pdir = opendir (LOC_INPROGRESSDIR); - if (!pdir) - exit (140); - - while ((pdirent = readdir (pdir)) && (i <= 14)) - { - snprintf (fullname, 130, "%s%s", LOC_INPROGRESSDIR, - pdirent->d_name); - - fd = 0; - fd = open (fullname, O_RDONLY); - if ((fd > 0) && flock (fd, LOCK_EX | LOCK_NB)) - { - - /* stat to check idle status */ - snprintf (ttyrecname, 130, "%s%s", LOC_TTYRECDIR, - pdirent->d_name); - replacestr = strstr (ttyrecname, ":"); - if (!replacestr) - exit (145); - replacestr[0] = '/'; - if (!stat (ttyrecname, &pstat)) - { - games[i] = pdirent->d_name; - - memset (m_name, 0, 26); - memset (m_date, 0, 11); - memset (m_time, 0, 9); - m_namelen = - replacestr - ttyrecname - strlen (LOC_TTYRECDIR); - strncpy (m_name, pdirent->d_name, m_namelen); - strncpy (m_date, replacestr + 1, 10); - strncpy (m_time, replacestr + 12, 8); - - mvprintw (7 + i, 1, "%c) %-15s %s %s (%ldm %lds idle)", - i + 97, m_name, m_date, m_time, - (time (&ctime) - pstat.st_mtime) / 60, - (time (&ctime) - pstat.st_mtime) % 60); - i++; - } - } - else - { - unlink (fullname); - } - flock (fd, LOCK_UN | LOCK_NB); - close (fd); - } - - mvaddstr (23, 1, "Watch which game? (r to refresh, q to quit) => "); - refresh (); - - menuchoice = tolower (getch ()); - - if ((menuchoice - 97) >= 0 && (menuchoice - 97) < i) - { - /* valid choice has been made */ - snprintf (ttyrecname, 130, "%s%s", LOC_TTYRECDIR, - games[menuchoice - 97]); - chosen_name = strdup (games[menuchoice - 97]); - if (!(replacestr = strstr (chosen_name, ":"))) - exit (145); - else - *replacestr = '\0'; - replacestr = strstr (ttyrecname, ":"); - if (!replacestr) - exit (145); - replacestr[0] = '/'; - - clear (); - refresh (); - endwin (); - ttyplay_main (ttyrecname, 1, 0); - } - - closedir (pdir); - } - while (menuchoice != 'q'); + int i; + DIR *pdir; + struct dirent *pdirent; + int fd; + struct stat pstat; + char fullname[130]; + char ttyrecname[130]; + char *replacestr; + char *games[15]; + char m_name[26], m_date[11], m_time[9]; + int m_namelen; + time_t ctime; + int menuchoice; + + + do + { + clear (); + drawbanner (1, 1); + mvprintw (3, 1, + "During playback, hit 'q' to return here%s.", + loggedin ? ", 'm' to contact the player" : ""); + mvaddstr (4, 1, + "(Use capital letter of selection to strip DEC graphics, VERY experimental!)"); + mvaddstr (5, 1, "The following games are in progress:"); + + /* clean old games and list good ones */ + i = 0; + pdir = opendir (LOC_INPROGRESSDIR); + if (!pdir) + exit (140); + + while ((pdirent = readdir (pdir)) && (i <= 14)) + { + snprintf (fullname, 130, "%s%s", LOC_INPROGRESSDIR, + pdirent->d_name); + + fd = 0; + fd = open (fullname, O_RDONLY); + if ((fd > 0) && flock (fd, LOCK_EX | LOCK_NB)) + { + + /* stat to check idle status */ + snprintf (ttyrecname, 130, "%s%s", LOC_TTYRECDIR, + pdirent->d_name); + replacestr = strstr (ttyrecname, ":"); + if (!replacestr) + exit (145); + replacestr[0] = '/'; + if (!stat (ttyrecname, &pstat)) + { + games[i] = pdirent->d_name; + + memset (m_name, 0, 26); + memset (m_date, 0, 11); + memset (m_time, 0, 9); + m_namelen = + replacestr - ttyrecname - strlen (LOC_TTYRECDIR); + strncpy (m_name, pdirent->d_name, m_namelen); + strncpy (m_date, replacestr + 1, 10); + strncpy (m_time, replacestr + 12, 8); + + mvprintw (7 + i, 1, "%c) %-15s %s %s (%ldm %lds idle)", + i + 97, m_name, m_date, m_time, + (time (&ctime) - pstat.st_mtime) / 60, + (time (&ctime) - pstat.st_mtime) % 60); + i++; + } + } + else + { + unlink (fullname); + } + flock (fd, LOCK_UN | LOCK_NB); + close (fd); + } + + mvaddstr (23, 1, "Watch which game? (r to refresh, q to quit) => "); + refresh (); + + menuchoice = tolower (getch ()); + + if ((menuchoice - 97) >= 0 && (menuchoice - 97) < i) + { + /* valid choice has been made */ + snprintf (ttyrecname, 130, "%s%s", LOC_TTYRECDIR, + games[menuchoice - 97]); + chosen_name = strdup (games[menuchoice - 97]); + if (!(replacestr = strstr (chosen_name, ":"))) + exit (145); + else + *replacestr = '\0'; + replacestr = strstr (ttyrecname, ":"); + if (!replacestr) + exit (145); + replacestr[0] = '/'; + + clear (); + refresh (); + endwin (); + ttyplay_main (ttyrecname, 1, 0); + } + + closedir (pdir); + } + while (menuchoice != 'q'); } /* ************************************************************* */ @@ -281,61 +356,63 @@ inprogressmenu () void changepw () { - char buf[21]; - int error = 2; - - /* A precondiction is that struct `me' exists because we can be not-yet-logged-in. */ - if (!me) - exit(122); /* Die. */ - - while (error) - { - char repeatbuf[21]; - clear (); - - mvaddstr (1, 1, VER1); - - mvprintw (5, 1, "Please enter a%s password. Remember that this is sent over the net", loggedin ? " new" : ""); - mvaddstr (6, 1, - "in plaintext, so make it something new and expect it to be relatively"); - mvaddstr (7, 1, "insecure."); - mvaddstr (8, 1, - "20 character max. No ':' characters. Blank line to abort."); - mvaddstr (10, 1, "=> "); - - if (error == 1) - { - mvaddstr (15, 1, "Sorry, the passwords don't match. Try again."); - move (10, 4); - } - - refresh (); - - noecho(); - getnstr (buf, 20); - echo(); /* Putting echo back on just for saftey and because it can't hurt. */ - - if (buf && *buf == '\0') - return; - - if (strstr (buf, ":") != NULL) - exit (112); - - mvaddstr (12, 1, "And again:"); - mvaddstr (13, 1, "=> "); - - noecho(); - getnstr (repeatbuf, 20); - echo(); /* Here is the important echo(); if the former is removed. */ - - if (!strcmp (buf, repeatbuf)) - error = 0; - else - error = 1; - } - - me->password = strdup (crypt (buf, buf)); - writefile (0); + char buf[21]; + int error = 2; + + /* A precondiction is that struct `me' exists because we can be not-yet-logged-in. */ + if (!me) + exit (122); /* Die. */ + + while (error) + { + char repeatbuf[21]; + clear (); + + drawbanner (1, 1); + + mvprintw (5, 1, + "Please enter a%s password. Remember that this is sent over the net", + loggedin ? " new" : ""); + mvaddstr (6, 1, + "in plaintext, so make it something new and expect it to be relatively"); + mvaddstr (7, 1, "insecure."); + mvaddstr (8, 1, + "20 character max. No ':' characters. Blank line to abort."); + mvaddstr (10, 1, "=> "); + + if (error == 1) + { + mvaddstr (15, 1, "Sorry, the passwords don't match. Try again."); + move (10, 4); + } + + refresh (); + + noecho (); + getnstr (buf, 20); + echo (); /* Putting echo back on just for saftey and because it can't hurt. */ + + if (buf && *buf == '\0') + return; + + if (strstr (buf, ":") != NULL) + exit (112); + + mvaddstr (12, 1, "And again:"); + mvaddstr (13, 1, "=> "); + + noecho (); + getnstr (repeatbuf, 20); + echo (); /* Here is the important echo(); if the former is removed. */ + + if (!strcmp (buf, repeatbuf)) + error = 0; + else + error = 1; + } + + me->password = strdup (crypt (buf, buf)); + writefile (0); } /* ************************************************************* */ @@ -343,114 +420,108 @@ changepw () void domailuser (char *username) { - unsigned int len, i; - char *spool_fn, message[80]; - FILE *user_spool = NULL; - time_t now; - int mail_empty = 1; - struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, getpid () }; - - assert (loggedin); - - len = - (sizeof (LOC_SPOOLDIR) / sizeof (LOC_SPOOLDIR[0])) + strlen (username) + - 1; - spool_fn = malloc (len + 1); - time (&now); - snprintf (spool_fn, len, "%s/%s", LOC_SPOOLDIR, username); - - /* print the enter your message line */ - clear (); - mvaddstr (1, 1, VER1); - mvaddstr (5, 1, - "Enter your message here. It is to be one line only and 80 characters or less."); - mvaddstr (7, 1, "=> "); - - getnstr (message, 80); - - for (i = 0; i < strlen (message); i++) - { - if (message[i] != ' ' && message[i] != '\n' && message[i] != '\t') - mail_empty = 0; - } - - if (mail_empty) - { - mvaddstr (9, 1, "This scroll appears to be blank.--More--"); - mvaddstr (10, 1, "(Aborting your message.)"); - getch (); - return; - } - - if ((user_spool = fopen (spool_fn, "a")) == NULL) - { - mvaddstr (9, 1, - "You fall into the water! You sink like a rock.--More--"); - mvprintw (10, 1, - "(I couldn't open %s'%c spool file for some reason, so I'm giving up.)", - username, (username[strlen (username) - 1] != 's') ? 's' : 0); - getch (); - return; - } - - mvaddstr (9, 1, "Getting a lock on the mailspool..."); - refresh (); - - while (fcntl (fileno (user_spool), F_SETLK, &fl) == -1); - - fprintf (user_spool, "%s:%s\n", me->username, message); - - fl.l_type = F_UNLCK; - - if (fcntl (fileno (user_spool), F_UNLCK, &fl) == -1) - mvaddstr (10, 1, "Couldn't unlock the file! Oh well."); - - fclose (user_spool); - - return; + unsigned int len, i; + char *spool_fn, message[80]; + FILE *user_spool = NULL; + time_t now; + int mail_empty = 1; + struct flock fl = { F_WRLCK, SEEK_SET, 0, 0, getpid () }; + + assert (loggedin); + + len = + (sizeof (LOC_SPOOLDIR) / sizeof (LOC_SPOOLDIR[0])) + strlen (username) + + 1; + spool_fn = malloc (len + 1); + time (&now); + snprintf (spool_fn, len, "%s/%s", LOC_SPOOLDIR, username); + + /* print the enter your message line */ + clear (); + drawbanner (1, 1); + mvaddstr (5, 1, + "Enter your message here. It is to be one line only and 80 characters or less."); + mvaddstr (7, 1, "=> "); + + getnstr (message, 80); + + for (i = 0; i < strlen (message); i++) + { + if (message[i] != ' ' && message[i] != '\n' && message[i] != '\t') + mail_empty = 0; + } + + if (mail_empty) + { + mvaddstr (9, 1, "This scroll appears to be blank.--More--"); + mvaddstr (10, 1, "(Aborting your message.)"); + getch (); + return; + } + + if ((user_spool = fopen (spool_fn, "a")) == NULL) + { + mvaddstr (9, 1, + "You fall into the water! You sink like a rock.--More--"); + mvprintw (10, 1, + "(I couldn't open %s'%c spool file for some reason, so I'm giving up.)", + username, (username[strlen (username) - 1] != 's') ? 's' : 0); + getch (); + return; + } + + mvaddstr (9, 1, "Getting a lock on the mailspool..."); + refresh (); + + while (fcntl (fileno (user_spool), F_SETLK, &fl) == -1); + + fprintf (user_spool, "%s:%s\n", me->username, message); + + fl.l_type = F_UNLCK; + + if (fcntl (fileno (user_spool), F_UNLCK, &fl) == -1) + mvaddstr (10, 1, "Couldn't unlock the file! Oh well."); + + fclose (user_spool); + + return; } void drawmenu () { - static int flood = 0; - - clear (); - - mvaddstr (1, 1, VER1); - mvaddstr (2, 1, VER2); - mvaddstr (3, 1, VER3); - mvaddstr (4, 1, VER4); - mvaddstr (5, 1, VER5); - mvaddstr (6, 1, VER6); - mvaddstr (7, 1, VER7); - - if (loggedin) - { - mvprintw (VERLINES + 2, 1, "Logged in as: %s", me->username); - mvaddstr (VERLINES + 4, 1, "c) Change password"); - mvaddstr (VERLINES + 5, 1, "o) Edit option file (requires vi use)"); - mvaddstr (VERLINES + 6, 1, "w) Watch games in progress"); - mvaddstr (VERLINES + 7, 1, "p) Play nethack!"); - mvaddstr (VERLINES + 8, 1, "q) Quit"); - mvaddstr (VERLINES + 10, 1, "=> "); - } - else - { - mvaddstr (VERLINES + 2, 1, "Not logged in."); - mvaddstr (VERLINES + 4, 1, "l) Login"); - mvaddstr (VERLINES + 5, 1, "r) Register new user"); - mvaddstr (VERLINES + 6, 1, "w) Watch games in progress"); - mvaddstr (VERLINES + 7, 1, "q) Quit"); - mvaddstr (VERLINES + 9, 1, "=> "); - } - - refresh (); - - /* for retarded clients */ - flood++; - if (flood >= 20) - exit (119); + static int flood = 0; + + clear (); + + drawbanner (1, 0); + + if (loggedin) + { + mvprintw (banner.len + 2, 1, "Logged in as: %s", me->username); + mvaddstr (banner.len + 4, 1, "c) Change password"); + mvaddstr (banner.len + 5, 1, "o) Edit option file (requires vi use)"); + mvaddstr (banner.len + 6, 1, "w) Watch games in progress"); + mvaddstr (banner.len + 7, 1, "p) Play nethack!"); + mvaddstr (banner.len + 8, 1, "q) Quit"); + mvaddstr (banner.len + 10, 1, "=> "); + } + else + { + mvaddstr (banner.len + 2, 1, "Not logged in."); + mvaddstr (banner.len + 4, 1, "l) Login"); + mvaddstr (banner.len + 5, 1, "r) Register new user"); + mvaddstr (banner.len + 6, 1, "w) Watch games in progress"); + mvaddstr (banner.len + 7, 1, "q) Quit"); + mvaddstr (banner.len + 9, 1, "=> "); + } + + refresh (); + + /* for retarded clients */ + flood++; + if (flood >= 20) + exit (119); } /* ************************************************************* */ @@ -458,23 +529,23 @@ drawmenu () void freefile () { - int i; - - /* free existing mem, clear existing entries */ - for (i = 0; i < f_num; i++) - { - free (users[i]->password); - free (users[i]->username); - free (users[i]->email); - free (users[i]->env); - free (users[i]); - } - - if (users) - free (users); - - users = NULL; - f_num = 0; + int i; + + /* free existing mem, clear existing entries */ + for (i = 0; i < f_num; i++) + { + free (users[i]->password); + free (users[i]->username); + free (users[i]->email); + free (users[i]->env); + free (users[i]); + } + + if (users) + free (users); + + users = NULL; + f_num = 0; } /* ************************************************************* */ @@ -482,12 +553,12 @@ freefile () void initncurses () { - initscr (); - cbreak (); - echo (); - nonl (); - intrflush (stdscr, FALSE); - keypad (stdscr, TRUE); + initscr (); + cbreak (); + echo (); + nonl (); + intrflush (stdscr, FALSE); + keypad (stdscr, TRUE); } /* ************************************************************* */ @@ -495,75 +566,75 @@ initncurses () struct dg_user * deep_copy (struct dg_user *src) { - struct dg_user *dest = malloc (sizeof (struct dg_user)); + struct dg_user *dest = malloc (sizeof (struct dg_user)); - dest->username = strdup (src->username); - dest->email = strdup (src->email); - dest->env = strdup (src->env); - dest->password = strdup (src->password); - dest->flags = src->flags; + dest->username = strdup (src->username); + dest->email = strdup (src->email); + dest->env = strdup (src->env); + dest->password = strdup (src->password); + dest->flags = src->flags; - return dest; + return dest; } void login () { - char user_buf[22], pw_buf[22]; - int error = 2, me_index = -1; + char user_buf[22], pw_buf[22]; + int error = 2, me_index = -1; - loggedin = 0; + loggedin = 0; - while (error) - { - clear (); + while (error) + { + clear (); - mvaddstr (1, 1, VER1); + drawbanner (1, 1); - mvaddstr (5, 1, - "Please enter your username. (blank entry returns to main menu)"); - mvaddstr (7, 1, "=> "); + mvaddstr (5, 1, + "Please enter your username. (blank entry returns to main menu)"); + mvaddstr (7, 1, "=> "); - if (error == 1) - { - mvaddstr (9, 1, "There was a problem with your last entry."); - move (7, 4); - } + if (error == 1) + { + mvaddstr (9, 1, "There was a problem with your last entry."); + move (7, 4); + } - refresh (); + refresh (); - getnstr (user_buf, 20); + getnstr (user_buf, 20); - if (user_buf && *user_buf == '\0') - return; + if (user_buf && *user_buf == '\0') + return; - error = 1; + error = 1; - if ((me_index = userexist (user_buf)) != -1) - { - me = deep_copy (users[me_index]); - error = 0; - } - } + if ((me_index = userexist (user_buf)) != -1) + { + me = deep_copy (users[me_index]); + error = 0; + } + } - clear (); + clear (); - mvaddstr (1, 1, VER1); + drawbanner (1, 1); - mvaddstr (5, 1, "Please enter your password."); - mvaddstr (7, 1, "=> "); + mvaddstr (5, 1, "Please enter your password."); + mvaddstr (7, 1, "=> "); - refresh (); + refresh (); - noecho (); - getnstr (pw_buf, 20); - echo (); + noecho (); + getnstr (pw_buf, 20); + echo (); - if (passwordgood (user_buf, pw_buf)) - { - loggedin = 1; - snprintf (rcfilename, 80, "%s%s.nethackrc", LOC_DGLDIR, me->username); - } + if (passwordgood (user_buf, pw_buf)) + { + loggedin = 1; + snprintf (rcfilename, 80, "%s%s.nethackrc", LOC_DGLDIR, me->username); + } } /* ************************************************************* */ @@ -571,97 +642,97 @@ login () void newuser () { - char buf[1024]; - int error = 2; - unsigned int i; + char buf[1024]; + int error = 2; + unsigned int i; + + loggedin = 0; - loggedin = 0; + if (me) + free (me); - if (me) - free (me); + me = malloc (sizeof (struct dg_user)); - me = malloc (sizeof (struct dg_user)); + while (error) + { + clear (); - while (error) - { - clear (); + drawbanner (1, 1); - mvaddstr (1, 1, VER1); + mvaddstr (5, 1, "Welcome new user. Please enter a username."); + mvaddstr (6, 1, + "Only characters and numbers are allowed, with no spaces."); + mvaddstr (7, 1, "20 character max."); + mvaddstr (9, 1, "=> "); - mvaddstr (5, 1, "Welcome new user. Please enter a username."); - mvaddstr (6, 1, - "Only characters and numbers are allowed, with no spaces."); - mvaddstr (7, 1, "20 character max."); - mvaddstr (9, 1, "=> "); + if (error == 1) + { + mvaddstr (11, 1, "There was a problem with your last entry."); + move (9, 4); + } - if (error == 1) - { - mvaddstr (11, 1, "There was a problem with your last entry."); - move (9, 4); - } + refresh (); - refresh (); + getnstr (buf, 20); + if (userexist (buf) == -1) + error = 0; + else + error = 1; - getnstr (buf, 20); - if (userexist (buf) == -1) - error = 0; - else - error = 1; + for (i = 0; i < strlen (buf); i++) + { + if (! + (((buf[i] >= 'a') && (buf[i] <= 'z')) + || ((buf[i] >= 'A') && (buf[i] <= 'Z')) || ((buf[i] >= '0') + && (buf[i] <= + '9')))) + error = 1; + } - for (i = 0; i < strlen (buf); i++) - { - if (! - (((buf[i] >= 'a') && (buf[i] <= 'z')) - || ((buf[i] >= 'A') && (buf[i] <= 'Z')) || ((buf[i] >= '0') - && (buf[i] <= - '9')))) - error = 1; - } + if (strlen (buf) < 2) + error = 1; - if (strlen (buf) < 2) - error = 1; + if (strlen (buf) == 0) + return; + } - if (strlen (buf) == 0) - return; - } + me->username = strdup (buf); - me->username = strdup (buf); + /* password step */ - /* password step */ + clear (); - clear (); + changepw (); /* Calling changepw instead to prompt twice. */ - changepw(); /* Calling changepw instead to prompt twice. */ - - /* email step */ + /* email step */ - clear (); + clear (); - mvaddstr (1, 1, VER1); + drawbanner (1, 1); - mvaddstr (5, 1, "Please enter your email address."); - mvaddstr (6, 1, - "This is sent _nowhere_ but will be used if you ask the sysadmin for lost"); - mvaddstr (7, 1, - "password help. Please use a correct one. It only benefits you."); - mvaddstr (8, 1, "80 character max. No ':' characters."); - mvaddstr (10, 1, "=> "); + mvaddstr (5, 1, "Please enter your email address."); + mvaddstr (6, 1, + "This is sent _nowhere_ but will be used if you ask the sysadmin for lost"); + mvaddstr (7, 1, + "password help. Please use a correct one. It only benefits you."); + mvaddstr (8, 1, "80 character max. No ':' characters."); + mvaddstr (10, 1, "=> "); - refresh (); - getnstr (buf, 80); + refresh (); + getnstr (buf, 80); - if (strstr (buf, ":") != NULL) - exit (113); + if (strstr (buf, ":") != NULL) + exit (113); - me->email = strdup (buf); - me->env = calloc (1, 1); + me->email = strdup (buf); + me->env = calloc (1, 1); - loggedin = 1; + loggedin = 1; - snprintf (rcfilename, 80, "%s%s.nethackrc", LOC_DGLDIR, me->username); - write_canned_rcfile (rcfilename); + snprintf (rcfilename, 80, "%s%s.nethackrc", LOC_DGLDIR, me->username); + write_canned_rcfile (rcfilename); - writefile (1); + writefile (1); } /* ************************************************************* */ @@ -669,12 +740,12 @@ newuser () int passwordgood (char *cname, char *cpw) { - if (!strncmp (crypt (cpw, cpw), me->password, 13)) - return 1; - if (!strncmp (cpw, me->password, 20)) - return 1; + if (!strncmp (crypt (cpw, cpw), me->password, 13)) + return 1; + if (!strncmp (cpw, me->password, 20)) + return 1; - return 0; + return 0; } /* ************************************************************* */ @@ -682,102 +753,102 @@ passwordgood (char *cname, char *cpw) int readfile (int nolock) { - FILE *fp = NULL, *fpl = NULL; - char buf[1200]; - - memset (buf, 1024, 0); - - /* read new stuff */ - - if (!nolock) - { - fpl = fopen ("/dgl-lock", "r"); - if (!fpl) - exit (106); - if (flock (fileno (fpl), LOCK_SH)) - exit (114); - } - - fp = fopen ("/dgl-login", "r"); - if (!fp) - exit (106); - - /* once per name in the file */ - while (fgets (buf, 1200, fp)) - { - char *b = buf, *n = buf; - - users = realloc (users, sizeof (struct dg_user *) * (f_num + 1)); - users[f_num] = malloc (sizeof (struct dg_user)); - users[f_num]->username = (char *) calloc (22, sizeof (char)); - users[f_num]->email = (char *) calloc (82, sizeof (char)); - users[f_num]->password = (char *) calloc (22, sizeof (char)); - users[f_num]->env = (char *) calloc (1026, sizeof (char)); - - /* name field, must be valid */ - while (*b != ':') - { - if (!(((*b >= 'a') && (*b <= 'z')) || ((*b >= 'A') && (*b <= 'Z')) - || ((*b >= '0') && (*b <= '9')))) - return 1; - users[f_num]->username[(b - n)] = *b; - b++; - if ((b - n) >= 21) - exit (100); - } - - /* advance to next field */ - n = b + 1; - b = n; - - /* email field */ - while (*b != ':') - { - users[f_num]->email[(b - n)] = *b; - b++; - if ((b - n) > 80) - exit (101); - } - - /* advance to next field */ - n = b + 1; - b = n; - - /* pw field */ - while (*b != ':') - { - users[f_num]->password[(b - n)] = *b; - b++; - if ((b - n) >= 20) - exit (102); - } - - /* advance to next field */ - n = b + 1; - b = n; - - /* env field */ - while ((*b != '\n') && (*b != 0) && (*b != EOF)) - { - users[f_num]->env[(b - n)] = *b; - b++; - if ((b - n) >= 1024) - exit (102); - } - - f_num++; - /* prevent a buffer overrun here */ - if (f_num >= MAXUSERS) - exit (109); - } - - if (!nolock) - { - flock (fileno (fpl), LOCK_UN); - fclose (fpl); - } - fclose (fp); - return 0; + FILE *fp = NULL, *fpl = NULL; + char buf[1200]; + + memset (buf, 1024, 0); + + /* read new stuff */ + + if (!nolock) + { + fpl = fopen ("/dgl-lock", "r"); + if (!fpl) + exit (106); + if (flock (fileno (fpl), LOCK_SH)) + exit (114); + } + + fp = fopen ("/dgl-login", "r"); + if (!fp) + exit (106); + + /* once per name in the file */ + while (fgets (buf, 1200, fp)) + { + char *b = buf, *n = buf; + + users = realloc (users, sizeof (struct dg_user *) * (f_num + 1)); + users[f_num] = malloc (sizeof (struct dg_user)); + users[f_num]->username = (char *) calloc (22, sizeof (char)); + users[f_num]->email = (char *) calloc (82, sizeof (char)); + users[f_num]->password = (char *) calloc (22, sizeof (char)); + users[f_num]->env = (char *) calloc (1026, sizeof (char)); + + /* name field, must be valid */ + while (*b != ':') + { + if (!(((*b >= 'a') && (*b <= 'z')) || ((*b >= 'A') && (*b <= 'Z')) + || ((*b >= '0') && (*b <= '9')))) + return 1; + users[f_num]->username[(b - n)] = *b; + b++; + if ((b - n) >= 21) + exit (100); + } + + /* advance to next field */ + n = b + 1; + b = n; + + /* email field */ + while (*b != ':') + { + users[f_num]->email[(b - n)] = *b; + b++; + if ((b - n) > 80) + exit (101); + } + + /* advance to next field */ + n = b + 1; + b = n; + + /* pw field */ + while (*b != ':') + { + users[f_num]->password[(b - n)] = *b; + b++; + if ((b - n) >= 20) + exit (102); + } + + /* advance to next field */ + n = b + 1; + b = n; + + /* env field */ + while ((*b != '\n') && (*b != 0) && (*b != EOF)) + { + users[f_num]->env[(b - n)] = *b; + b++; + if ((b - n) >= 1024) + exit (102); + } + + f_num++; + /* prevent a buffer overrun here */ + if (f_num >= MAXUSERS) + exit (109); + } + + if (!nolock) + { + flock (fileno (fpl), LOCK_UN); + fclose (fpl); + } + fclose (fp); + return 0; } /* ************************************************************* */ @@ -785,15 +856,15 @@ readfile (int nolock) int userexist (char *cname) { - int i; + int i; - for (i = 0; i < f_num; i++) - { - if (!strncasecmp (cname, users[i]->username, 20)) - return i; - } + for (i = 0; i < f_num; i++) + { + if (!strncasecmp (cname, users[i]->username, 20)) + return i; + } - return -1; + return -1; } /* ************************************************************* */ @@ -801,64 +872,64 @@ userexist (char *cname) void write_canned_rcfile (char *target) { - FILE *canned, *newfile; - char buf[1024]; - size_t bytes; - - if (!(newfile = fopen (target, "w"))) - { - bail: - mvaddstr (13, 1, - "You don't know how to write that! You write \"%s\" was here and the scroll disappears."); - mvaddstr (14, 1, - "(Sorry, but I couldn't open one of the nethackrc files. This is a bug.)"); - return; - } - - if (!(canned = fopen (LOC_CANNED, "r"))) - goto bail; - - while ((bytes = fread (buf, 1, 1024, canned)) > 0) - { - if (fwrite (buf, 1, bytes, newfile) != bytes) - { - if (ferror (newfile)) - { - mvaddstr (13, 1, "Your hand slips while engraving."); - mvaddstr (14, 1, - "(Encountered a problem writing the new file. This is a bug.)"); - fclose (canned); - fclose (newfile); - return; - } - } - } - - fclose (canned); - fclose (newfile); + FILE *canned, *newfile; + char buf[1024]; + size_t bytes; + + if (!(newfile = fopen (target, "w"))) + { + bail: + mvaddstr (13, 1, + "You don't know how to write that! You write \"%s\" was here and the scroll disappears."); + mvaddstr (14, 1, + "(Sorry, but I couldn't open one of the nethackrc files. This is a bug.)"); + return; + } + + if (!(canned = fopen (LOC_CANNED, "r"))) + goto bail; + + while ((bytes = fread (buf, 1, 1024, canned)) > 0) + { + if (fwrite (buf, 1, bytes, newfile) != bytes) + { + if (ferror (newfile)) + { + mvaddstr (13, 1, "Your hand slips while engraving."); + mvaddstr (14, 1, + "(Encountered a problem writing the new file. This is a bug.)"); + fclose (canned); + fclose (newfile); + return; + } + } + } + + fclose (canned); + fclose (newfile); } void editoptions () { - FILE *rcfile; - char *myargv[3]; + FILE *rcfile; + char *myargv[3]; - rcfile = fopen (rcfilename, "r"); - printf (" read"); - if (!rcfile) /* should not really happen except for old users */ - write_canned_rcfile (rcfilename); + rcfile = fopen (rcfilename, "r"); + printf (" read"); + if (!rcfile) /* should not really happen except for old users */ + write_canned_rcfile (rcfilename); - /* use virus to edit */ + /* use virus to edit */ - myargv[0] = ""; - myargv[1] = rcfilename; - myargv[2] = 0; + myargv[0] = ""; + myargv[1] = rcfilename; + myargv[2] = 0; - endwin (); - vi_main (2, myargv); - refresh (); + endwin (); + vi_main (2, myargv); + refresh (); } /* ************************************************************* */ @@ -866,52 +937,52 @@ editoptions () void writefile (int requirenew) { - FILE *fp, *fpl; - int i = 0; - int my_done = 0; - - fpl = fopen ("/dgl-lock", "r"); - if (!fpl) - exit (115); - if (flock (fileno (fpl), LOCK_EX)) - exit (107); - - freefile (); - readfile (1); - - fp = fopen ("/dgl-login", "w"); - if (!fp) - exit (104); - - for (i = 0; i < f_num; i++) - { - if (loggedin && !strncasecmp (me->username, users[i]->username, 20)) - { - if (requirenew) - { - /* this is if someone managed to register at the same time - * as someone else. just die. */ - exit (111); - } - fprintf (fp, "%s:%s:%s:%s\n", me->username, me->email, me->password, - me->env); - my_done = 1; - } - else - { - fprintf (fp, "%s:%s:%s:%s\n", users[i]->username, users[i]->email, - users[i]->password, users[i]->env); - } - } - if (loggedin && !my_done) - { /* new entry */ - fprintf (fp, "%s:%s:%s:%s\n", me->username, me->email, me->password, - me->env); - } - - flock (fileno (fpl), LOCK_UN); - fclose (fp); - fclose (fpl); + FILE *fp, *fpl; + int i = 0; + int my_done = 0; + + fpl = fopen ("/dgl-lock", "r"); + if (!fpl) + exit (115); + if (flock (fileno (fpl), LOCK_EX)) + exit (107); + + freefile (); + readfile (1); + + fp = fopen ("/dgl-login", "w"); + if (!fp) + exit (104); + + for (i = 0; i < f_num; i++) + { + if (loggedin && !strncasecmp (me->username, users[i]->username, 20)) + { + if (requirenew) + { + /* this is if someone managed to register at the same time + * as someone else. just die. */ + exit (111); + } + fprintf (fp, "%s:%s:%s:%s\n", me->username, me->email, me->password, + me->env); + my_done = 1; + } + else + { + fprintf (fp, "%s:%s:%s:%s\n", users[i]->username, users[i]->email, + users[i]->password, users[i]->env); + } + } + if (loggedin && !my_done) + { /* new entry */ + fprintf (fp, "%s:%s:%s:%s\n", me->username, me->email, me->password, + me->env); + } + + flock (fileno (fpl), LOCK_UN); + fclose (fp); + fclose (fpl); } /* ************************************************************* */ @@ -921,120 +992,120 @@ writefile (int requirenew) int main (void) { - /* for chroot and program execution */ - uid_t newuid = SHED_UID; - gid_t newgid = SHED_GID; - char atrcfilename[81], *spool; - unsigned int len; - struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; - - int userchoice = 0; - - /* coredumper */ - setrlimit(RLIMIT_CORE, &rl); - - /* signal handlers */ - signal (SIGHUP, catch_sighup); - - /* get master tty just before chroot (lives in /dev) */ - ttyrec_getmaster (); - grantpt (master); - unlockpt (master); - if ((slave = open ((const char *) ptsname (master), O_RDWR)) < 0) - { - exit (65); - } - - - /* chroot */ - if (chroot (LOC_CHROOT)) - { - perror ("cannot change root directory"); - exit (1); - } - - if (chdir ("/")) - { - perror ("cannot chdir to root directory"); - exit (1); - } - - /* shed privs. this is done immediately after chroot. */ - setgid (newgid); - setuid (newuid); - - /* simple login routine, uses ncurses */ - if (readfile (0)) - exit (110); - - initncurses (); - while ((userchoice != 'p') | (!loggedin)) - { - drawmenu (); - userchoice = getch (); - switch (tolower (userchoice)) - { - case 'c': - changepw (); - break; - case 'w': - inprogressmenu (); - break; - case 'o': - if (loggedin) - editoptions (); - break; - case 'q': - endwin (); - exit (1); - /* break; */ - case 'r': - if (!loggedin) /*not visible to loggedin */ - newuser (); - break; - case 'l': - if (!loggedin) /* not visible to loggedin */ - login (); - break; - } - } - - assert (loggedin); - - endwin (); - - /* environment */ - snprintf (atrcfilename, 81, "@%s", rcfilename); - - len = - (sizeof (LOC_SPOOLDIR) / sizeof (LOC_SPOOLDIR[0])) + - strlen (me->username) + 1; - spool = malloc (len + 1); - snprintf (spool, len, "%s/%s", LOC_SPOOLDIR, me->username); - - setenv ("NETHACKOPTIONS", atrcfilename, 1); - setenv ("MAIL", spool, 1); - setenv ("SIMPLEMAIL", "1", 1); - - /* don't let the mail file grow */ - if (access (spool, F_OK) == 0) - unlink (spool); - - free (spool); - - /* lock */ - gen_ttyrec_filename (); - gen_inprogress_lock (); - - /* launch program */ - ttyrec_main (me->username); - - /* NOW we can safely kill this */ - freefile (); - - if (me) - free (me); - - exit (1); - return 1; + /* for chroot and program execution */ + uid_t newuid = SHED_UID; + gid_t newgid = SHED_GID; + char atrcfilename[81], *spool; + unsigned int len; + struct rlimit rl = { RLIM_INFINITY, RLIM_INFINITY }; + + int userchoice = 0; + + /* coredumper */ + setrlimit (RLIMIT_CORE, &rl); + + /* signal handlers */ + signal (SIGHUP, catch_sighup); + + /* get master tty just before chroot (lives in /dev) */ + ttyrec_getmaster (); + grantpt (master); + unlockpt (master); + if ((slave = open ((const char *) ptsname (master), O_RDWR)) < 0) + { + exit (65); + } + + + /* chroot */ + if (chroot (LOC_CHROOT)) + { + perror ("cannot change root directory"); + exit (1); + } + + if (chdir ("/")) + { + perror ("cannot chdir to root directory"); + exit (1); + } + + /* shed privs. this is done immediately after chroot. */ + setgid (newgid); + setuid (newuid); + + /* simple login routine, uses ncurses */ + if (readfile (0)) + exit (110); + + initncurses (); + while ((userchoice != 'p') | (!loggedin)) + { + drawmenu (); + userchoice = getch (); + switch (tolower (userchoice)) + { + case 'c': + changepw (); + break; + case 'w': + inprogressmenu (); + break; + case 'o': + if (loggedin) + editoptions (); + break; + case 'q': + endwin (); + exit (1); + /* break; */ + case 'r': + if (!loggedin) /*not visible to loggedin */ + newuser (); + break; + case 'l': + if (!loggedin) /* not visible to loggedin */ + login (); + break; + } + } + + assert (loggedin); + + endwin (); + + /* environment */ + snprintf (atrcfilename, 81, "@%s", rcfilename); + + len = + (sizeof (LOC_SPOOLDIR) / sizeof (LOC_SPOOLDIR[0])) + + strlen (me->username) + 1; + spool = malloc (len + 1); + snprintf (spool, len, "%s/%s", LOC_SPOOLDIR, me->username); + + setenv ("NETHACKOPTIONS", atrcfilename, 1); + setenv ("MAIL", spool, 1); + setenv ("SIMPLEMAIL", "1", 1); + + /* don't let the mail file grow */ + if (access (spool, F_OK) == 0) + unlink (spool); + + free (spool); + + /* lock */ + gen_ttyrec_filename (); + gen_inprogress_lock (); + + /* launch program */ + ttyrec_main (me->username); + + /* NOW we can safely kill this */ + freefile (); + + if (me) + free (me); + + exit (1); + return 1; } diff --git a/dgamelaunch.h b/dgamelaunch.h index a07a56f..9c083cb 100644 --- a/dgamelaunch.h +++ b/dgamelaunch.h @@ -5,16 +5,22 @@ struct dg_user { - char *username; - char *email; - char *env; - char *password; - int flags; + char *username; + char *email; + char *env; + char *password; + int flags; }; -#define SHED_UID 5 /* the uid to shed privs to */ -#define SHED_GID 60 /* the gid to shed privs to */ -#define MAXUSERS 64000 /* solves some preallocation issues. */ +struct dg_banner +{ + char **lines; + unsigned int len; +}; + +#define SHED_UID 5 /* the uid to shed privs to */ +#define SHED_GID 60 /* the gid to shed privs to */ +#define MAXUSERS 64000 /* solves some preallocation issues. */ #define LOC_CHROOT "/var/lib/dgamelaunch/" #define LOC_NETHACK "/bin/nethack" diff --git a/dgl-banner b/dgl-banner new file mode 100644 index 0000000..956e12b --- /dev/null +++ b/dgl-banner @@ -0,0 +1,7 @@ +## dgamelaunch - network console game launcher +## version $VERSION +## +## (c)2001-3 M. Drew Streib. This program's source is released under the GPL. +## Send mail to for details or a copy of the source code. +## ** Games on this server are recorded for in-progress viewing and playback! +## Server info is at http://alt.org/nethack/ diff --git a/io.c b/io.c index 15a81ae..3cbee29 100644 --- a/io.c +++ b/io.c @@ -48,99 +48,99 @@ static int is_little_endian () { - static int retval = -1; - - if (retval == -1) - { - int n = 1; - char *p = (char *) &n; - char x[] = { 1, 0, 0, 0 }; - - assert (sizeof (int) == 4); - - if (memcmp (p, x, 4) == 0) - { - retval = 1; - } - else - { - retval = 0; - } - } - - return retval; + static int retval = -1; + + if (retval == -1) + { + int n = 1; + char *p = (char *) &n; + char x[] = { 1, 0, 0, 0 }; + + assert (sizeof (int) == 4); + + if (memcmp (p, x, 4) == 0) + { + retval = 1; + } + else + { + retval = 0; + } + } + + return retval; } static int convert_to_little_endian (int x) { - if (is_little_endian ()) - { - return x; - } - else - { - return SWAP_ENDIAN (x); - } + if (is_little_endian ()) + { + return x; + } + else + { + return SWAP_ENDIAN (x); + } } int read_header (FILE * fp, Header * h) { - int buf[3]; - int numread; - long offset; - - offset = ftell (fp); - numread = fread (buf, sizeof (int), 3, fp); - - /* odd but possible race condition when full header isn't read because - * it isn't there yet. */ - if (numread < 3) - { - fseek (fp, offset, SEEK_SET); - return 0; - } - - h->tv.tv_sec = convert_to_little_endian (buf[0]); - h->tv.tv_usec = convert_to_little_endian (buf[1]); - h->len = convert_to_little_endian (buf[2]); - - return 1; + int buf[3]; + int numread; + long offset; + + offset = ftell (fp); + numread = fread (buf, sizeof (int), 3, fp); + + /* odd but possible race condition when full header isn't read because + * it isn't there yet. */ + if (numread < 3) + { + fseek (fp, offset, SEEK_SET); + return 0; + } + + h->tv.tv_sec = convert_to_little_endian (buf[0]); + h->tv.tv_usec = convert_to_little_endian (buf[1]); + h->len = convert_to_little_endian (buf[2]); + + return 1; } int write_header (FILE * fp, Header * h) { - int buf[3]; + int buf[3]; - buf[0] = convert_to_little_endian (h->tv.tv_sec); - buf[1] = convert_to_little_endian (h->tv.tv_usec); - buf[2] = convert_to_little_endian (h->len); + buf[0] = convert_to_little_endian (h->tv.tv_sec); + buf[1] = convert_to_little_endian (h->tv.tv_usec); + buf[2] = convert_to_little_endian (h->len); - if (fwrite (buf, sizeof (int), 3, fp) == 0) - { - return 0; - } + if (fwrite (buf, sizeof (int), 3, fp) == 0) + { + return 0; + } - return 1; + return 1; } static char *progname = ""; void set_progname (const char *name) { - progname = strdup (name); + progname = strdup (name); } FILE * efopen (const char *path, const char *mode) { - FILE *fp = fopen (path, mode); - if (fp == NULL) - { - fprintf (stderr, "%s: %s: %s\n", progname, path, strerror (errno)); - exit (EXIT_FAILURE); - } - return fp; + FILE *fp = fopen (path, mode); + if (fp == NULL) + { + fprintf (stderr, "%s: %s: %s\n", progname, path, strerror (errno)); + exit (EXIT_FAILURE); + } + return fp; } diff --git a/last_char_is.c b/last_char_is.c index 64e9a9d..aa8c88f 100644 --- a/last_char_is.c +++ b/last_char_is.c @@ -28,16 +28,16 @@ char * last_char_is (const char *s, int c) { - char *sret; - if (!s) - return NULL; - sret = (char *) s + strlen (s) - 1; - if (sret >= s && *sret == c) - { - return sret; - } - else - { - return NULL; - } + char *sret; + if (!s) + return NULL; + sret = (char *) s + strlen (s) - 1; + if (sret >= s && *sret == c) + { + return sret; + } + else + { + return NULL; + } } diff --git a/stripgfx.c b/stripgfx.c index 614abb0..ac47466 100644 --- a/stripgfx.c +++ b/stripgfx.c @@ -11,384 +11,384 @@ unsigned char gfx_map[256]; unsigned int state = 0; static unsigned char no_graphics[MAXPCHARS] = { - ' ', /* 0 */ - /* stone */ - '|', /* vwall */ - '-', /* hwall */ - '-', /* tlcorn */ - '-', /* trcorn */ - '-', /* blcorn */ - '-', /* brcorn */ - '-', /* crwall */ - '-', /* tuwall */ - '-', /* tdwall */ - '|', /* 10 */ - /* tlwall */ - '|', /* trwall */ - '.', /* ndoor */ - '-', /* vodoor */ - '|', /* hodoor */ - '+', /* vcdoor */ - '+', /* hcdoor */ - '#', /* bars */ - '#', /* tree */ - '.', /* room */ - '#', /* 20 */ - /* dark corr */ - '#', /* lit corr */ - '<', /* upstair */ - '>', /* dnstair */ - '<', /* upladder */ - '>', /* dnladder */ - '_', /* altar */ - '|', /* grave */ - '\\', /* throne */ - '#', /* sink */ - '{', /* 30 */ - /* fountain */ - '}', /* pool */ - '.', /* ice */ - '}', /* lava */ - '.', /* vodbridge */ - '.', /* hodbridge */ - '#', /* vcdbridge */ - '#', /* hcdbridge */ - ' ', /* open air */ - '#', /* [part of] a cloud */ - '}', /* 40 */ - /* under water */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* 50 */ - /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '^', /* trap */ - '"', /* web */ - '^', /* trap */ - '^', /* 60 */ - /* trap */ - '^', /* trap */ - '^', /* trap */ - '|', /* vbeam */ - '-', /* hbeam */ - '\\', /* lslant */ - '/', /* rslant */ - '*', /* dig beam */ - '!', /* camera flash beam */ - ')', /* boomerang open left */ - '(', /* 70 */ - /* boomerang open right */ - '0', /* 4 magic shield symbols */ - '#', - '@', - '*', - '/', /* swallow top left */ - '-', /* swallow top center */ - '\\', /* swallow top right */ - '|', /* swallow middle left */ - '|', /* swallow middle right */ - '\\', /* 80 */ - /* swallow bottom left */ - '-', /* swallow bottom center */ - '/', /* swallow bottom right */ - '/', /* explosion top left */ - '-', /* explosion top center */ - '\\', /* explosion top right */ - '|', /* explosion middle left */ - ' ', /* explosion middle center */ - '|', /* explosion middle right */ - '\\', /* explosion bottom left */ - '-', /* 90 */ - /* explosion bottom center */ - '/' /* explosion bottom right */ + ' ', /* 0 */ + /* stone */ + '|', /* vwall */ + '-', /* hwall */ + '-', /* tlcorn */ + '-', /* trcorn */ + '-', /* blcorn */ + '-', /* brcorn */ + '-', /* crwall */ + '-', /* tuwall */ + '-', /* tdwall */ + '|', /* 10 */ + /* tlwall */ + '|', /* trwall */ + '.', /* ndoor */ + '-', /* vodoor */ + '|', /* hodoor */ + '+', /* vcdoor */ + '+', /* hcdoor */ + '#', /* bars */ + '#', /* tree */ + '.', /* room */ + '#', /* 20 */ + /* dark corr */ + '#', /* lit corr */ + '<', /* upstair */ + '>', /* dnstair */ + '<', /* upladder */ + '>', /* dnladder */ + '_', /* altar */ + '|', /* grave */ + '\\', /* throne */ + '#', /* sink */ + '{', /* 30 */ + /* fountain */ + '}', /* pool */ + '.', /* ice */ + '}', /* lava */ + '.', /* vodbridge */ + '.', /* hodbridge */ + '#', /* vcdbridge */ + '#', /* hcdbridge */ + ' ', /* open air */ + '#', /* [part of] a cloud */ + '}', /* 40 */ + /* under water */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* 50 */ + /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '^', /* trap */ + '"', /* web */ + '^', /* trap */ + '^', /* 60 */ + /* trap */ + '^', /* trap */ + '^', /* trap */ + '|', /* vbeam */ + '-', /* hbeam */ + '\\', /* lslant */ + '/', /* rslant */ + '*', /* dig beam */ + '!', /* camera flash beam */ + ')', /* boomerang open left */ + '(', /* 70 */ + /* boomerang open right */ + '0', /* 4 magic shield symbols */ + '#', + '@', + '*', + '/', /* swallow top left */ + '-', /* swallow top center */ + '\\', /* swallow top right */ + '|', /* swallow middle left */ + '|', /* swallow middle right */ + '\\', /* 80 */ + /* swallow bottom left */ + '-', /* swallow bottom center */ + '/', /* swallow bottom right */ + '/', /* explosion top left */ + '-', /* explosion top center */ + '\\', /* explosion top right */ + '|', /* explosion middle left */ + ' ', /* explosion middle center */ + '|', /* explosion middle right */ + '\\', /* explosion bottom left */ + '-', /* 90 */ + /* explosion bottom center */ + '/' /* explosion bottom right */ }; static unsigned char ibm_graphics[MAXPCHARS] = { /* 0*/ 0x00, - 0xb3, /* : meta-3, vertical rule */ - 0xc4, /* : meta-D, horizontal rule */ - 0xda, /* : meta-Z, top left corner */ - 0xbf, /* : meta-?, top right corner */ - 0xc0, /* : meta-@, bottom left */ - 0xd9, /* : meta-Y, bottom right */ - 0xc5, /* : meta-E, cross */ - 0xc1, /* : meta-A, T up */ - 0xc2, /* : meta-B, T down */ - /*10 */ 0xb4, - /* : meta-4, T left */ - 0xc3, /* : meta-C, T right */ - 0xfa, /* : meta-z, centered dot */ - 0xfe, /* : meta-~, small centered square */ - 0xfe, /* : meta-~, small centered square */ - 0x00, - 0x00, - 240, /* : equivalence symbol */ - 241, /* : plus or minus symbol */ - 0xfa, /* : meta-z, centered dot */ - /*20 */ 0xb0, - /* : meta-0, light shading */ - 0xb1, /* : meta-1, medium shading */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - /*30 */ 0xf4, - /* : meta-t, integral top half */ - 0xf7, /* : meta-w, approx. equals */ - 0xfa, /* : meta-z, centered dot */ - 0xf7, /* : meta-w, approx. equals */ - 0xfa, /* : meta-z, centered dot */ - 0xfa, /* : meta-z, centered dot */ - 0x00, - 0x00, - 0x00, - 0x00, - /*40 */ 0xf7, - /* : meta-w, approx. equals */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, + 0xb3, /* : meta-3, vertical rule */ + 0xc4, /* : meta-D, horizontal rule */ + 0xda, /* : meta-Z, top left corner */ + 0xbf, /* : meta-?, top right corner */ + 0xc0, /* : meta-@, bottom left */ + 0xd9, /* : meta-Y, bottom right */ + 0xc5, /* : meta-E, cross */ + 0xc1, /* : meta-A, T up */ + 0xc2, /* : meta-B, T down */ + /*10 */ 0xb4, + /* : meta-4, T left */ + 0xc3, /* : meta-C, T right */ + 0xfa, /* : meta-z, centered dot */ + 0xfe, /* : meta-~, small centered square */ + 0xfe, /* : meta-~, small centered square */ + 0x00, + 0x00, + 240, /* : equivalence symbol */ + 241, /* : plus or minus symbol */ + 0xfa, /* : meta-z, centered dot */ + /*20 */ 0xb0, + /* : meta-0, light shading */ + 0xb1, /* : meta-1, medium shading */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + /*30 */ 0xf4, + /* : meta-t, integral top half */ + 0xf7, /* : meta-w, approx. equals */ + 0xfa, /* : meta-z, centered dot */ + 0xf7, /* : meta-w, approx. equals */ + 0xfa, /* : meta-z, centered dot */ + 0xfa, /* : meta-z, centered dot */ + 0x00, + 0x00, + 0x00, + 0x00, + /*40 */ 0xf7, + /* : meta-w, approx. equals */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, /*50*/ 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, /*60*/ 0x00, - 0x00, - 0x00, - 0xb3, /* : meta-3, vertical rule */ - 0xc4, /* : meta-D, horizontal rule */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, + 0x00, + 0x00, + 0xb3, /* : meta-3, vertical rule */ + 0xc4, /* : meta-D, horizontal rule */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, /*70*/ 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xb3, /* : meta-3, vertical rule */ - 0xb3, /* : meta-3, vertical rule */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xb3, /* : meta-3, vertical rule */ + 0xb3, /* : meta-3, vertical rule */ /*80*/ 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xb3, /* : meta-3, vertical rule */ - 0x00, - 0xb3, /* : meta-3, vertical rule */ - 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xb3, /* : meta-3, vertical rule */ + 0x00, + 0xb3, /* : meta-3, vertical rule */ + 0x00, /*90*/ 0x00, - 0x00 + 0x00 }; static unsigned char dec_graphics[MAXPCHARS] = { /* 0*/ 0x00, - 0xf8, /* : meta-x, vertical rule */ - 0xf1, /* : meta-q, horizontal rule */ - 0xec, /* : meta-l, top left corner */ - 0xeb, /* : meta-k, top right corner */ - 0xed, /* : meta-m, bottom left */ - 0xea, /* : meta-j, bottom right */ - 0xee, /* : meta-n, cross */ - 0xf6, /* : meta-v, T up */ - 0xf7, /* : meta-w, T down */ - /*10 */ 0xf5, - /* : meta-u, T left */ - 0xf4, /* : meta-t, T right */ - 0xfe, /* : meta-~, centered dot */ - 0xe1, /* : meta-a, solid block */ - 0xe1, /* : meta-a, solid block */ - 0x00, - 0x00, - 0xfb, /* : meta-{, small pi */ - 0xe7, /* : meta-g, plus-or-minus */ - 0xfe, /* : meta-~, centered dot */ + 0xf8, /* : meta-x, vertical rule */ + 0xf1, /* : meta-q, horizontal rule */ + 0xec, /* : meta-l, top left corner */ + 0xeb, /* : meta-k, top right corner */ + 0xed, /* : meta-m, bottom left */ + 0xea, /* : meta-j, bottom right */ + 0xee, /* : meta-n, cross */ + 0xf6, /* : meta-v, T up */ + 0xf7, /* : meta-w, T down */ + /*10 */ 0xf5, + /* : meta-u, T left */ + 0xf4, /* : meta-t, T right */ + 0xfe, /* : meta-~, centered dot */ + 0xe1, /* : meta-a, solid block */ + 0xe1, /* : meta-a, solid block */ + 0x00, + 0x00, + 0xfb, /* : meta-{, small pi */ + 0xe7, /* : meta-g, plus-or-minus */ + 0xfe, /* : meta-~, centered dot */ /*20*/ 0x00, - 0x00, - 0x00, - 0x00, - 0xf9, /* : meta-y, greater-than-or-equals */ - 0xfa, /* : meta-z, less-than-or-equals */ - 0x00, /* 0xc3, \E)3: meta-C, dagger */ - 0x00, - 0x00, - 0x00, - /*30 */ 0x00, - /* 0xdb, \E)3: meta-[, integral top half */ - 0xe0, /* : meta-\, diamond */ - 0xfe, /* : meta-~, centered dot */ - 0xe0, /* : meta-\, diamond */ - 0xfe, /* : meta-~, centered dot */ - 0xfe, /* : meta-~, centered dot */ - 0x00, - 0x00, - 0x00, - 0x00, - /*40 */ 0xe0, - /* : meta-\, diamond */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, + 0x00, + 0x00, + 0x00, + 0xf9, /* : meta-y, greater-than-or-equals */ + 0xfa, /* : meta-z, less-than-or-equals */ + 0x00, /* 0xc3, \E)3: meta-C, dagger */ + 0x00, + 0x00, + 0x00, + /*30 */ 0x00, + /* 0xdb, \E)3: meta-[, integral top half */ + 0xe0, /* : meta-\, diamond */ + 0xfe, /* : meta-~, centered dot */ + 0xe0, /* : meta-\, diamond */ + 0xfe, /* : meta-~, centered dot */ + 0xfe, /* : meta-~, centered dot */ + 0x00, + 0x00, + 0x00, + 0x00, + /*40 */ 0xe0, + /* : meta-\, diamond */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, /*50*/ 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, /* 0xbd, \E)3: meta-=, int'l currency */ - 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, /* 0xbd, \E)3: meta-=, int'l currency */ + 0x00, /*60*/ 0x00, - 0x00, - 0x00, - 0xf8, /* : meta-x, vertical rule */ - 0xf1, /* : meta-q, horizontal rule */ - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, + 0x00, + 0x00, + 0xf8, /* : meta-x, vertical rule */ + 0xf1, /* : meta-q, horizontal rule */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, /*70*/ 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0x00, - 0xef, /* : meta-o, high horizontal line */ - 0x00, - 0xf8, /* : meta-x, vertical rule */ - 0xf8, /* : meta-x, vertical rule */ + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xef, /* : meta-o, high horizontal line */ + 0x00, + 0xf8, /* : meta-x, vertical rule */ + 0xf8, /* : meta-x, vertical rule */ /*80*/ 0x00, - 0xf3, /* : meta-s, low horizontal line */ - 0x00, - 0x00, - 0xef, /* : meta-o, high horizontal line */ - 0x00, - 0xf8, /* : meta-x, vertical rule */ - 0x00, - 0xf8, /* : meta-x, vertical rule */ - 0x00, - /*90 */ 0xf3, - /* : meta-s, low horizontal line */ - 0x00 + 0xf3, /* : meta-s, low horizontal line */ + 0x00, + 0x00, + 0xef, /* : meta-o, high horizontal line */ + 0x00, + 0xf8, /* : meta-x, vertical rule */ + 0x00, + 0xf8, /* : meta-x, vertical rule */ + 0x00, + /*90 */ 0xf3, + /* : meta-s, low horizontal line */ + 0x00 }; -static unsigned char IBM_r_oc_syms[18] = { /* a la EPYX Rogue */ +static unsigned char IBM_r_oc_syms[18] = { /* a la EPYX Rogue */ /* 0*/ '\0', - 0x00, - 0x18, /* weapon: up arrow */ - /* 0x0a, */ 0x00, - /* armor: Vert rect with o */ - /* 0x09, */ 0x00, - /* ring: circle with arrow */ - /* 5 */ 0x0c, - /* amulet: "female" symbol */ - 0x00, - 0x05, /* food: club (as in cards) */ - 0xad, /* potion: upside down '!' */ - 0x0e, /* scroll: musical note */ + 0x00, + 0x18, /* weapon: up arrow */ + /* 0x0a, */ 0x00, + /* armor: Vert rect with o */ + /* 0x09, */ 0x00, + /* ring: circle with arrow */ + /* 5 */ 0x0c, + /* amulet: "female" symbol */ + 0x00, + 0x05, /* food: club (as in cards) */ + 0xad, /* potion: upside down '!' */ + 0x0e, /* scroll: musical note */ /*10*/ 0x00, - 0xe7, /* wand: greek tau */ - 0x0f, /* gold: yes it's the same as gems */ - 0x0f, /* gems: fancy '*' */ - 0x00, + 0xe7, /* wand: greek tau */ + 0x0f, /* gold: yes it's the same as gems */ + 0x0f, /* gems: fancy '*' */ + 0x00, /*15*/ 0x00, - 0x00, - 0x00 + 0x00, + 0x00 }; void populate_gfx_array (int gfxset) { - int i; + int i; - memset (gfx_map, 0, 256); + memset (gfx_map, 0, 256); - if (gfxset == NO_GRAPHICS) - return; + if (gfxset == NO_GRAPHICS) + return; - for (i = 0; i < MAXPCHARS; i++) - { - if ((gfxset == DEC_GRAPHICS) && (dec_graphics[i]) - && !(gfx_map[dec_graphics[i]])) - gfx_map[dec_graphics[i] - 128] = no_graphics[i]; - if ((gfxset == IBM_GRAPHICS) && (ibm_graphics[i])) - gfx_map[ibm_graphics[i] - 128] = no_graphics[i]; - } + for (i = 0; i < MAXPCHARS; i++) + { + if ((gfxset == DEC_GRAPHICS) && (dec_graphics[i]) + && !(gfx_map[dec_graphics[i]])) + gfx_map[dec_graphics[i] - 128] = no_graphics[i]; + if ((gfxset == IBM_GRAPHICS) && (ibm_graphics[i])) + gfx_map[ibm_graphics[i] - 128] = no_graphics[i]; + } - /* - endwin(); - for (i=0;i<256;i++) { - printf("%X:%X ",i,gfx_map[i]); - } - exit(1); */ + /* + endwin(); + for (i=0;i<256;i++) { + printf("%X:%X ",i,gfx_map[i]); + } + exit(1); */ } unsigned char strip_gfx (unsigned char inchar) { - if ((inchar == 0x0E) && (state == 0)) - { - state = 1; - return 0x00; - } + if ((inchar == 0x0E) && (state == 0)) + { + state = 1; + return 0x00; + } - if ((inchar == 0x0F) && (state == 1)) - { - state = 0; - return inchar; - } + if ((inchar == 0x0F) && (state == 1)) + { + state = 0; + return inchar; + } - if ((inchar == 0x1B) && (state == 1)) - { - state = 0; - return inchar; - } + if ((inchar == 0x1B) && (state == 1)) + { + state = 0; + return inchar; + } - if (gfx_map[inchar] && (state == 1)) - { - return gfx_map[inchar]; - } + if (gfx_map[inchar] && (state == 1)) + { + return gfx_map[inchar]; + } - return inchar; + return inchar; } diff --git a/ttyplay.c b/ttyplay.c index 5178de4..48f5780 100644 --- a/ttyplay.c +++ b/ttyplay.c @@ -58,368 +58,368 @@ int bstripgfx; char *ttyfile_local; typedef double (*WaitFunc) (struct timeval prev, - struct timeval cur, double speed); + struct timeval cur, double speed); typedef int (*ReadFunc) (FILE * fp, Header * h, char **buf, int pread); typedef void (*WriteFunc) (char *buf, int len); typedef void (*ProcessFunc) (FILE * fp, double speed, - ReadFunc read_func, WaitFunc wait_func); + ReadFunc read_func, WaitFunc wait_func); struct timeval timeval_diff (struct timeval tv1, struct timeval tv2) { - struct timeval diff; + struct timeval diff; - diff.tv_sec = tv2.tv_sec - tv1.tv_sec; - diff.tv_usec = tv2.tv_usec - tv1.tv_usec; - if (diff.tv_usec < 0) - { - diff.tv_sec--; - diff.tv_usec += 1000000; - } + diff.tv_sec = tv2.tv_sec - tv1.tv_sec; + diff.tv_usec = tv2.tv_usec - tv1.tv_usec; + if (diff.tv_usec < 0) + { + diff.tv_sec--; + diff.tv_usec += 1000000; + } - return diff; + return diff; } struct timeval timeval_div (struct timeval tv1, double n) { - double x = ((double) tv1.tv_sec + (double) tv1.tv_usec / 1000000.0) / n; - struct timeval div; + double x = ((double) tv1.tv_sec + (double) tv1.tv_usec / 1000000.0) / n; + struct timeval div; - div.tv_sec = (int) x; - div.tv_usec = (x - (int) x) * 1000000; + div.tv_sec = (int) x; + div.tv_usec = (x - (int) x) * 1000000; - return div; + return div; } double ttywait (struct timeval prev, struct timeval cur, double speed) { - struct timeval diff = timeval_diff (prev, cur); - fd_set readfs; - - assert (speed != 0); - diff = timeval_div (diff, speed); - - FD_SET (STDIN_FILENO, &readfs); - select (1, &readfs, NULL, NULL, &diff); /* skip if a user hits any key */ - if (FD_ISSET (0, &readfs)) - { /* a user hits a character? */ - char c; - read (STDIN_FILENO, &c, 1); /* drain the character */ - switch (c) - { - case '+': - case 'f': - speed *= 2; - break; - case '-': - case 's': - speed /= 2; - break; - case '1': - speed = 1.0; - break; - } - } - return speed; + struct timeval diff = timeval_diff (prev, cur); + fd_set readfs; + + assert (speed != 0); + diff = timeval_div (diff, speed); + + FD_SET (STDIN_FILENO, &readfs); + select (1, &readfs, NULL, NULL, &diff); /* skip if a user hits any key */ + if (FD_ISSET (0, &readfs)) + { /* a user hits a character? */ + char c; + read (STDIN_FILENO, &c, 1); /* drain the character */ + switch (c) + { + case '+': + case 'f': + speed *= 2; + break; + case '-': + case 's': + speed /= 2; + break; + case '1': + speed = 1.0; + break; + } + } + return speed; } double ttynowait (struct timeval prev, struct timeval cur, double speed) { - return 0; /* Speed isn't important. */ + return 0; /* Speed isn't important. */ } int ttyread (FILE * fp, Header * h, char **buf, int pread) { - long offset; - - /* do this BEFORE header read, hlen bug */ - offset = ftell (fp); - - if (read_header (fp, h) == 0) - { - return 0; - } - - /* length should never be longer than one BUFSIZ */ - if (h->len > BUFSIZ) - { - perror ("hlen"); - exit (1); - } - - *buf = malloc (h->len); - if (*buf == NULL) - { - perror ("malloc"); - exit (1); - } - - if (fread (*buf, 1, h->len, fp) != h->len) - { - fseek (fp, offset, SEEK_SET); - return 0; - } - return 1; + long offset; + + /* do this BEFORE header read, hlen bug */ + offset = ftell (fp); + + if (read_header (fp, h) == 0) + { + return 0; + } + + /* length should never be longer than one BUFSIZ */ + if (h->len > BUFSIZ) + { + perror ("hlen"); + exit (1); + } + + *buf = malloc (h->len); + if (*buf == NULL) + { + perror ("malloc"); + exit (1); + } + + if (fread (*buf, 1, h->len, fp) != h->len) + { + fseek (fp, offset, SEEK_SET); + return 0; + } + return 1; } int ttypread (FILE * fp, Header * h, char **buf, int pread) { - int counter = 0; - fd_set readfs; - struct timeval zerotime; - - zerotime.tv_sec = 0; - zerotime.tv_usec = 0; - - /* - * Read persistently just like tail -f. - */ - while (ttyread (fp, h, buf, 1) == 0) - { - struct timeval w = { 0, 100000 }; - select (0, NULL, NULL, NULL, &w); - clearerr (fp); - if (counter++ > (20 * 60 * 10)) - { - endwin (); - printf ("Exiting due to 20 minutes of inactivity.\n"); - exit (2); - return 0; - } - - - /* look for keypresses here. as good a place as any */ - FD_SET (STDIN_FILENO, &readfs); - select (1, &readfs, NULL, NULL, &zerotime); - if (FD_ISSET (0, &readfs)) - { /* a user hits a character? */ - char c; - read (STDIN_FILENO, &c, 1); /* drain the character */ - switch (c) - { - case 'q': - return 0; - break; - case 'm': - if (loggedin) - { - initncurses (); - domailuser (chosen_name); - endwin (); - ttyplay_main (ttyfile_local, 1, 0); - return 0; - } - break; - } - } - } - return 1; + int counter = 0; + fd_set readfs; + struct timeval zerotime; + + zerotime.tv_sec = 0; + zerotime.tv_usec = 0; + + /* + * Read persistently just like tail -f. + */ + while (ttyread (fp, h, buf, 1) == 0) + { + struct timeval w = { 0, 100000 }; + select (0, NULL, NULL, NULL, &w); + clearerr (fp); + if (counter++ > (20 * 60 * 10)) + { + endwin (); + printf ("Exiting due to 20 minutes of inactivity.\n"); + exit (2); + return 0; + } + + + /* look for keypresses here. as good a place as any */ + FD_SET (STDIN_FILENO, &readfs); + select (1, &readfs, NULL, NULL, &zerotime); + if (FD_ISSET (0, &readfs)) + { /* a user hits a character? */ + char c; + read (STDIN_FILENO, &c, 1); /* drain the character */ + switch (c) + { + case 'q': + return 0; + break; + case 'm': + if (loggedin) + { + initncurses (); + domailuser (chosen_name); + endwin (); + ttyplay_main (ttyfile_local, 1, 0); + return 0; + } + break; + } + } + } + return 1; } void ttywrite (char *buf, int len) { - int i; + int i; - if (bstripgfx) - { - for (i = 0; i < len; i++) - { - buf[i] = strip_gfx (buf[i]); - } - } + if (bstripgfx) + { + for (i = 0; i < len; i++) + { + buf[i] = strip_gfx (buf[i]); + } + } - fwrite (buf, 1, len, stdout); + fwrite (buf, 1, len, stdout); } void ttynowrite (char *buf, int len) { - /* do nothing */ + /* do nothing */ } void ttyplay (FILE * fp, double speed, ReadFunc read_func, - WriteFunc write_func, WaitFunc wait_func, off_t offset) + WriteFunc write_func, WaitFunc wait_func, off_t offset) { - int first_time = 1; - struct timeval prev; - - setbuf (stdout, NULL); - setbuf (fp, NULL); - - /* for dtype's attempt to get the last clrscr and playback from there */ - if (offset) - { - lseek (fileno (fp), offset, SEEK_SET); - } - - while (1) - { - char *buf; - Header h; - - if (read_func (fp, &h, &buf, 0) == 0) - { - break; - } - - if (!first_time) - { - speed = wait_func (prev, h.tv, speed); - } - first_time = 0; - - write_func (buf, h.len); - prev = h.tv; - free (buf); - } + int first_time = 1; + struct timeval prev; + + setbuf (stdout, NULL); + setbuf (fp, NULL); + + /* for dtype's attempt to get the last clrscr and playback from there */ + if (offset) + { + lseek (fileno (fp), offset, SEEK_SET); + } + + while (1) + { + char *buf; + Header h; + + if (read_func (fp, &h, &buf, 0) == 0) + { + break; + } + + if (!first_time) + { + speed = wait_func (prev, h.tv, speed); + } + first_time = 0; + + write_func (buf, h.len); + prev = h.tv; + free (buf); + } } void set_seek_offset_clrscr (FILE * fp) { - off_t raw_seek_offset = 0; - char *buf; - struct stat mystat; - int state = 0; - int i; - int bytesread; - - lseek (fileno (fp), 0, SEEK_SET); - fstat (fileno (fp), &mystat); - buf = malloc (mystat.st_size); - bytesread = read (fileno (fp), buf, mystat.st_size); - - /* one byte at at time sucks, but is a simple hack for the temp - * being to avoid looking for wraparounds */ - for (i = 0; i < bytesread; i++) - { - if (buf[i] == 0x1b) - { - state = 1; - } - else if ((buf[i] == 0x5b) && (state == 1)) - { - state = 2; - } - else if ((buf[i] == 0x32) && (state == 2)) - { - state = 3; - } - else if ((buf[i] == 0x4a) && ((state == 2) || (state == 3))) - { - state = 4; - } - else - { - state = 0; - } - - if (state == 4) - { - raw_seek_offset = i - 2; - } - } - - free (buf); - - /* now find last filepos that is less than seek offset */ - lseek (fileno (fp), 0, SEEK_SET); - while (1) - { - char *buf; - Header h; - - if (ttyread (fp, &h, &buf, 0) == 0) - { - break; - } - - if (lseek (fileno (fp), 0, SEEK_CUR) < raw_seek_offset) - { - seek_offset_clrscr = lseek (fileno (fp), 0, SEEK_CUR); - } - - free (buf); - } + off_t raw_seek_offset = 0; + char *buf; + struct stat mystat; + int state = 0; + int i; + int bytesread; + + lseek (fileno (fp), 0, SEEK_SET); + fstat (fileno (fp), &mystat); + buf = malloc (mystat.st_size); + bytesread = read (fileno (fp), buf, mystat.st_size); + + /* one byte at at time sucks, but is a simple hack for the temp + * being to avoid looking for wraparounds */ + for (i = 0; i < bytesread; i++) + { + if (buf[i] == 0x1b) + { + state = 1; + } + else if ((buf[i] == 0x5b) && (state == 1)) + { + state = 2; + } + else if ((buf[i] == 0x32) && (state == 2)) + { + state = 3; + } + else if ((buf[i] == 0x4a) && ((state == 2) || (state == 3))) + { + state = 4; + } + else + { + state = 0; + } + + if (state == 4) + { + raw_seek_offset = i - 2; + } + } + + free (buf); + + /* now find last filepos that is less than seek offset */ + lseek (fileno (fp), 0, SEEK_SET); + while (1) + { + char *buf; + Header h; + + if (ttyread (fp, &h, &buf, 0) == 0) + { + break; + } + + if (lseek (fileno (fp), 0, SEEK_CUR) < raw_seek_offset) + { + seek_offset_clrscr = lseek (fileno (fp), 0, SEEK_CUR); + } + + free (buf); + } } void ttyskipall (FILE * fp) { - /* - * Skip all records. - */ - ttyplay (fp, 0, ttyread, ttynowrite, ttynowait, 0); + /* + * Skip all records. + */ + ttyplay (fp, 0, ttyread, ttynowrite, ttynowait, 0); } void ttyplayback (FILE * fp, double speed, ReadFunc read_func, WaitFunc wait_func) { - ttyplay (fp, speed, ttyread, ttywrite, wait_func, 0); + ttyplay (fp, speed, ttyread, ttywrite, wait_func, 0); } void ttypeek (FILE * fp, double speed, ReadFunc read_func, WaitFunc wait_func) { - ttyskipall (fp); - set_seek_offset_clrscr (fp); - if (seek_offset_clrscr) - { - ttyplay (fp, 0, ttyread, ttywrite, ttynowait, seek_offset_clrscr); - } - ttyplay (fp, speed, ttypread, ttywrite, ttynowait, 0); + ttyskipall (fp); + set_seek_offset_clrscr (fp); + if (seek_offset_clrscr) + { + ttyplay (fp, 0, ttyread, ttywrite, ttynowait, seek_offset_clrscr); + } + ttyplay (fp, speed, ttypread, ttywrite, ttynowait, 0); } void usage (void) { - printf ("Usage: ttyplay [OPTION] [FILE]\n"); - printf (" -s SPEED Set speed to SPEED [1.0]\n"); - printf (" -n No wait mode\n"); - printf (" -p Peek another person's ttyrecord\n"); - exit (EXIT_FAILURE); + printf ("Usage: ttyplay [OPTION] [FILE]\n"); + printf (" -s SPEED Set speed to SPEED [1.0]\n"); + printf (" -n No wait mode\n"); + printf (" -p Peek another person's ttyrecord\n"); + exit (EXIT_FAILURE); } int ttyplay_main (char *ttyfile, int mode, int rstripgfx) { - double speed = 1.0; - ReadFunc read_func = ttyread; - WaitFunc wait_func = ttywait; - ProcessFunc process = ttyplayback; - FILE *input = stdin; - struct termios old, new; + double speed = 1.0; + ReadFunc read_func = ttyread; + WaitFunc wait_func = ttywait; + ProcessFunc process = ttyplayback; + FILE *input = stdin; + struct termios old, new; - ttyfile_local = ttyfile; + ttyfile_local = ttyfile; - /* strip graphics mode flag */ - bstripgfx = rstripgfx; - if (bstripgfx) - populate_gfx_array (DEC_GRAPHICS); + /* strip graphics mode flag */ + bstripgfx = rstripgfx; + if (bstripgfx) + populate_gfx_array (DEC_GRAPHICS); - seek_offset_clrscr = 0; + seek_offset_clrscr = 0; - if (mode == 1) - process = ttypeek; + if (mode == 1) + process = ttypeek; - input = efopen (ttyfile, "r"); + input = efopen (ttyfile, "r"); - tcgetattr (0, &old); /* Get current terminal state */ - new = old; /* Make a copy */ - new.c_lflag &= ~(ICANON | ECHO | ECHONL); /* unbuffered, no echo */ - tcsetattr (0, TCSANOW, &new); /* Make it current */ + tcgetattr (0, &old); /* Get current terminal state */ + new = old; /* Make a copy */ + new.c_lflag &= ~(ICANON | ECHO | ECHONL); /* unbuffered, no echo */ + tcsetattr (0, TCSANOW, &new); /* Make it current */ - process (input, speed, read_func, wait_func); - tcsetattr (0, TCSANOW, &old); /* Return terminal state */ + process (input, speed, read_func, wait_func); + tcsetattr (0, TCSANOW, &old); /* Return terminal state */ - return 0; + return 0; } diff --git a/ttyrec.c b/ttyrec.c index 0ac40c4..7b07634 100644 --- a/ttyrec.c +++ b/ttyrec.c @@ -101,65 +101,65 @@ int uflg; int ttyrec_main (char *username) { - void finish (); - char dirname[100]; - - snprintf (dirname, 100, "%s%s", LOC_TTYRECDIR, username); - - if (access (dirname, F_OK) != 0) - mkdir (dirname, 0755); - - snprintf (dirname, 100, "%s%s/%s", LOC_TTYRECDIR, username, - ttyrec_filename); - - if ((fscript = fopen (dirname, "w")) == NULL) - { - perror (dirname); - fail (); - } - setbuf (fscript, NULL); - - fixtty (); - - (void) signal (SIGCHLD, finish); - child = fork (); - if (child < 0) - { - perror ("fork"); - fail (); - } - if (child == 0) - { - subchild = child = fork (); - if (child < 0) - { - perror ("fork"); - fail (); - } - if (child) - { - close (slave); - pid_game = child; - dooutput (); - } - else - doshell (username); - } - doinput (); - - return 0; + void finish (); + char dirname[100]; + + snprintf (dirname, 100, "%s%s", LOC_TTYRECDIR, username); + + if (access (dirname, F_OK) != 0) + mkdir (dirname, 0755); + + snprintf (dirname, 100, "%s%s/%s", LOC_TTYRECDIR, username, + ttyrec_filename); + + if ((fscript = fopen (dirname, "w")) == NULL) + { + perror (dirname); + fail (); + } + setbuf (fscript, NULL); + + fixtty (); + + (void) signal (SIGCHLD, finish); + child = fork (); + if (child < 0) + { + perror ("fork"); + fail (); + } + if (child == 0) + { + subchild = child = fork (); + if (child < 0) + { + perror ("fork"); + fail (); + } + if (child) + { + close (slave); + pid_game = child; + dooutput (); + } + else + doshell (username); + } + doinput (); + + return 0; } void doinput () { - register int cc; - char ibuf[BUFSIZ]; + register int cc; + char ibuf[BUFSIZ]; - (void) fclose (fscript); - while ((cc = read (0, ibuf, BUFSIZ)) > 0) - (void) write (master, ibuf, cc); - done (); + (void) fclose (fscript); + while ((cc = read (0, ibuf, BUFSIZ)) > 0) + (void) write (master, ibuf, cc); + done (); } #include @@ -168,221 +168,221 @@ void finish () { #if defined(SVR4) - int status; -#else /* !SVR4 */ - union wait status; + int status; +#else /* !SVR4 */ + union wait status; #endif /* !SVR4 */ - register int pid; - register int die = 0; + register int pid; + register int die = 0; - while ((pid = wait3 ((int *) &status, WNOHANG, 0)) > 0) - if (pid == child) - die = 1; + while ((pid = wait3 ((int *) &status, WNOHANG, 0)) > 0) + if (pid == child) + die = 1; - if (die) - done (); + if (die) + done (); } struct linebuf { - char str[BUFSIZ + 1]; /* + 1 for an additional NULL character. */ - int len; + char str[BUFSIZ + 1]; /* + 1 for an additional NULL character. */ + int len; }; void check_line (const char *line) { - static int uuencode_mode = 0; - static FILE *uudecode; - - if (uuencode_mode == 1) - { - fprintf (uudecode, "%s", line); - if (strcmp (line, "end\n") == 0) - { - pclose (uudecode); - uuencode_mode = 0; - } - } - else - { - int dummy; - char dummy2[BUFSIZ]; - if (sscanf (line, "begin %o %s", &dummy, dummy2) == 2) - { - /* - * uuencode line found! - */ - uudecode = popen ("uudecode", "w"); - fprintf (uudecode, "%s", line); - uuencode_mode = 1; - } - } + static int uuencode_mode = 0; + static FILE *uudecode; + + if (uuencode_mode == 1) + { + fprintf (uudecode, "%s", line); + if (strcmp (line, "end\n") == 0) + { + pclose (uudecode); + uuencode_mode = 0; + } + } + else + { + int dummy; + char dummy2[BUFSIZ]; + if (sscanf (line, "begin %o %s", &dummy, dummy2) == 2) + { + /* + * uuencode line found! + */ + uudecode = popen ("uudecode", "w"); + fprintf (uudecode, "%s", line); + uuencode_mode = 1; + } + } } void check_output (const char *str, int len) { - static struct linebuf lbuf = { "", 0 }; - int i; - - for (i = 0; i < len; i++) - { - if (lbuf.len < BUFSIZ) - { - lbuf.str[lbuf.len] = str[i]; - if (lbuf.str[lbuf.len] == '\r') - { - lbuf.str[lbuf.len] = '\n'; - } - lbuf.len++; - if (lbuf.str[lbuf.len - 1] == '\n') - { - if (lbuf.len > 1) - { /* skip a blank line. */ - lbuf.str[lbuf.len] = '\0'; - check_line (lbuf.str); - } - lbuf.len = 0; - } - } - else - { /* buffer overflow */ - lbuf.len = 0; - } - } + static struct linebuf lbuf = { "", 0 }; + int i; + + for (i = 0; i < len; i++) + { + if (lbuf.len < BUFSIZ) + { + lbuf.str[lbuf.len] = str[i]; + if (lbuf.str[lbuf.len] == '\r') + { + lbuf.str[lbuf.len] = '\n'; + } + lbuf.len++; + if (lbuf.str[lbuf.len - 1] == '\n') + { + if (lbuf.len > 1) + { /* skip a blank line. */ + lbuf.str[lbuf.len] = '\0'; + check_line (lbuf.str); + } + lbuf.len = 0; + } + } + else + { /* buffer overflow */ + lbuf.len = 0; + } + } } void dooutput () { - int cc; - time_t tvec, time (); - char obuf[BUFSIZ], *ctime (); - - setbuf (stdout, NULL); - (void) close (0); - tvec = time ((time_t *) NULL); - for (;;) - { - Header h; - - cc = read (master, obuf, BUFSIZ); - if (cc <= 0) - break; - if (uflg) - check_output (obuf, cc); - h.len = cc; - gettimeofday (&h.tv, NULL); - (void) write (1, obuf, cc); - (void) write_header (fscript, &h); - (void) fwrite (obuf, 1, cc, fscript); - } - done (); + int cc; + time_t tvec, time (); + char obuf[BUFSIZ], *ctime (); + + setbuf (stdout, NULL); + (void) close (0); + tvec = time ((time_t *) NULL); + for (;;) + { + Header h; + + cc = read (master, obuf, BUFSIZ); + if (cc <= 0) + break; + if (uflg) + check_output (obuf, cc); + h.len = cc; + gettimeofday (&h.tv, NULL); + (void) write (1, obuf, cc); + (void) write_header (fscript, &h); + (void) fwrite (obuf, 1, cc, fscript); + } + done (); } void doshell (char *username) { - char *argv1 = LOC_NETHACK; - char *argv2 = "-u"; - char *myargv[10]; - - getslave (); - (void) close (master); - (void) fclose (fscript); - (void) dup2 (slave, 0); - (void) dup2 (slave, 1); - (void) dup2 (slave, 2); - (void) close (slave); - - myargv[0] = argv1; - myargv[1] = argv2; - myargv[2] = username; - myargv[3] = 0; - - execvp (LOC_NETHACK, myargv); - - fail (); + char *argv1 = LOC_NETHACK; + char *argv2 = "-u"; + char *myargv[10]; + + getslave (); + (void) close (master); + (void) fclose (fscript); + (void) dup2 (slave, 0); + (void) dup2 (slave, 1); + (void) dup2 (slave, 2); + (void) close (slave); + + myargv[0] = argv1; + myargv[1] = argv2; + myargv[2] = username; + myargv[3] = 0; + + execvp (LOC_NETHACK, myargv); + + fail (); } void fixtty () { - struct termios rtt; - - rtt = tt; - rtt.c_iflag = 0; - rtt.c_lflag &= ~(ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK | ECHONL); - rtt.c_oflag = OPOST; - rtt.c_cc[VINTR] = CDEL; - rtt.c_cc[VQUIT] = CDEL; - rtt.c_cc[VERASE] = CDEL; - rtt.c_cc[VKILL] = CDEL; - rtt.c_cc[VEOF] = 1; - rtt.c_cc[VEOL] = 0; - (void) tcsetattr (0, TCSAFLUSH, &rtt); + struct termios rtt; + + rtt = tt; + rtt.c_iflag = 0; + rtt.c_lflag &= ~(ISIG | ICANON | XCASE | ECHO | ECHOE | ECHOK | ECHONL); + rtt.c_oflag = OPOST; + rtt.c_cc[VINTR] = CDEL; + rtt.c_cc[VQUIT] = CDEL; + rtt.c_cc[VERASE] = CDEL; + rtt.c_cc[VKILL] = CDEL; + rtt.c_cc[VEOF] = 1; + rtt.c_cc[VEOL] = 0; + (void) tcsetattr (0, TCSAFLUSH, &rtt); } void fail () { - (void) kill (0, SIGTERM); - done (); + (void) kill (0, SIGTERM); + done (); } void done () { - time_t tvec, time (); - char *ctime (); - - if (subchild) - { - tvec = time ((time_t *) NULL); - (void) fclose (fscript); - (void) close (master); - } - else - { - (void) tcsetattr (0, TCSAFLUSH, &tt); - } - exit (0); + time_t tvec, time (); + char *ctime (); + + if (subchild) + { + tvec = time ((time_t *) NULL); + (void) fclose (fscript); + (void) close (master); + } + else + { + (void) tcsetattr (0, TCSAFLUSH, &tt); + } + exit (0); } void getslave () { - (void) setsid (); - /* grantpt( master); - unlockpt(master); - if ((slave = open((const char *)ptsname(master), O_RDWR)) < 0) { - perror((const char *)ptsname(master)); - fail(); - perror("open(fd, O_RDWR)"); - fail(); - } */ - if (isastream (slave)) - { - if (ioctl (slave, I_PUSH, "ptem") < 0) - { - perror ("ioctl(fd, I_PUSH, ptem)"); - fail (); - } - if (ioctl (slave, I_PUSH, "ldterm") < 0) - { - perror ("ioctl(fd, I_PUSH, ldterm)"); - fail (); - } + (void) setsid (); + /* grantpt( master); + unlockpt(master); + if ((slave = open((const char *)ptsname(master), O_RDWR)) < 0) { + perror((const char *)ptsname(master)); + fail(); + perror("open(fd, O_RDWR)"); + fail(); + } */ + if (isastream (slave)) + { + if (ioctl (slave, I_PUSH, "ptem") < 0) + { + perror ("ioctl(fd, I_PUSH, ptem)"); + fail (); + } + if (ioctl (slave, I_PUSH, "ldterm") < 0) + { + perror ("ioctl(fd, I_PUSH, ldterm)"); + fail (); + } #ifndef _HPUX_SOURCE - if (ioctl (slave, I_PUSH, "ttcompat") < 0) - { - perror ("ioctl(fd, I_PUSH, ttcompat)"); - fail (); - } + if (ioctl (slave, I_PUSH, "ttcompat") < 0) + { + perror ("ioctl(fd, I_PUSH, ttcompat)"); + fail (); + } #endif - (void) ioctl (0, TIOCGWINSZ, (char *) &win); - } + (void) ioctl (0, TIOCGWINSZ, (char *) &win); + } } diff --git a/ttyrec.h b/ttyrec.h index b728b7f..c8c623a 100644 --- a/ttyrec.h +++ b/ttyrec.h @@ -6,8 +6,8 @@ typedef struct header { - struct timeval tv; - size_t len; + struct timeval tv; + size_t len; } Header; diff --git a/virus.c b/virus.c index d8f35f3..415e4d4 100644 --- a/virus.c +++ b/virus.c @@ -47,15 +47,15 @@ char *vi_Version = "0.0.2+dgamelaunch 1.1.2"; //---- Feature -------------- Bytes to immplement #define vi_main vi_main -#define BB_FEATURE_VI_COLON // 4288 -#define BB_FEATURE_VI_YANKMARK // 1408 -#define BB_FEATURE_VI_SEARCH // 1088 +#define BB_FEATURE_VI_COLON // 4288 +#define BB_FEATURE_VI_YANKMARK // 1408 +#define BB_FEATURE_VI_SEARCH // 1088 // #define BB_FEATURE_VI_USE_SIGNALS // 1056 -#define BB_FEATURE_VI_DOT_CMD // 576 -#define BB_FEATURE_VI_READONLY // 128 -#define BB_FEATURE_VI_SETOPTS // 576 -#define BB_FEATURE_VI_SET // 224 -#define BB_FEATURE_VI_WIN_RESIZE // 256 WIN_RESIZE +#define BB_FEATURE_VI_DOT_CMD // 576 +#define BB_FEATURE_VI_READONLY // 128 +#define BB_FEATURE_VI_SETOPTS // 576 +#define BB_FEATURE_VI_SET // 224 +#define BB_FEATURE_VI_WIN_RESIZE // 256 WIN_RESIZE // To test editor using CRASHME: // vi -C filename // To stop testing, wait until all to text[] is deleted, or @@ -91,89 +91,89 @@ char *vi_Version = "0.0.2+dgamelaunch 1.1.2"; #define MAX_SCR_COLS BUFSIZ // Misc. non-Ascii keys that report an escape sequence -#define VI_K_UP 128 // cursor key Up -#define VI_K_DOWN 129 // cursor key Down -#define VI_K_RIGHT 130 // Cursor Key Right -#define VI_K_LEFT 131 // cursor key Left -#define VI_K_HOME 132 // Cursor Key Home -#define VI_K_END 133 // Cursor Key End -#define VI_K_INSERT 134 // Cursor Key Insert -#define VI_K_PAGEUP 135 // Cursor Key Page Up -#define VI_K_PAGEDOWN 136 // Cursor Key Page Down -#define VI_K_FUN1 137 // Function Key F1 -#define VI_K_FUN2 138 // Function Key F2 -#define VI_K_FUN3 139 // Function Key F3 -#define VI_K_FUN4 140 // Function Key F4 -#define VI_K_FUN5 141 // Function Key F5 -#define VI_K_FUN6 142 // Function Key F6 -#define VI_K_FUN7 143 // Function Key F7 -#define VI_K_FUN8 144 // Function Key F8 -#define VI_K_FUN9 145 // Function Key F9 -#define VI_K_FUN10 146 // Function Key F10 -#define VI_K_FUN11 147 // Function Key F11 -#define VI_K_FUN12 148 // Function Key F12 +#define VI_K_UP 128 // cursor key Up +#define VI_K_DOWN 129 // cursor key Down +#define VI_K_RIGHT 130 // Cursor Key Right +#define VI_K_LEFT 131 // cursor key Left +#define VI_K_HOME 132 // Cursor Key Home +#define VI_K_END 133 // Cursor Key End +#define VI_K_INSERT 134 // Cursor Key Insert +#define VI_K_PAGEUP 135 // Cursor Key Page Up +#define VI_K_PAGEDOWN 136 // Cursor Key Page Down +#define VI_K_FUN1 137 // Function Key F1 +#define VI_K_FUN2 138 // Function Key F2 +#define VI_K_FUN3 139 // Function Key F3 +#define VI_K_FUN4 140 // Function Key F4 +#define VI_K_FUN5 141 // Function Key F5 +#define VI_K_FUN6 142 // Function Key F6 +#define VI_K_FUN7 143 // Function Key F7 +#define VI_K_FUN8 144 // Function Key F8 +#define VI_K_FUN9 145 // Function Key F9 +#define VI_K_FUN10 146 // Function Key F10 +#define VI_K_FUN11 147 // Function Key F11 +#define VI_K_FUN12 148 // Function Key F12 static const int YANKONLY = FALSE; static const int YANKDEL = TRUE; -static const int FORWARD = 1; // code depends on "1" for array index -static const int BACK = -1; // code depends on "-1" for array index -static const int LIMITED = 0; // how much of text[] in char_search -static const int FULL = 1; // how much of text[] in char_search +static const int FORWARD = 1; // code depends on "1" for array index +static const int BACK = -1; // code depends on "-1" for array index +static const int LIMITED = 0; // how much of text[] in char_search +static const int FULL = 1; // how much of text[] in char_search -static const int S_BEFORE_WS = 1; // used in skip_thing() for moving "dot" -static const int S_TO_WS = 2; // used in skip_thing() for moving "dot" -static const int S_OVER_WS = 3; // used in skip_thing() for moving "dot" -static const int S_END_PUNCT = 4; // used in skip_thing() for moving "dot" -static const int S_END_ALNUM = 5; // used in skip_thing() for moving "dot" +static const int S_BEFORE_WS = 1; // used in skip_thing() for moving "dot" +static const int S_TO_WS = 2; // used in skip_thing() for moving "dot" +static const int S_OVER_WS = 3; // used in skip_thing() for moving "dot" +static const int S_END_PUNCT = 4; // used in skip_thing() for moving "dot" +static const int S_END_ALNUM = 5; // used in skip_thing() for moving "dot" typedef unsigned char Byte; -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 -static int screensize; // and its size -static Byte *screenbegin; // index into text[], of top line on the screen -static Byte *dot; // where all the action takes place +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 +static int screensize; // and its size +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 struct termios term_orig, term_vi; // remember what the cooked mode was #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR -static int last_row; // where the cursor was last moved to +static int last_row; // where the cursor was last moved to #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ #ifdef BB_FEATURE_VI_USE_SIGNALS -static jmp_buf restart; // catch_sig() +static jmp_buf restart; // catch_sig() #endif /* BB_FEATURE_VI_USE_SIGNALS */ #ifdef BB_FEATURE_VI_WIN_RESIZE -static struct winsize winsize; // remember the window size +static struct winsize winsize; // remember the window size #endif /* BB_FEATURE_VI_WIN_RESIZE */ #ifdef BB_FEATURE_VI_DOT_CMD -static int adding2q; // are we currently adding user input to q -static Byte *last_modifying_cmd; // last modifying cmd for "." -static Byte *ioq, *ioq_start; // pointer to string for get_one_char to "read" +static int adding2q; // are we currently adding user input to q +static Byte *last_modifying_cmd; // last modifying cmd for "." +static Byte *ioq, *ioq_start; // pointer to string for get_one_char to "read" #endif /* BB_FEATURE_VI_DOT_CMD */ #if defined(BB_FEATURE_VI_DOT_CMD) || defined(BB_FEATURE_VI_YANKMARK) -static Byte *modifying_cmds; // cmds that modify text[] +static Byte *modifying_cmds; // cmds that modify text[] #endif /* BB_FEATURE_VI_DOT_CMD || BB_FEATURE_VI_YANKMARK */ #ifdef BB_FEATURE_VI_READONLY static int vi_readonly, readonly; @@ -184,116 +184,116 @@ static int showmatch; static int ignorecase; #endif /* BB_FEATURE_VI_SETOPTS */ #ifdef BB_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" -static Byte *mark[28]; // user marks points somewhere in text[]- a-z and previous context '' +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" +static Byte *mark[28]; // user marks points somewhere in text[]- a-z and previous context '' static Byte *context_start, *context_end; #endif /* BB_FEATURE_VI_YANKMARK */ #ifdef BB_FEATURE_VI_SEARCH -static Byte *last_search_pattern; // last pattern from a '/' or '?' search +static Byte *last_search_pattern; // last pattern from a '/' or '?' search #endif /* BB_FEATURE_VI_SEARCH */ -static void edit_file (Byte *); // edit one file -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 -static 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 -static int count_lines (Byte *, Byte *); // count line from start to stop -static Byte *find_line (int); // find begining of line #li -static Byte *move_to_col (Byte *, int); // move "p" to column l -static int isblnk (Byte); // is the char a blank or tab -static void dot_left (void); // move dot left- dont leave line -static void dot_right (void); // move dot right- dont leave line -static void dot_begin (void); // move dot to B-o-l -static void dot_end (void); // move dot to E-o-l -static void dot_next (void); // move dot to next line B-o-l -static void dot_prev (void); // move dot to prev line B-o-l -static void dot_scroll (int, int); // move the screen up or down -static void dot_skip_over_ws (void); // move dot pat WS -static void dot_delete (void); // delete the char at 'dot' -static Byte *bound_dot (Byte *); // make sure text[0] <= P < "end" -static Byte *new_screen (int, int); // malloc virtual screen memory -static Byte *new_text (int); // malloc memory for text[] buffer -static Byte *char_insert (Byte *, Byte); // insert the char c at 'p' -static Byte *stupid_insert (Byte *, Byte); // stupidly insert the char c at 'p' -static Byte find_range (Byte **, Byte **, Byte); // return pointers for an object -static int st_test (Byte *, int, int, Byte *); // helper for skip_thing() -static Byte *skip_thing (Byte *, int, int, int); // skip some object -static Byte *find_pair (Byte *, Byte); // find matching pair () [] {} -static Byte *text_hole_delete (Byte *, Byte *); // at "p", delete a 'size' byte hole -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 -static 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 void edit_file (Byte *); // edit one file +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 +static 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 +static int count_lines (Byte *, Byte *); // count line from start to stop +static Byte *find_line (int); // find begining of line #li +static Byte *move_to_col (Byte *, int); // move "p" to column l +static int isblnk (Byte); // is the char a blank or tab +static void dot_left (void); // move dot left- dont leave line +static void dot_right (void); // move dot right- dont leave line +static void dot_begin (void); // move dot to B-o-l +static void dot_end (void); // move dot to E-o-l +static void dot_next (void); // move dot to next line B-o-l +static void dot_prev (void); // move dot to prev line B-o-l +static void dot_scroll (int, int); // move the screen up or down +static void dot_skip_over_ws (void); // move dot pat WS +static void dot_delete (void); // delete the char at 'dot' +static Byte *bound_dot (Byte *); // make sure text[0] <= P < "end" +static Byte *new_screen (int, int); // malloc virtual screen memory +static Byte *new_text (int); // malloc memory for text[] buffer +static Byte *char_insert (Byte *, Byte); // insert the char c at 'p' +static Byte *stupid_insert (Byte *, Byte); // stupidly insert the char c at 'p' +static Byte find_range (Byte **, Byte **, Byte); // return pointers for an object +static int st_test (Byte *, int, int, Byte *); // helper for skip_thing() +static Byte *skip_thing (Byte *, int, int, int); // skip some object +static Byte *find_pair (Byte *, Byte); // find matching pair () [] {} +static Byte *text_hole_delete (Byte *, Byte *); // at "p", delete a 'size' byte hole +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 +static 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_insert (Byte *, Byte *, int); static int file_write (Byte *, Byte *, Byte *); static void place_cursor (int, int, int); static void screen_erase (); static void clear_to_eol (void); 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 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 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 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 refresh (int); // update the terminal from screen[] #ifdef BB_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" +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" #endif /* BB_FEATURE_VI_SEARCH */ #ifdef BB_FEATURE_VI_COLON static void Hit_Return (void); -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 +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 /* BB_FEATURE_VI_COLON */ -static Byte *get_input_line (Byte *); // get input line- use "status line" +static Byte *get_input_line (Byte *); // get input line- use "status line" #ifdef BB_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 core_sig (int); // catch a core dump signal +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 core_sig (int); // catch a core dump signal #endif /* BB_FEATURE_VI_USE_SIGNALS */ #ifdef BB_FEATURE_VI_DOT_CMD -static void start_new_cmd_q (Byte); // new queue for command -static void end_cmd_q (); // stop saving input chars -#else /* BB_FEATURE_VI_DOT_CMD */ +static void start_new_cmd_q (Byte); // new queue for command +static void end_cmd_q (); // stop saving input chars +#else /* BB_FEATURE_VI_DOT_CMD */ #define end_cmd_q() #endif /* BB_FEATURE_VI_DOT_CMD */ #ifdef BB_FEATURE_VI_WIN_RESIZE -static void window_size_get (int); // find out what size the window is +static void window_size_get (int); // find out what size the window is #endif /* BB_FEATURE_VI_WIN_RESIZE */ #ifdef BB_FEATURE_VI_SETOPTS -static void showmatching (Byte *); // show the matching pair () [] {} +static void showmatching (Byte *); // show the matching pair () [] {} #endif /* BB_FEATURE_VI_SETOPTS */ #if defined(BB_FEATURE_VI_YANKMARK) || defined(BB_FEATURE_VI_COLON) || defined(BB_FEATURE_VI_CRASHME) -static Byte *string_insert (Byte *, Byte *); // insert the string at 'p' +static Byte *string_insert (Byte *, Byte *); // insert the string at 'p' #endif /* BB_FEATURE_VI_YANKMARK || BB_FEATURE_VI_COLON || BB_FEATURE_VI_CRASHME */ #ifdef BB_FEATURE_VI_YANKMARK -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 -static Byte *swap_context (Byte *); // goto new context for '' command +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 +static Byte *swap_context (Byte *); // goto new context for '' command #endif /* BB_FEATURE_VI_YANKMARK */ #ifdef BB_FEATURE_VI_CRASHME static void crash_dummy (); @@ -306,474 +306,474 @@ extern int vi_main (int argc, char **argv) { #ifdef BB_FEATURE_VI_YANKMARK - int i; + int i; #endif /* BB_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 + 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 #ifdef BB_FEATURE_VI_CRASHME - (void) srand ((long) getpid ()); + (void) srand ((long) getpid ()); #endif /* BB_FEATURE_VI_CRASHME */ - status_buffer = (Byte *) malloc (200); // hold messages to user + status_buffer = (Byte *) malloc (200); // hold messages to user #ifdef BB_FEATURE_VI_READONLY - vi_readonly = readonly = FALSE; - if (strncmp (argv[0], "view", 4) == 0) - { - readonly = TRUE; - vi_readonly = TRUE; - } + vi_readonly = readonly = FALSE; + if (strncmp (argv[0], "view", 4) == 0) + { + readonly = TRUE; + vi_readonly = TRUE; + } #endif /* BB_FEATURE_VI_READONLY */ #ifdef BB_FEATURE_VI_SETOPTS - autoindent = 1; - ignorecase = 1; - showmatch = 1; + autoindent = 1; + ignorecase = 1; + showmatch = 1; #endif /* BB_FEATURE_VI_SETOPTS */ #ifdef BB_FEATURE_VI_YANKMARK - for (i = 0; i < 28; i++) - { - reg[i] = 0; - } // init the yank regs + for (i = 0; i < 28; i++) + { + reg[i] = 0; + } // init the yank regs #endif /* BB_FEATURE_VI_YANKMARK */ #ifdef BB_FEATURE_VI_DOT_CMD - modifying_cmds = (Byte *) "aAcCdDiIJoOpPrRsxX<>~"; // cmds modifying text[] + modifying_cmds = (Byte *) "aAcCdDiIJoOpPrRsxX<>~"; // cmds modifying text[] #endif /* BB_FEATURE_VI_DOT_CMD */ - if (argc >= 2) - { - cfn = (Byte *) strdup (argv[1]); - edit_file (cfn); - } - else - { - fprintf (stderr, "%s: no file to edit, bailing out\n", argv[0]); - exit (1); - } + if (argc >= 2) + { + cfn = (Byte *) strdup (argv[1]); + edit_file (cfn); + } + else + { + fprintf (stderr, "%s: no file to edit, bailing out\n", argv[0]); + exit (1); + } - //----------------------------------------------------------- + //----------------------------------------------------------- - /* set these back to defaults. this was the infamous screen resize crash bug */ - signal (SIGWINCH, SIG_DFL); - signal (SIGTSTP, SIG_DFL); + /* set these back to defaults. this was the infamous screen resize crash bug */ + signal (SIGWINCH, SIG_DFL); + signal (SIGTSTP, SIG_DFL); - return (0); + return (0); } static void edit_file (Byte * fn) { - char c; - int cnt, size, ch; + char c; + int cnt, size, ch; #ifdef BB_FEATURE_VI_USE_SIGNALS - char *msg; - int sig; + char *msg; + int sig; #endif /* BB_FEATURE_VI_USE_SIGNALS */ #ifdef BB_FEATURE_VI_YANKMARK - static Byte *cur_line; + static Byte *cur_line; #endif /* BB_FEATURE_VI_YANKMARK */ - rawmode (); - rows = 24; - columns = 80; - ch = -1; + rawmode (); + rows = 24; + columns = 80; + ch = -1; #ifdef BB_FEATURE_VI_WIN_RESIZE - window_size_get (0); + window_size_get (0); #endif /* BB_FEATURE_VI_WIN_RESIZE */ - new_screen (rows, columns); // get memory for virtual screen - - cnt = file_size (fn); // file size - size = 2 * cnt; // 200% of file size - new_text (size); // get a text[] buffer - screenbegin = dot = end = text; - if (fn != 0) - { - ch = file_insert (fn, text, cnt); - } - if (ch < 1) - { - (void) char_insert (text, '\n'); // start empty buf with dummy line - } - file_modified = FALSE; + new_screen (rows, columns); // get memory for virtual screen + + cnt = file_size (fn); // file size + size = 2 * cnt; // 200% of file size + new_text (size); // get a text[] buffer + screenbegin = dot = end = text; + if (fn != 0) + { + ch = file_insert (fn, text, cnt); + } + if (ch < 1) + { + (void) char_insert (text, '\n'); // start empty buf with dummy line + } + file_modified = FALSE; #ifdef BB_FEATURE_VI_YANKMARK - YDreg = 26; // default Yank/Delete reg - Ureg = 27; // hold orig line for "U" cmd - for (cnt = 0; cnt < 28; cnt++) - { - mark[cnt] = 0; - } // init the marks - mark[26] = mark[27] = text; // init "previous context" + YDreg = 26; // default Yank/Delete reg + Ureg = 27; // hold orig line for "U" cmd + for (cnt = 0; cnt < 28; cnt++) + { + mark[cnt] = 0; + } // init the marks + mark[26] = mark[27] = text; // init "previous context" #endif /* BB_FEATURE_VI_YANKMARK */ - err_method = 1; // flash - last_forward_char = last_input_char = '\0'; - crow = 0; - ccol = 0; - edit_status (); + err_method = 1; // flash + last_forward_char = last_input_char = '\0'; + crow = 0; + ccol = 0; + edit_status (); #ifdef BB_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); + 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); + signal (SIGSYS, core_sig); #endif - signal (SIGWINCH, winch_sig); - signal (SIGTSTP, suspend_sig); - sig = setjmp (restart); - if (sig != 0) - { - msg = ""; - if (sig == SIGWINCH) - msg = "(window resize)"; - if (sig == SIGHUP) - msg = "(hangup)"; - if (sig == SIGINT) - msg = "(interrupt)"; - if (sig == SIGTERM) - msg = "(terminate)"; - if (sig == SIGBUS) - msg = "(bus error)"; - if (sig == SIGSEGV) - msg = "(I tried to touch invalid memory)"; - if (sig == SIGALRM) - msg = "(alarm)"; - - psbs ("-- caught signal %d %s--", sig, msg); - screenbegin = dot = text; - } + signal (SIGWINCH, winch_sig); + signal (SIGTSTP, suspend_sig); + sig = setjmp (restart); + if (sig != 0) + { + msg = ""; + if (sig == SIGWINCH) + msg = "(window resize)"; + if (sig == SIGHUP) + msg = "(hangup)"; + if (sig == SIGINT) + msg = "(interrupt)"; + if (sig == SIGTERM) + msg = "(terminate)"; + if (sig == SIGBUS) + msg = "(bus error)"; + if (sig == SIGSEGV) + msg = "(I tried to touch invalid memory)"; + if (sig == SIGALRM) + msg = "(alarm)"; + + psbs ("-- caught signal %d %s--", sig, msg); + screenbegin = dot = text; + } #endif /* BB_FEATURE_VI_USE_SIGNALS */ - editing = 1; - cmd_mode = 0; // 0=command 1=insert 2='R'eplace - cmdcnt = 0; - tabstop = 8; - offset = 0; // no horizontal offset - c = '\0'; + editing = 1; + cmd_mode = 0; // 0=command 1=insert 2='R'eplace + cmdcnt = 0; + tabstop = 8; + offset = 0; // no horizontal offset + c = '\0'; #ifdef BB_FEATURE_VI_DOT_CMD - if (last_modifying_cmd != 0) - free (last_modifying_cmd); - if (ioq_start != NULL) - free (ioq_start); - ioq = ioq_start = last_modifying_cmd = 0; - adding2q = 0; + if (last_modifying_cmd != 0) + free (last_modifying_cmd); + if (ioq_start != NULL) + free (ioq_start); + ioq = ioq_start = last_modifying_cmd = 0; + adding2q = 0; #endif /* BB_FEATURE_VI_DOT_CMD */ - redraw (FALSE); // dont force every col re-draw - show_status_line (); + redraw (FALSE); // dont force every col re-draw + show_status_line (); - //------This is the main Vi cmd handling loop ----------------------- - while (editing > 0) - { + //------This is the main Vi cmd handling loop ----------------------- + while (editing > 0) + { #ifdef BB_FEATURE_VI_CRASHME - if (crashme > 0) - { - if ((end - text) > 1) - { - crash_dummy (); // generate a random command - } - else - { - crashme = 0; - dot = string_insert (text, (Byte *) "\n\n##### Ran out of text to work on. #####\n\n"); // insert the string - refresh (FALSE); - } - } + if (crashme > 0) + { + if ((end - text) > 1) + { + crash_dummy (); // generate a random command + } + else + { + crashme = 0; + dot = string_insert (text, (Byte *) "\n\n##### Ran out of text to work on. #####\n\n"); // insert the string + refresh (FALSE); + } + } #endif /* BB_FEATURE_VI_CRASHME */ - last_input_char = c = get_one_char (); // get a cmd from user + last_input_char = c = get_one_char (); // get a cmd from user #ifdef BB_FEATURE_VI_YANKMARK - // save a copy of the current line- for the 'U" command - if (begin_line (dot) != cur_line) - { - cur_line = begin_line (dot); - text_yank (begin_line (dot), end_line (dot), Ureg); - } + // save a copy of the current line- for the 'U" command + if (begin_line (dot) != cur_line) + { + cur_line = begin_line (dot); + text_yank (begin_line (dot), end_line (dot), Ureg); + } #endif /* BB_FEATURE_VI_YANKMARK */ #ifdef BB_FEATURE_VI_DOT_CMD - // These are commands that change text[]. - // Remember the input for the "." command - if (!adding2q && ioq_start == 0 - && strchr ((char *) modifying_cmds, c) != NULL) - { - start_new_cmd_q (c); - } + // These are commands that change text[]. + // Remember the input for the "." command + if (!adding2q && ioq_start == 0 + && strchr ((char *) modifying_cmds, c) != NULL) + { + start_new_cmd_q (c); + } #endif /* BB_FEATURE_VI_DOT_CMD */ - do_cmd (c); // execute the user command - // - // poll to see if there is input already waiting. if we are - // not able to display output fast enough to keep up, skip - // the display update until we catch up with input. - if (mysleep (0) == 0) - { - // no input pending- so update output - refresh (FALSE); - show_status_line (); - } + do_cmd (c); // execute the user command + // + // poll to see if there is input already waiting. if we are + // not able to display output fast enough to keep up, skip + // the display update until we catch up with input. + if (mysleep (0) == 0) + { + // no input pending- so update output + refresh (FALSE); + show_status_line (); + } #ifdef BB_FEATURE_VI_CRASHME - if (crashme > 0) - crash_test (); // test editor variables + if (crashme > 0) + crash_test (); // test editor variables #endif /* BB_FEATURE_VI_CRASHME */ - } - //------------------------------------------------------------------- + } + //------------------------------------------------------------------- - place_cursor (rows, 0, FALSE); // go to bottom of screen - clear_to_eol (); // Erase to end of line - cookmode (); + place_cursor (rows, 0, FALSE); // go to bottom of screen + clear_to_eol (); // Erase to end of line + cookmode (); } static Byte readbuffer[BUFSIZ]; #ifdef BB_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 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" + "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", + "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", + "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; + 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"; + // "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; + // 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"); - } + 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 + 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 textend) - { - strcat ((char *) msg, "end>textend "); - } - if (dot < text) - { - strcat ((char *) msg, "dot end) - { - strcat ((char *) msg, "dot>end "); - } - if (screenbegin < text) - { - strcat ((char *) msg, "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; + static time_t oldtim; + time_t tim; + char d[2], buf[BUFSIZ], msg[BUFSIZ]; + + msg[0] = '\0'; + if (end < text) + { + strcat ((char *) msg, "end textend) + { + strcat ((char *) msg, "end>textend "); + } + if (dot < text) + { + strcat ((char *) msg, "dot end) + { + strcat ((char *) msg, "dot>end "); + } + if (screenbegin < text) + { + strcat ((char *) msg, "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 /* BB_FEATURE_VI_CRASHME */ @@ -802,1661 +802,1661 @@ crash_test () static void do_cmd (Byte c) { - Byte c1, *p, *q, *msg, buf[9], *save_dot; - int cnt, i, j, dir, yf; - - c1 = c; // quiet the compiler - cnt = yf = dir = 0; // quiet the compiler - p = q = save_dot = msg = buf; // quiet the compiler - memset (buf, '\0', 9); // clear buf - if (cmd_mode == 2) - { - // 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 (c != 27) - dot = yank_delete (dot, dot, 0, YANKDEL); // delete char - dot = char_insert (dot, c); // insert new char - } - goto dc1; - } - } - if (cmd_mode == 1) - { - // 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 - } - goto dc1; - } - - switch (c) - { - //case 0x01: // soh - //case 0x09: // ht - //case 0x0b: // vt - //case 0x0e: // so - //case 0x0f: // si - //case 0x10: // dle - //case 0x11: // dc1 - //case 0x13: // dc3 + Byte c1, *p, *q, *msg, buf[9], *save_dot; + int cnt, i, j, dir, yf; + + c1 = c; // quiet the compiler + cnt = yf = dir = 0; // quiet the compiler + p = q = save_dot = msg = buf; // quiet the compiler + memset (buf, '\0', 9); // clear buf + if (cmd_mode == 2) + { + // 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 (c != 27) + dot = yank_delete (dot, dot, 0, YANKDEL); // delete char + dot = char_insert (dot, c); // insert new char + } + goto dc1; + } + } + if (cmd_mode == 1) + { + // 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 + } + goto dc1; + } + + switch (c) + { + //case 0x01: // soh + //case 0x09: // ht + //case 0x0b: // vt + //case 0x0e: // so + //case 0x0f: // si + //case 0x10: // dle + //case 0x11: // dc1 + //case 0x13: // dc3 #ifdef BB_FEATURE_VI_CRASHME - case 0x14: // dc4 ctrl-T - crashme = (crashme == 0) ? 1 : 0; - break; + case 0x14: // dc4 ctrl-T + crashme = (crashme == 0) ? 1 : 0; + break; #endif /* BB_FEATURE_VI_CRASHME */ - //case 0x16: // syn - //case 0x17: // etb - //case 0x18: // can - //case 0x1c: // fs - //case 0x1d: // gs - //case 0x1e: // rs - //case 0x1f: // us - //case '!': // !- - //case '#': // #- - //case '&': // &- - //case '(': // (- - //case ')': // )- - //case '*': // *- - //case ',': // ,- - //case '=': // =- - //case '@': // @- - //case 'F': // F- - //case 'K': // K- - //case 'Q': // Q- - //case 'S': // S- - //case 'T': // T- - //case 'V': // V- - //case '[': // [- - //case '\\': // \- - //case ']': // ]- - //case '_': // _- - //case '`': // `- - //case 'g': // g- - //case 'u': // u- FIXME- there is no undo - //case 'v': // v- - default: // unrecognised command - buf[0] = c; - buf[1] = '\0'; - if (c <= ' ') - { - buf[0] = '^'; - buf[1] = c + '@'; - buf[2] = '\0'; - } - ni ((Byte *) buf); - end_cmd_q (); // stop adding to q - case 0x00: // nul- ignore - break; - case 2: // ctrl-B scroll up full screen - case VI_K_PAGEUP: // Cursor Key Page Up - dot_scroll (rows - 2, -1); - break; + //case 0x16: // syn + //case 0x17: // etb + //case 0x18: // can + //case 0x1c: // fs + //case 0x1d: // gs + //case 0x1e: // rs + //case 0x1f: // us + //case '!': // !- + //case '#': // #- + //case '&': // &- + //case '(': // (- + //case ')': // )- + //case '*': // *- + //case ',': // ,- + //case '=': // =- + //case '@': // @- + //case 'F': // F- + //case 'K': // K- + //case 'Q': // Q- + //case 'S': // S- + //case 'T': // T- + //case 'V': // V- + //case '[': // [- + //case '\\': // \- + //case ']': // ]- + //case '_': // _- + //case '`': // `- + //case 'g': // g- + //case 'u': // u- FIXME- there is no undo + //case 'v': // v- + default: // unrecognised command + buf[0] = c; + buf[1] = '\0'; + if (c <= ' ') + { + buf[0] = '^'; + buf[1] = c + '@'; + buf[2] = '\0'; + } + ni ((Byte *) buf); + end_cmd_q (); // stop adding to q + case 0x00: // nul- ignore + break; + case 2: // ctrl-B scroll up full screen + case VI_K_PAGEUP: // Cursor Key Page Up + dot_scroll (rows - 2, -1); + break; #ifdef BB_FEATURE_VI_USE_SIGNALS - case 0x03: // ctrl-C interrupt - longjmp (restart, 1); - break; - case 26: // ctrl-Z suspend - suspend_sig (SIGTSTP); - break; + case 0x03: // ctrl-C interrupt + longjmp (restart, 1); + break; + case 26: // ctrl-Z suspend + suspend_sig (SIGTSTP); + break; #endif /* BB_FEATURE_VI_USE_SIGNALS */ - case 4: // ctrl-D scroll down half screen - dot_scroll ((rows - 2) / 2, 1); - break; - case 5: // ctrl-E scroll down one line - dot_scroll (1, 1); - break; - case 6: // ctrl-F scroll down full screen - case VI_K_PAGEDOWN: // Cursor Key Page Down - dot_scroll (rows - 2, 1); - break; - case 7: // ctrl-G show current status - edit_status (); - break; - case 'h': // h- move left - case VI_K_LEFT: // cursor key Left - case 8: // ctrl-H- move left (This may be ERASE char) - case 127: // DEL- move left (This may be ERASE char) - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dot_left (); - break; - case 10: // Newline ^J - case 'j': // j- goto next line, same col - case VI_K_DOWN: // cursor key Down - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dot_next (); // go to next B-o-l - dot = move_to_col (dot, ccol + offset); // try stay in same col - break; - case 12: // ctrl-L force redraw whole screen - case 18: // ctrl-R force redraw - place_cursor (0, 0, FALSE); // put cursor in correct place - clear_to_eos (); // tel terminal to erase display - (void) mysleep (10); - screen_erase (); // erase the internal screen buffer - refresh (TRUE); // this will redraw the entire display - break; - case 13: // Carriage Return ^M - case '+': // +- goto next line - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dot_next (); - dot_skip_over_ws (); - break; - case 21: // ctrl-U scroll up half screen - dot_scroll ((rows - 2) / 2, -1); - break; - case 25: // ctrl-Y scroll up one line - dot_scroll (1, -1); - break; - case 27: // esc - if (cmd_mode == 0) - indicate_error (c); - cmd_mode = 0; // stop insrting - end_cmd_q (); - *status_buffer = '\0'; // clear status buffer - break; - case ' ': // move right - case 'l': // move right - case VI_K_RIGHT: // Cursor Key Right - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dot_right (); - break; + case 4: // ctrl-D scroll down half screen + dot_scroll ((rows - 2) / 2, 1); + break; + case 5: // ctrl-E scroll down one line + dot_scroll (1, 1); + break; + case 6: // ctrl-F scroll down full screen + case VI_K_PAGEDOWN: // Cursor Key Page Down + dot_scroll (rows - 2, 1); + break; + case 7: // ctrl-G show current status + edit_status (); + break; + case 'h': // h- move left + case VI_K_LEFT: // cursor key Left + case 8: // ctrl-H- move left (This may be ERASE char) + case 127: // DEL- move left (This may be ERASE char) + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dot_left (); + break; + case 10: // Newline ^J + case 'j': // j- goto next line, same col + case VI_K_DOWN: // cursor key Down + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dot_next (); // go to next B-o-l + dot = move_to_col (dot, ccol + offset); // try stay in same col + break; + case 12: // ctrl-L force redraw whole screen + case 18: // ctrl-R force redraw + place_cursor (0, 0, FALSE); // put cursor in correct place + clear_to_eos (); // tel terminal to erase display + (void) mysleep (10); + screen_erase (); // erase the internal screen buffer + refresh (TRUE); // this will redraw the entire display + break; + case 13: // Carriage Return ^M + case '+': // +- goto next line + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dot_next (); + dot_skip_over_ws (); + break; + case 21: // ctrl-U scroll up half screen + dot_scroll ((rows - 2) / 2, -1); + break; + case 25: // ctrl-Y scroll up one line + dot_scroll (1, -1); + break; + case 27: // esc + if (cmd_mode == 0) + indicate_error (c); + cmd_mode = 0; // stop insrting + end_cmd_q (); + *status_buffer = '\0'; // clear status buffer + break; + case ' ': // move right + case 'l': // move right + case VI_K_RIGHT: // Cursor Key Right + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dot_right (); + break; #ifdef BB_FEATURE_VI_YANKMARK - case '"': // "- name a register to use for Delete/Yank - c1 = get_one_char (); - c1 = tolower (c1); - if (islower (c1)) - { - YDreg = c1 - 'a'; - } - else - { - indicate_error (c); - } - break; - case '\'': // '- goto a specific mark - c1 = get_one_char (); - c1 = tolower (c1); - if (islower (c1)) - { - c1 = c1 - 'a'; - // get the b-o-l - q = mark[(int) c1]; - if (text <= q && q < end) - { - dot = q; - dot_begin (); // go to B-o-l - dot_skip_over_ws (); - } - } - else if (c1 == '\'') - { // goto previous context - dot = swap_context (dot); // swap current and previous context - dot_begin (); // go to B-o-l - dot_skip_over_ws (); - } - else - { - indicate_error (c); - } - break; - case 'm': // m- Mark a line - // this is really stupid. If there are any inserts or deletes - // between text[0] and dot then this mark will not point to the - // correct location! It could be off by many lines! - // Well..., at least its quick and dirty. - c1 = get_one_char (); - c1 = tolower (c1); - if (islower (c1)) - { - c1 = c1 - 'a'; - // remember the line - mark[(int) c1] = dot; - } - else - { - indicate_error (c); - } - break; - case 'P': // P- Put register before - case 'p': // p- put register after - p = reg[YDreg]; - if (p == 0) - { - psbs ("Nothing in register %c", what_reg ()); - break; - } - // are we putting whole lines or strings - if (strchr ((char *) p, '\n') != NULL) - { - if (c == 'P') - { - dot_begin (); // putting lines- Put above - } - if (c == 'p') - { - // are we putting after very last line? - if (end_line (dot) == (end - 1)) - { - dot = end; // force dot to end of text[] - } - else - { - dot_next (); // next line, then put before - } - } - } - else - { - if (c == 'p') - dot_right (); // move to right, can move to NL - } - dot = string_insert (dot, p); // insert the string - end_cmd_q (); // stop adding to q - break; - case 'U': // U- Undo; replace current line with original version - if (reg[Ureg] != 0) - { - p = begin_line (dot); - q = end_line (dot); - p = text_hole_delete (p, q); // delete cur line - p = string_insert (p, reg[Ureg]); // insert orig line - dot = p; - dot_skip_over_ws (); - } - break; + case '"': // "- name a register to use for Delete/Yank + c1 = get_one_char (); + c1 = tolower (c1); + if (islower (c1)) + { + YDreg = c1 - 'a'; + } + else + { + indicate_error (c); + } + break; + case '\'': // '- goto a specific mark + c1 = get_one_char (); + c1 = tolower (c1); + if (islower (c1)) + { + c1 = c1 - 'a'; + // get the b-o-l + q = mark[(int) c1]; + if (text <= q && q < end) + { + dot = q; + dot_begin (); // go to B-o-l + dot_skip_over_ws (); + } + } + else if (c1 == '\'') + { // goto previous context + dot = swap_context (dot); // swap current and previous context + dot_begin (); // go to B-o-l + dot_skip_over_ws (); + } + else + { + indicate_error (c); + } + break; + case 'm': // m- Mark a line + // this is really stupid. If there are any inserts or deletes + // between text[0] and dot then this mark will not point to the + // correct location! It could be off by many lines! + // Well..., at least its quick and dirty. + c1 = get_one_char (); + c1 = tolower (c1); + if (islower (c1)) + { + c1 = c1 - 'a'; + // remember the line + mark[(int) c1] = dot; + } + else + { + indicate_error (c); + } + break; + case 'P': // P- Put register before + case 'p': // p- put register after + p = reg[YDreg]; + if (p == 0) + { + psbs ("Nothing in register %c", what_reg ()); + break; + } + // are we putting whole lines or strings + if (strchr ((char *) p, '\n') != NULL) + { + if (c == 'P') + { + dot_begin (); // putting lines- Put above + } + if (c == 'p') + { + // are we putting after very last line? + if (end_line (dot) == (end - 1)) + { + dot = end; // force dot to end of text[] + } + else + { + dot_next (); // next line, then put before + } + } + } + else + { + if (c == 'p') + dot_right (); // move to right, can move to NL + } + dot = string_insert (dot, p); // insert the string + end_cmd_q (); // stop adding to q + break; + case 'U': // U- Undo; replace current line with original version + if (reg[Ureg] != 0) + { + p = begin_line (dot); + q = end_line (dot); + p = text_hole_delete (p, q); // delete cur line + p = string_insert (p, reg[Ureg]); // insert orig line + dot = p; + dot_skip_over_ws (); + } + break; #endif /* BB_FEATURE_VI_YANKMARK */ - case '$': // $- goto end of line - case VI_K_END: // Cursor Key End - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dot = end_line (dot + 1); - break; - case '%': // %- find matching char of pair () [] {} - for (q = dot; q < end && *q != '\n'; q++) - { - if (strchr ("()[]{}", *q) != NULL) - { - // we found half of a pair - p = find_pair (q, *q); - if (p == NULL) - { - indicate_error (c); - } - else - { - dot = p; - } - break; - } - } - if (*q == '\n') - indicate_error (c); - break; - case 'f': // f- forward to a user specified char - last_forward_char = get_one_char (); // get the search char - // - // dont seperate these two commands. 'f' depends on ';' - // - //**** fall thru to ... 'i' - case ';': // ;- look at rest of line for last forward char - if (cmdcnt-- > 1) - { - do_cmd (';'); - } // repeat cnt - if (last_forward_char == 0) - break; - q = dot + 1; - while (q < end - 1 && *q != '\n' && *q != last_forward_char) - { - q++; - } - if (*q == last_forward_char) - dot = q; - break; - case '-': // -- goto prev line - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dot_prev (); - dot_skip_over_ws (); - break; + case '$': // $- goto end of line + case VI_K_END: // Cursor Key End + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dot = end_line (dot + 1); + break; + case '%': // %- find matching char of pair () [] {} + for (q = dot; q < end && *q != '\n'; q++) + { + if (strchr ("()[]{}", *q) != NULL) + { + // we found half of a pair + p = find_pair (q, *q); + if (p == NULL) + { + indicate_error (c); + } + else + { + dot = p; + } + break; + } + } + if (*q == '\n') + indicate_error (c); + break; + case 'f': // f- forward to a user specified char + last_forward_char = get_one_char (); // get the search char + // + // dont seperate these two commands. 'f' depends on ';' + // + //**** fall thru to ... 'i' + case ';': // ;- look at rest of line for last forward char + if (cmdcnt-- > 1) + { + do_cmd (';'); + } // repeat cnt + if (last_forward_char == 0) + break; + q = dot + 1; + while (q < end - 1 && *q != '\n' && *q != last_forward_char) + { + q++; + } + if (*q == last_forward_char) + dot = q; + break; + case '-': // -- goto prev line + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dot_prev (); + dot_skip_over_ws (); + break; #ifdef BB_FEATURE_VI_DOT_CMD - case '.': // .- repeat the last modifying command - // Stuff the last_modifying_cmd back into stdin - // and let it be re-executed. - if (last_modifying_cmd != 0) - { - ioq = ioq_start = (Byte *) strdup ((char *) last_modifying_cmd); - } - break; + case '.': // .- repeat the last modifying command + // Stuff the last_modifying_cmd back into stdin + // and let it be re-executed. + if (last_modifying_cmd != 0) + { + ioq = ioq_start = (Byte *) strdup ((char *) last_modifying_cmd); + } + break; #endif /* BB_FEATURE_VI_DOT_CMD */ #ifdef BB_FEATURE_VI_SEARCH - case '?': // /- search for a pattern - case '/': // /- search for a pattern - buf[0] = c; - buf[1] = '\0'; - q = get_input_line (buf); // get input line- use "status line" - if (strlen ((char *) q) == 1) - goto dc3; // if no pat re-use old pat - if (strlen ((char *) q) > 1) - { // new pat- save it and find - // there is a new pat - if (last_search_pattern != 0) - { - free (last_search_pattern); - } - last_search_pattern = (Byte *) strdup ((char *) q); - goto dc3; // now find the pattern - } - // user changed mind and erased the "/"- do nothing - break; - case 'N': // N- backward search for last pattern - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dir = BACK; // assume BACKWARD search - p = dot - 1; - if (last_search_pattern[0] == '?') - { - dir = FORWARD; - p = dot + 1; - } - goto dc4; // now search for pattern - break; - case 'n': // n- repeat search for last pattern - // search rest of text[] starting at next char - // if search fails return orignal "p" not the "p+1" address - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dc3: - if (last_search_pattern == 0) - { - msg = (Byte *) "No previous regular expression"; - goto dc2; - } - if (last_search_pattern[0] == '/') - { - dir = FORWARD; // assume FORWARD search - p = dot + 1; - } - if (last_search_pattern[0] == '?') - { - dir = BACK; - p = dot - 1; - } - dc4: - q = char_search (p, last_search_pattern + 1, dir, FULL); - if (q != NULL) - { - dot = q; // good search, update "dot" - msg = (Byte *) ""; - goto dc2; - } - // no pattern found between "dot" and "end"- continue at top - p = text; - if (dir == BACK) - { - p = end - 1; - } - q = char_search (p, last_search_pattern + 1, dir, FULL); - if (q != NULL) - { // found something - dot = q; // found new pattern- goto it - msg = (Byte *) "search hit BOTTOM, continuing at TOP"; - if (dir == BACK) - { - msg = (Byte *) "search hit TOP, continuing at BOTTOM"; - } - } - else - { - msg = (Byte *) "Pattern not found"; - } - dc2: - psbs ("%s", msg); - break; - case '{': // {- move backward paragraph - q = char_search (dot, (Byte *) "\n\n", BACK, FULL); - if (q != NULL) - { // found blank line - dot = next_line (q); // move to next blank line - } - break; - case '}': // }- move forward paragraph - q = char_search (dot, (Byte *) "\n\n", FORWARD, FULL); - if (q != NULL) - { // found blank line - dot = next_line (q); // move to next blank line - } - break; + case '?': // /- search for a pattern + case '/': // /- search for a pattern + buf[0] = c; + buf[1] = '\0'; + q = get_input_line (buf); // get input line- use "status line" + if (strlen ((char *) q) == 1) + goto dc3; // if no pat re-use old pat + if (strlen ((char *) q) > 1) + { // new pat- save it and find + // there is a new pat + if (last_search_pattern != 0) + { + free (last_search_pattern); + } + last_search_pattern = (Byte *) strdup ((char *) q); + goto dc3; // now find the pattern + } + // user changed mind and erased the "/"- do nothing + break; + case 'N': // N- backward search for last pattern + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dir = BACK; // assume BACKWARD search + p = dot - 1; + if (last_search_pattern[0] == '?') + { + dir = FORWARD; + p = dot + 1; + } + goto dc4; // now search for pattern + break; + case 'n': // n- repeat search for last pattern + // search rest of text[] starting at next char + // if search fails return orignal "p" not the "p+1" address + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dc3: + if (last_search_pattern == 0) + { + msg = (Byte *) "No previous regular expression"; + goto dc2; + } + if (last_search_pattern[0] == '/') + { + dir = FORWARD; // assume FORWARD search + p = dot + 1; + } + if (last_search_pattern[0] == '?') + { + dir = BACK; + p = dot - 1; + } + dc4: + q = char_search (p, last_search_pattern + 1, dir, FULL); + if (q != NULL) + { + dot = q; // good search, update "dot" + msg = (Byte *) ""; + goto dc2; + } + // no pattern found between "dot" and "end"- continue at top + p = text; + if (dir == BACK) + { + p = end - 1; + } + q = char_search (p, last_search_pattern + 1, dir, FULL); + if (q != NULL) + { // found something + dot = q; // found new pattern- goto it + msg = (Byte *) "search hit BOTTOM, continuing at TOP"; + if (dir == BACK) + { + msg = (Byte *) "search hit TOP, continuing at BOTTOM"; + } + } + else + { + msg = (Byte *) "Pattern not found"; + } + dc2: + psbs ("%s", msg); + break; + case '{': // {- move backward paragraph + q = char_search (dot, (Byte *) "\n\n", BACK, FULL); + if (q != NULL) + { // found blank line + dot = next_line (q); // move to next blank line + } + break; + case '}': // }- move forward paragraph + q = char_search (dot, (Byte *) "\n\n", FORWARD, FULL); + if (q != NULL) + { // found blank line + dot = next_line (q); // move to next blank line + } + break; #endif /* BB_FEATURE_VI_SEARCH */ - case '0': // 0- goto begining of line - case '1': // 1- - case '2': // 2- - case '3': // 3- - case '4': // 4- - case '5': // 5- - case '6': // 6- - case '7': // 7- - case '8': // 8- - case '9': // 9- - if (c == '0' && cmdcnt < 1) - { - dot_begin (); // this was a standalone zero - } - else - { - cmdcnt = cmdcnt * 10 + (c - '0'); // this 0 is part of a number - } - break; - case ':': // :- the colon mode commands - p = get_input_line ((Byte *) ":"); // get input line- use "status line" + case '0': // 0- goto begining of line + case '1': // 1- + case '2': // 2- + case '3': // 3- + case '4': // 4- + case '5': // 5- + case '6': // 6- + case '7': // 7- + case '8': // 8- + case '9': // 9- + if (c == '0' && cmdcnt < 1) + { + dot_begin (); // this was a standalone zero + } + else + { + cmdcnt = cmdcnt * 10 + (c - '0'); // this 0 is part of a number + } + break; + case ':': // :- the colon mode commands + p = get_input_line ((Byte *) ":"); // get input line- use "status line" #ifdef BB_FEATURE_VI_COLON - colon (p); // execute the command -#else /* BB_FEATURE_VI_COLON */ - if (*p == ':') - p++; // move past the ':' - cnt = strlen ((char *) p); - if (cnt <= 0) - break; - if (strncasecmp ((char *) p, "quit", cnt) == 0 || - strncasecmp ((char *) p, "q!", cnt) == 0) - { // delete lines - if (file_modified == TRUE && p[1] != '!') - { - psbs ("No write since last change (:quit! overrides)"); - } - else - { - editing = 0; - } - } - else if (strncasecmp ((char *) p, "write", cnt) == 0 || - strncasecmp ((char *) p, "wq", cnt) == 0) - { - cnt = file_write (cfn, text, end - 1); - file_modified = FALSE; - psb ("\"%s\" %dL, %dC", cfn, count_lines (text, end - 1), cnt); - if (p[1] == 'q') - { - editing = 0; - } - } - else if (strncasecmp ((char *) p, "file", cnt) == 0) - { - edit_status (); // show current file status - } - else if (sscanf ((char *) p, "%d", &j) > 0) - { - dot = find_line (j); // go to line # j - dot_skip_over_ws (); - } - else - { // unrecognised cmd - ni ((Byte *) p); - } + colon (p); // execute the command +#else /* BB_FEATURE_VI_COLON */ + if (*p == ':') + p++; // move past the ':' + cnt = strlen ((char *) p); + if (cnt <= 0) + break; + if (strncasecmp ((char *) p, "quit", cnt) == 0 || + strncasecmp ((char *) p, "q!", cnt) == 0) + { // delete lines + if (file_modified == TRUE && p[1] != '!') + { + psbs ("No write since last change (:quit! overrides)"); + } + else + { + editing = 0; + } + } + else if (strncasecmp ((char *) p, "write", cnt) == 0 || + strncasecmp ((char *) p, "wq", cnt) == 0) + { + cnt = file_write (cfn, text, end - 1); + file_modified = FALSE; + psb ("\"%s\" %dL, %dC", cfn, count_lines (text, end - 1), cnt); + if (p[1] == 'q') + { + editing = 0; + } + } + else if (strncasecmp ((char *) p, "file", cnt) == 0) + { + edit_status (); // show current file status + } + else if (sscanf ((char *) p, "%d", &j) > 0) + { + dot = find_line (j); // go to line # j + dot_skip_over_ws (); + } + else + { // unrecognised cmd + ni ((Byte *) p); + } #endif /* BB_FEATURE_VI_COLON */ - break; - case '<': // <- Left shift something - case '>': // >- Right shift something - cnt = count_lines (text, dot); // remember what line we are on - c1 = get_one_char (); // get the type of thing to delete - find_range (&p, &q, c1); - (void) yank_delete (p, q, 1, YANKONLY); // save copy before change - p = begin_line (p); - q = end_line (q); - i = count_lines (p, q); // # of lines we are shifting - for (; i > 0; i--, p = next_line (p)) - { - if (c == '<') - { - // shift left- remove tab or 8 spaces - if (*p == '\t') - { - // shrink buffer 1 char - (void) text_hole_delete (p, p); - } - else if (*p == ' ') - { - // we should be calculating columns, not just SPACE - for (j = 0; *p == ' ' && j < tabstop; j++) - { - (void) text_hole_delete (p, p); - } - } - } - else if (c == '>') - { - // shift right -- add tab or 8 spaces - (void) char_insert (p, '\t'); - } - } - dot = find_line (cnt); // what line were we on - dot_skip_over_ws (); - end_cmd_q (); // stop adding to q - break; - case 'A': // A- append at e-o-l - dot_end (); // go to e-o-l - //**** fall thru to ... 'a' - case 'a': // a- append after current char - if (*dot != '\n') - dot++; - goto dc_i; - break; - case 'B': // B- back a blank-delimited Word - case 'E': // E- end of a blank-delimited word - case 'W': // W- forward a blank-delimited word - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dir = FORWARD; - if (c == 'B') - dir = BACK; - if (c == 'W' || isspace (dot[dir])) - { - dot = skip_thing (dot, 1, dir, S_TO_WS); - dot = skip_thing (dot, 2, dir, S_OVER_WS); - } - if (c != 'W') - dot = skip_thing (dot, 1, dir, S_BEFORE_WS); - break; - case 'C': // C- Change to e-o-l - case 'D': // D- delete to e-o-l - save_dot = dot; - dot = dollar_line (dot); // move to before NL - // copy text into a register and delete - dot = yank_delete (save_dot, dot, 0, YANKDEL); // delete to e-o-l - if (c == 'C') - goto dc_i; // start inserting + break; + case '<': // <- Left shift something + case '>': // >- Right shift something + cnt = count_lines (text, dot); // remember what line we are on + c1 = get_one_char (); // get the type of thing to delete + find_range (&p, &q, c1); + (void) yank_delete (p, q, 1, YANKONLY); // save copy before change + p = begin_line (p); + q = end_line (q); + i = count_lines (p, q); // # of lines we are shifting + for (; i > 0; i--, p = next_line (p)) + { + if (c == '<') + { + // shift left- remove tab or 8 spaces + if (*p == '\t') + { + // shrink buffer 1 char + (void) text_hole_delete (p, p); + } + else if (*p == ' ') + { + // we should be calculating columns, not just SPACE + for (j = 0; *p == ' ' && j < tabstop; j++) + { + (void) text_hole_delete (p, p); + } + } + } + else if (c == '>') + { + // shift right -- add tab or 8 spaces + (void) char_insert (p, '\t'); + } + } + dot = find_line (cnt); // what line were we on + dot_skip_over_ws (); + end_cmd_q (); // stop adding to q + break; + case 'A': // A- append at e-o-l + dot_end (); // go to e-o-l + //**** fall thru to ... 'a' + case 'a': // a- append after current char + if (*dot != '\n') + dot++; + goto dc_i; + break; + case 'B': // B- back a blank-delimited Word + case 'E': // E- end of a blank-delimited word + case 'W': // W- forward a blank-delimited word + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dir = FORWARD; + if (c == 'B') + dir = BACK; + if (c == 'W' || isspace (dot[dir])) + { + dot = skip_thing (dot, 1, dir, S_TO_WS); + dot = skip_thing (dot, 2, dir, S_OVER_WS); + } + if (c != 'W') + dot = skip_thing (dot, 1, dir, S_BEFORE_WS); + break; + case 'C': // C- Change to e-o-l + case 'D': // D- delete to e-o-l + save_dot = dot; + dot = dollar_line (dot); // move to before NL + // copy text into a register and delete + dot = yank_delete (save_dot, dot, 0, YANKDEL); // delete to e-o-l + if (c == 'C') + goto dc_i; // start inserting #ifdef BB_FEATURE_VI_DOT_CMD - if (c == 'D') - end_cmd_q (); // stop adding to q + if (c == 'D') + end_cmd_q (); // stop adding to q #endif /* BB_FEATURE_VI_DOT_CMD */ - break; - case 'G': // G- goto to a line number (default= E-O-F) - dot = end - 1; // assume E-O-F - if (cmdcnt > 0) - { - dot = find_line (cmdcnt); // what line is #cmdcnt - } - dot_skip_over_ws (); - break; - case 'H': // H- goto top line on screen - dot = screenbegin; - if (cmdcnt > (rows - 1)) - { - cmdcnt = (rows - 1); - } - if (cmdcnt-- > 1) - { - do_cmd ('+'); - } // repeat cnt - dot_skip_over_ws (); - break; - case 'I': // I- insert before first non-blank - dot_begin (); // 0 - dot_skip_over_ws (); - //**** fall thru to ... 'i' - case 'i': // i- insert before current char - case VI_K_INSERT: // Cursor Key Insert - dc_i: - cmd_mode = 1; // start insrting - psb ("-- Insert --"); - break; - case 'J': // J- join current and next lines together - if (cmdcnt-- > 2) - { - do_cmd (c); - } // repeat cnt - dot_end (); // move to NL - if (dot < end - 1) - { // make sure not last char in text[] - *dot++ = ' '; // replace NL with space - while (isblnk (*dot)) - { // delete leading WS - dot_delete (); - } - } - end_cmd_q (); // stop adding to q - break; - case 'L': // L- goto bottom line on screen - dot = end_screen (); - if (cmdcnt > (rows - 1)) - { - cmdcnt = (rows - 1); - } - if (cmdcnt-- > 1) - { - do_cmd ('-'); - } // repeat cnt - dot_begin (); - dot_skip_over_ws (); - break; - case 'M': // M- goto middle line on screen - dot = screenbegin; - for (cnt = 0; cnt < (rows - 1) / 2; cnt++) - dot = next_line (dot); - break; - case 'O': // O- open a empty line above - // 0i\n ESC -i - p = begin_line (dot); - if (p[-1] == '\n') - { - dot_prev (); - case 'o': // o- open a empty line below; Yes, I know it is in the middle of the "if (..." - dot_end (); - dot = char_insert (dot, '\n'); - } - else - { - dot_begin (); // 0 - dot = char_insert (dot, '\n'); // i\n ESC - dot_prev (); // - - } - goto dc_i; - break; - case 'R': // R- continuous Replace char - dc5: - cmd_mode = 2; - psb ("-- Replace --"); - break; - case 'X': // X- delete char before dot - case 'x': // x- delete the current char - case 's': // s- substitute the current char - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dir = 0; - if (c == 'X') - dir = -1; - if (dot[dir] != '\n') - { - if (c == 'X') - dot--; // delete prev char - dot = yank_delete (dot, dot, 0, YANKDEL); // delete char - } - if (c == 's') - goto dc_i; // start insrting - end_cmd_q (); // stop adding to q - break; - case 'Z': // Z- if modified, {write}; exit - // ZZ means to save file (if necessary), then exit - c1 = get_one_char (); - if (c1 != 'Z') - { - indicate_error (c); - break; - } - if (file_modified == TRUE + break; + case 'G': // G- goto to a line number (default= E-O-F) + dot = end - 1; // assume E-O-F + if (cmdcnt > 0) + { + dot = find_line (cmdcnt); // what line is #cmdcnt + } + dot_skip_over_ws (); + break; + case 'H': // H- goto top line on screen + dot = screenbegin; + if (cmdcnt > (rows - 1)) + { + cmdcnt = (rows - 1); + } + if (cmdcnt-- > 1) + { + do_cmd ('+'); + } // repeat cnt + dot_skip_over_ws (); + break; + case 'I': // I- insert before first non-blank + dot_begin (); // 0 + dot_skip_over_ws (); + //**** fall thru to ... 'i' + case 'i': // i- insert before current char + case VI_K_INSERT: // Cursor Key Insert + dc_i: + cmd_mode = 1; // start insrting + psb ("-- Insert --"); + break; + case 'J': // J- join current and next lines together + if (cmdcnt-- > 2) + { + do_cmd (c); + } // repeat cnt + dot_end (); // move to NL + if (dot < end - 1) + { // make sure not last char in text[] + *dot++ = ' '; // replace NL with space + while (isblnk (*dot)) + { // delete leading WS + dot_delete (); + } + } + end_cmd_q (); // stop adding to q + break; + case 'L': // L- goto bottom line on screen + dot = end_screen (); + if (cmdcnt > (rows - 1)) + { + cmdcnt = (rows - 1); + } + if (cmdcnt-- > 1) + { + do_cmd ('-'); + } // repeat cnt + dot_begin (); + dot_skip_over_ws (); + break; + case 'M': // M- goto middle line on screen + dot = screenbegin; + for (cnt = 0; cnt < (rows - 1) / 2; cnt++) + dot = next_line (dot); + break; + case 'O': // O- open a empty line above + // 0i\n ESC -i + p = begin_line (dot); + if (p[-1] == '\n') + { + dot_prev (); + case 'o': // o- open a empty line below; Yes, I know it is in the middle of the "if (..." + dot_end (); + dot = char_insert (dot, '\n'); + } + else + { + dot_begin (); // 0 + dot = char_insert (dot, '\n'); // i\n ESC + dot_prev (); // - + } + goto dc_i; + break; + case 'R': // R- continuous Replace char + dc5: + cmd_mode = 2; + psb ("-- Replace --"); + break; + case 'X': // X- delete char before dot + case 'x': // x- delete the current char + case 's': // s- substitute the current char + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dir = 0; + if (c == 'X') + dir = -1; + if (dot[dir] != '\n') + { + if (c == 'X') + dot--; // delete prev char + dot = yank_delete (dot, dot, 0, YANKDEL); // delete char + } + if (c == 's') + goto dc_i; // start insrting + end_cmd_q (); // stop adding to q + break; + case 'Z': // Z- if modified, {write}; exit + // ZZ means to save file (if necessary), then exit + c1 = get_one_char (); + if (c1 != 'Z') + { + indicate_error (c); + break; + } + if (file_modified == TRUE #ifdef BB_FEATURE_VI_READONLY - && vi_readonly == FALSE && readonly == FALSE + && vi_readonly == FALSE && readonly == FALSE #endif /* BB_FEATURE_VI_READONLY */ - ) - { - cnt = file_write (cfn, text, end - 1); - if (cnt == (end - 1 - text + 1)) - { - editing = 0; - } - } - else - { - editing = 0; - } - break; - case '^': // ^- move to first non-blank on line - dot_begin (); - dot_skip_over_ws (); - break; - case 'b': // b- back a word - case 'e': // e- end of word - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dir = FORWARD; - if (c == 'b') - dir = BACK; - if ((dot + dir) < text || (dot + dir) > end - 1) - break; - dot += dir; - if (isspace (*dot)) - { - dot = skip_thing (dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS); - } - if (isalnum (*dot) || *dot == '_') - { - dot = skip_thing (dot, 1, dir, S_END_ALNUM); - } - else if (ispunct (*dot)) - { - dot = skip_thing (dot, 1, dir, S_END_PUNCT); - } - break; - case 'c': // c- change something - case 'd': // d- delete something + ) + { + cnt = file_write (cfn, text, end - 1); + if (cnt == (end - 1 - text + 1)) + { + editing = 0; + } + } + else + { + editing = 0; + } + break; + case '^': // ^- move to first non-blank on line + dot_begin (); + dot_skip_over_ws (); + break; + case 'b': // b- back a word + case 'e': // e- end of word + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dir = FORWARD; + if (c == 'b') + dir = BACK; + if ((dot + dir) < text || (dot + dir) > end - 1) + break; + dot += dir; + if (isspace (*dot)) + { + dot = skip_thing (dot, (c == 'e') ? 2 : 1, dir, S_OVER_WS); + } + if (isalnum (*dot) || *dot == '_') + { + dot = skip_thing (dot, 1, dir, S_END_ALNUM); + } + else if (ispunct (*dot)) + { + dot = skip_thing (dot, 1, dir, S_END_PUNCT); + } + break; + case 'c': // c- change something + case 'd': // d- delete something #ifdef BB_FEATURE_VI_YANKMARK - case 'y': // y- yank something - case 'Y': // Y- Yank a line + case 'y': // y- yank something + case 'Y': // Y- Yank a line #endif /* BB_FEATURE_VI_YANKMARK */ - yf = YANKDEL; // assume either "c" or "d" + yf = YANKDEL; // assume either "c" or "d" #ifdef BB_FEATURE_VI_YANKMARK - if (c == 'y' || c == 'Y') - yf = YANKONLY; + if (c == 'y' || c == 'Y') + yf = YANKONLY; #endif /* BB_FEATURE_VI_YANKMARK */ - c1 = 'y'; - if (c != 'Y') - c1 = get_one_char (); // get the type of thing to delete - find_range (&p, &q, c1); - if (c1 == 27) - { // ESC- user changed mind and wants out - c = c1 = 27; // Escape- do nothing - } - else if (strchr ("wW", c1)) - { - if (c == 'c') - { - // don't include trailing WS as part of word - while (isblnk (*q)) - { - if (q <= text || q[-1] == '\n') - break; - q--; - } - } - dot = yank_delete (p, q, 0, yf); // delete word - } - else if (strchr ("^0bBeEft$", c1)) - { - // single line copy text into a register and delete - dot = yank_delete (p, q, 0, yf); // delete word - } - else if (strchr ("cdykjHL%+-{}\r\n", c1)) - { - // multiple line copy text into a register and delete - dot = yank_delete (p, q, 1, yf); // delete lines - if (c == 'c') - { - dot = char_insert (dot, '\n'); - // on the last line of file don't move to prev line - if (dot != (end - 1)) - { - dot_prev (); - } - } - else if (c == 'd') - { - dot_begin (); - dot_skip_over_ws (); - } - } - else - { - // could not recognize object - c = c1 = 27; // error- - indicate_error (c); - } - if (c1 != 27) - { - // if CHANGING, not deleting, start inserting after the delete - if (c == 'c') - { - strcpy ((char *) buf, "Change"); - goto dc_i; // start inserting - } - if (c == 'd') - { - strcpy ((char *) buf, "Delete"); - } + c1 = 'y'; + if (c != 'Y') + c1 = get_one_char (); // get the type of thing to delete + find_range (&p, &q, c1); + if (c1 == 27) + { // ESC- user changed mind and wants out + c = c1 = 27; // Escape- do nothing + } + else if (strchr ("wW", c1)) + { + if (c == 'c') + { + // don't include trailing WS as part of word + while (isblnk (*q)) + { + if (q <= text || q[-1] == '\n') + break; + q--; + } + } + dot = yank_delete (p, q, 0, yf); // delete word + } + else if (strchr ("^0bBeEft$", c1)) + { + // single line copy text into a register and delete + dot = yank_delete (p, q, 0, yf); // delete word + } + else if (strchr ("cdykjHL%+-{}\r\n", c1)) + { + // multiple line copy text into a register and delete + dot = yank_delete (p, q, 1, yf); // delete lines + if (c == 'c') + { + dot = char_insert (dot, '\n'); + // on the last line of file don't move to prev line + if (dot != (end - 1)) + { + dot_prev (); + } + } + else if (c == 'd') + { + dot_begin (); + dot_skip_over_ws (); + } + } + else + { + // could not recognize object + c = c1 = 27; // error- + indicate_error (c); + } + if (c1 != 27) + { + // if CHANGING, not deleting, start inserting after the delete + if (c == 'c') + { + strcpy ((char *) buf, "Change"); + goto dc_i; // start inserting + } + if (c == 'd') + { + strcpy ((char *) buf, "Delete"); + } #ifdef BB_FEATURE_VI_YANKMARK - if (c == 'y' || c == 'Y') - { - strcpy ((char *) buf, "Yank"); - } - p = reg[YDreg]; - q = p + strlen ((char *) p); - for (cnt = 0; p <= q; p++) - { - if (*p == '\n') - cnt++; - } - psb ("%s %d lines (%d chars) using [%c]", - buf, cnt, strlen ((char *) reg[YDreg]), what_reg ()); + if (c == 'y' || c == 'Y') + { + strcpy ((char *) buf, "Yank"); + } + p = reg[YDreg]; + q = p + strlen ((char *) p); + for (cnt = 0; p <= q; p++) + { + if (*p == '\n') + cnt++; + } + psb ("%s %d lines (%d chars) using [%c]", + buf, cnt, strlen ((char *) reg[YDreg]), what_reg ()); #endif /* BB_FEATURE_VI_YANKMARK */ - end_cmd_q (); // stop adding to q - } - break; - case 'k': // k- goto prev line, same col - case VI_K_UP: // cursor key Up - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - dot_prev (); - dot = move_to_col (dot, ccol + offset); // try stay in same col - break; - case 'r': // r- replace the current char with user input - c1 = get_one_char (); // get the replacement char - if (*dot != '\n') - { - *dot = c1; - file_modified = TRUE; // has the file been modified - } - end_cmd_q (); // stop adding to q - break; - case 't': // t- move to char prior to next x - last_forward_char = get_one_char (); - do_cmd (';'); - if (*dot == last_forward_char) - dot_left (); - last_forward_char = 0; - break; - case 'w': // w- forward a word - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - if (isalnum (*dot) || *dot == '_') - { // we are on ALNUM - dot = skip_thing (dot, 1, FORWARD, S_END_ALNUM); - } - else if (ispunct (*dot)) - { // we are on PUNCT - dot = skip_thing (dot, 1, FORWARD, S_END_PUNCT); - } - if (dot < end - 1) - dot++; // move over word - if (isspace (*dot)) - { - dot = skip_thing (dot, 2, FORWARD, S_OVER_WS); - } - break; - case 'z': // z- - c1 = get_one_char (); // get the replacement char - cnt = 0; - if (c1 == '.') - cnt = (rows - 2) / 2; // put dot at center - if (c1 == '-') - cnt = rows - 2; // put dot at bottom - screenbegin = begin_line (dot); // start dot at top - dot_scroll (cnt, -1); - break; - case '|': // |- move to column "cmdcnt" - dot = move_to_col (dot, cmdcnt - 1); // try to move to column - break; - case '~': // ~- flip the case of letters a-z -> A-Z - if (cmdcnt-- > 1) - { - do_cmd (c); - } // repeat cnt - if (islower (*dot)) - { - *dot = toupper (*dot); - file_modified = TRUE; // has the file been modified - } - else if (isupper (*dot)) - { - *dot = tolower (*dot); - file_modified = TRUE; // has the file been modified - } - dot_right (); - end_cmd_q (); // stop adding to q - break; - //----- The Cursor and Function Keys ----------------------------- - case VI_K_HOME: // Cursor Key Home - dot_begin (); - break; - // The Fn keys could point to do_macro which could translate them - case VI_K_FUN1: // Function Key F1 - case VI_K_FUN2: // Function Key F2 - case VI_K_FUN3: // Function Key F3 - case VI_K_FUN4: // Function Key F4 - case VI_K_FUN5: // Function Key F5 - case VI_K_FUN6: // Function Key F6 - case VI_K_FUN7: // Function Key F7 - case VI_K_FUN8: // Function Key F8 - case VI_K_FUN9: // Function Key F9 - case VI_K_FUN10: // Function Key F10 - case VI_K_FUN11: // Function Key F11 - case VI_K_FUN12: // Function Key F12 - break; - } + end_cmd_q (); // stop adding to q + } + break; + case 'k': // k- goto prev line, same col + case VI_K_UP: // cursor key Up + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + dot_prev (); + dot = move_to_col (dot, ccol + offset); // try stay in same col + break; + case 'r': // r- replace the current char with user input + c1 = get_one_char (); // get the replacement char + if (*dot != '\n') + { + *dot = c1; + file_modified = TRUE; // has the file been modified + } + end_cmd_q (); // stop adding to q + break; + case 't': // t- move to char prior to next x + last_forward_char = get_one_char (); + do_cmd (';'); + if (*dot == last_forward_char) + dot_left (); + last_forward_char = 0; + break; + case 'w': // w- forward a word + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + if (isalnum (*dot) || *dot == '_') + { // we are on ALNUM + dot = skip_thing (dot, 1, FORWARD, S_END_ALNUM); + } + else if (ispunct (*dot)) + { // we are on PUNCT + dot = skip_thing (dot, 1, FORWARD, S_END_PUNCT); + } + if (dot < end - 1) + dot++; // move over word + if (isspace (*dot)) + { + dot = skip_thing (dot, 2, FORWARD, S_OVER_WS); + } + break; + case 'z': // z- + c1 = get_one_char (); // get the replacement char + cnt = 0; + if (c1 == '.') + cnt = (rows - 2) / 2; // put dot at center + if (c1 == '-') + cnt = rows - 2; // put dot at bottom + screenbegin = begin_line (dot); // start dot at top + dot_scroll (cnt, -1); + break; + case '|': // |- move to column "cmdcnt" + dot = move_to_col (dot, cmdcnt - 1); // try to move to column + break; + case '~': // ~- flip the case of letters a-z -> A-Z + if (cmdcnt-- > 1) + { + do_cmd (c); + } // repeat cnt + if (islower (*dot)) + { + *dot = toupper (*dot); + file_modified = TRUE; // has the file been modified + } + else if (isupper (*dot)) + { + *dot = tolower (*dot); + file_modified = TRUE; // has the file been modified + } + dot_right (); + end_cmd_q (); // stop adding to q + break; + //----- The Cursor and Function Keys ----------------------------- + case VI_K_HOME: // Cursor Key Home + dot_begin (); + break; + // The Fn keys could point to do_macro which could translate them + case VI_K_FUN1: // Function Key F1 + case VI_K_FUN2: // Function Key F2 + case VI_K_FUN3: // Function Key F3 + case VI_K_FUN4: // Function Key F4 + case VI_K_FUN5: // Function Key F5 + case VI_K_FUN6: // Function Key F6 + case VI_K_FUN7: // Function Key F7 + case VI_K_FUN8: // Function Key F8 + case VI_K_FUN9: // Function Key F9 + case VI_K_FUN10: // Function Key F10 + case VI_K_FUN11: // Function Key F11 + case VI_K_FUN12: // Function Key F12 + break; + } dc1: - // if text[] just became empty, add back an empty line - if (end == text) - { - (void) char_insert (text, '\n'); // start empty buf with dummy line - dot = text; - } - // it is OK for dot to exactly equal to end, otherwise check dot validity - if (dot != end) - { - dot = bound_dot (dot); // make sure "dot" is valid - } + // if text[] just became empty, add back an empty line + if (end == text) + { + (void) char_insert (text, '\n'); // start empty buf with dummy line + dot = text; + } + // it is OK for dot to exactly equal to end, otherwise check dot validity + if (dot != end) + { + dot = bound_dot (dot); // make sure "dot" is valid + } #ifdef BB_FEATURE_VI_YANKMARK - check_context (c); // update the current context + check_context (c); // update the current context #endif /* BB_FEATURE_VI_YANKMARK */ - if (!isdigit (c)) - cmdcnt = 0; // cmd was not a number, reset cmdcnt - cnt = dot - begin_line (dot); - // Try to stay off of the Newline - if (*dot == '\n' && cnt > 0 && cmd_mode == 0) - dot--; + if (!isdigit (c)) + cmdcnt = 0; // cmd was not a number, reset cmdcnt + cnt = dot - begin_line (dot); + // Try to stay off of the Newline + if (*dot == '\n' && cnt > 0 && cmd_mode == 0) + dot--; } //----- The Colon commands ------------------------------------- #ifdef BB_FEATURE_VI_COLON static Byte * -get_one_address (Byte * p, int *addr) // get colon addr, if present +get_one_address (Byte * p, int *addr) // get colon addr, if present { - int st; - Byte *q; + int st; + Byte *q; #ifdef BB_FEATURE_VI_YANKMARK - Byte c; + Byte c; #endif /* BB_FEATURE_VI_YANKMARK */ #ifdef BB_FEATURE_VI_SEARCH - Byte *pat, buf[BUFSIZ]; + Byte *pat, buf[BUFSIZ]; #endif /* BB_FEATURE_VI_SEARCH */ - *addr = -1; // assume no addr - if (*p == '.') - { // the current line - p++; - q = begin_line (dot); - *addr = count_lines (text, q); + *addr = -1; // assume no addr + if (*p == '.') + { // the current line + p++; + q = begin_line (dot); + *addr = count_lines (text, q); #ifdef BB_FEATURE_VI_YANKMARK - } - else if (*p == '\'') - { // is this a mark addr - p++; - c = tolower (*p); - p++; - if (c >= 'a' && c <= 'z') - { - // we have a mark - c = c - 'a'; - q = mark[(int) c]; - if (q != NULL) - { // is mark valid - *addr = count_lines (text, q); // count lines - } - } + } + else if (*p == '\'') + { // is this a mark addr + p++; + c = tolower (*p); + p++; + if (c >= 'a' && c <= 'z') + { + // we have a mark + c = c - 'a'; + q = mark[(int) c]; + if (q != NULL) + { // is mark valid + *addr = count_lines (text, q); // count lines + } + } #endif /* BB_FEATURE_VI_YANKMARK */ #ifdef BB_FEATURE_VI_SEARCH - } - else if (*p == '/') - { // a search pattern - q = buf; - for (p++; *p; p++) - { - if (*p == '/') - break; - *q++ = *p; - *q = '\0'; - } - pat = (Byte *) strdup ((char *) buf); // save copy of pattern - if (*p == '/') - p++; - q = char_search (dot, pat, FORWARD, FULL); - if (q != NULL) - { - *addr = count_lines (text, q); - } - free (pat); + } + else if (*p == '/') + { // a search pattern + q = buf; + for (p++; *p; p++) + { + if (*p == '/') + break; + *q++ = *p; + *q = '\0'; + } + pat = (Byte *) strdup ((char *) buf); // save copy of pattern + if (*p == '/') + p++; + q = char_search (dot, pat, FORWARD, FULL); + if (q != NULL) + { + *addr = count_lines (text, q); + } + free (pat); #endif /* BB_FEATURE_VI_SEARCH */ - } - else if (*p == '$') - { // the last line in file - p++; - q = begin_line (end - 1); - *addr = count_lines (text, q); - } - else if (isdigit (*p)) - { // specific line number - sscanf ((char *) p, "%d%n", addr, &st); - p += st; - } - else - { // I don't reconise this - // unrecognised address- assume -1 - *addr = -1; - } - return (p); + } + else if (*p == '$') + { // the last line in file + p++; + q = begin_line (end - 1); + *addr = count_lines (text, q); + } + else if (isdigit (*p)) + { // specific line number + sscanf ((char *) p, "%d%n", addr, &st); + p += st; + } + else + { // I don't reconise this + // unrecognised address- assume -1 + *addr = -1; + } + return (p); } static Byte * -get_address (Byte * p, int *b, int *e) // get two colon addrs, if present +get_address (Byte * p, int *b, int *e) // get two colon addrs, if present { - //----- get the address' i.e., 1,3 'a,'b ----- - // get FIRST addr, if present - while (isblnk (*p)) - p++; // skip over leading spaces - if (*p == '%') - { // alias for 1,$ - p++; - *b = 1; - *e = count_lines (text, end - 1); - goto ga0; - } - p = get_one_address (p, b); - while (isblnk (*p)) - p++; - if (*p == ',') - { // is there a address seperator - p++; - while (isblnk (*p)) - p++; - // get SECOND addr, if present - p = get_one_address (p, e); - } + //----- get the address' i.e., 1,3 'a,'b ----- + // get FIRST addr, if present + while (isblnk (*p)) + p++; // skip over leading spaces + if (*p == '%') + { // alias for 1,$ + p++; + *b = 1; + *e = count_lines (text, end - 1); + goto ga0; + } + p = get_one_address (p, b); + while (isblnk (*p)) + p++; + if (*p == ',') + { // is there a address seperator + p++; + while (isblnk (*p)) + p++; + // get SECOND addr, if present + p = get_one_address (p, e); + } ga0: - while (isblnk (*p)) - p++; // skip over trailing spaces - return (p); + while (isblnk (*p)) + p++; // skip over trailing spaces + return (p); } static void colon (Byte * buf) { - Byte c, *orig_buf, *buf1, *q, *r; - Byte *fn, cmd[BUFSIZ], args[BUFSIZ]; - int i, l, li, ch, st, b, e; - int useforce, forced; - struct stat st_buf; - - // :3154 // if (-e line 3154) goto it else stay put - // :4,33w! foo // write a portion of buffer to file "foo" - // :w // write all of buffer to current file - // :q // quit - // :q! // quit- dont care about modified file - // :'a,'z!sort -u // filter block through sort - // :'f // goto mark "f" - // :'fl // list literal the mark "f" line - // :.r bar // read file "bar" into buffer before dot - // :/123/,/abc/d // delete lines from "123" line to "abc" line - // :/xyz/ // goto the "xyz" line - // :s/find/replace/ // substitute pattern "find" with "replace" - // :! // run then return - // - if (strlen ((char *) buf) <= 0) - goto vc1; - if (*buf == ':') - buf++; // move past the ':' - - forced = useforce = FALSE; - li = st = ch = i = 0; - b = e = -1; - q = text; // assume 1,$ for the range - r = end - 1; - li = count_lines (text, end - 1); - fn = cfn; // default to current file - memset (cmd, '\0', BUFSIZ); // clear cmd[] - memset (args, '\0', BUFSIZ); // clear args[] - - // look for optional address(es) :. :1 :1,9 :'q,'a :% - buf = get_address (buf, &b, &e); - - // remember orig command line - orig_buf = buf; - - // get the COMMAND into cmd[] - buf1 = cmd; - while (*buf != '\0') - { - if (isspace (*buf)) - break; - *buf1++ = *buf++; - } - // get any ARGuments - while (isblnk (*buf)) - buf++; - strcpy ((char *) args, (char *) buf); - buf1 = last_char_is ((char *) cmd, '!'); - if (buf1) - { - useforce = TRUE; - *buf1 = '\0'; // get rid of ! - } - if (b >= 0) - { - // if there is only one addr, then the addr - // is the line number of the single line the - // user wants. So, reset the end - // pointer to point at end of the "b" line - q = find_line (b); // what line is #b - r = end_line (q); - li = 1; - } - if (e >= 0) - { - // we were given two addrs. change the - // end pointer to the addr given by user. - r = find_line (e); // what line is #e - r = end_line (r); - li = e - b + 1; - } - // ------------ now look for the command ------------ - i = strlen ((char *) cmd); - if (i == 0) - { // :123CR goto line #123 - if (b >= 0) - { - dot = find_line (b); // what line is #b - dot_skip_over_ws (); - } - } - else if (0) - { - // } else if (strncmp((char *) cmd, "!", 1) == 0) { // run a cmd - // :!ls run the - // (void) alarm(0); // wait for input- no alarms - place_cursor (rows - 1, 0, FALSE); // go to Status line - clear_to_eol (); // clear the line - cookmode (); - system (orig_buf + 1); // run the cmd - rawmode (); - Hit_Return (); // let user see results - // (void) alarm(3); // done waiting for input - } - else if (strncmp ((char *) cmd, "=", i) == 0) - { // where is the address - if (b < 0) - { // no addr given- use defaults - b = e = count_lines (text, dot); - } - psb ("%d", b); - } - else if (strncasecmp ((char *) cmd, "delete", i) == 0) - { // delete lines - if (b < 0) - { // no addr given- use defaults - q = begin_line (dot); // assume .,. for the range - r = end_line (dot); - } - dot = yank_delete (q, r, 1, YANKDEL); // save, then delete lines - dot_skip_over_ws (); - } - else if (0) - { - // } else if (strncasecmp((char *) cmd, "edit", i) == 0) { // Edit a file - int sr; - sr = 0; - // don't edit, if the current file has been modified - if (file_modified == TRUE && useforce != TRUE) - { - psbs ("No write since last change (:edit! overrides)"); - goto vc1; - } - if (strlen (args) > 0) - { - // the user supplied a file name - fn = args; - } - else if (cfn != 0 && strlen (cfn) > 0) - { - // no user supplied name- use the current filename - fn = cfn; - goto vc5; - } - else - { - // no user file name, no current name- punt - psbs ("No current filename"); - goto vc1; - } - - // see if file exists- if not, its just a new file request - if ((sr = stat ((char *) fn, &st_buf)) < 0) - { - // This is just a request for a new file creation. - // The file_insert below will fail but we get - // an empty buffer with a file name. Then the "write" - // command can do the create. - } - else - { - if ((st_buf.st_mode & (S_IFREG)) == 0) - { - // This is not a regular file - psbs ("\"%s\" is not a regular file", fn); - goto vc1; - } - if ((st_buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) - { - // dont have any read permissions - psbs ("\"%s\" is not readable", fn); - goto vc1; - } - } - - // There is a read-able regular file - // make this the current file - q = (Byte *) strdup ((char *) fn); // save the cfn - if (cfn != 0) - free (cfn); // free the old name - cfn = q; // remember new cfn - - vc5: - // delete all the contents of text[] - new_text (2 * file_size (fn)); - screenbegin = dot = end = text; - - // insert new file - ch = file_insert (fn, text, file_size (fn)); - - if (ch < 1) - { - // start empty buf with dummy line - (void) char_insert (text, '\n'); - ch = 1; - } - file_modified = FALSE; + Byte c, *orig_buf, *buf1, *q, *r; + Byte *fn, cmd[BUFSIZ], args[BUFSIZ]; + int i, l, li, ch, st, b, e; + int useforce, forced; + struct stat st_buf; + + // :3154 // if (-e line 3154) goto it else stay put + // :4,33w! foo // write a portion of buffer to file "foo" + // :w // write all of buffer to current file + // :q // quit + // :q! // quit- dont care about modified file + // :'a,'z!sort -u // filter block through sort + // :'f // goto mark "f" + // :'fl // list literal the mark "f" line + // :.r bar // read file "bar" into buffer before dot + // :/123/,/abc/d // delete lines from "123" line to "abc" line + // :/xyz/ // goto the "xyz" line + // :s/find/replace/ // substitute pattern "find" with "replace" + // :! // run then return + // + if (strlen ((char *) buf) <= 0) + goto vc1; + if (*buf == ':') + buf++; // move past the ':' + + forced = useforce = FALSE; + li = st = ch = i = 0; + b = e = -1; + q = text; // assume 1,$ for the range + r = end - 1; + li = count_lines (text, end - 1); + fn = cfn; // default to current file + memset (cmd, '\0', BUFSIZ); // clear cmd[] + memset (args, '\0', BUFSIZ); // clear args[] + + // look for optional address(es) :. :1 :1,9 :'q,'a :% + buf = get_address (buf, &b, &e); + + // remember orig command line + orig_buf = buf; + + // get the COMMAND into cmd[] + buf1 = cmd; + while (*buf != '\0') + { + if (isspace (*buf)) + break; + *buf1++ = *buf++; + } + // get any ARGuments + while (isblnk (*buf)) + buf++; + strcpy ((char *) args, (char *) buf); + buf1 = last_char_is ((char *) cmd, '!'); + if (buf1) + { + useforce = TRUE; + *buf1 = '\0'; // get rid of ! + } + if (b >= 0) + { + // if there is only one addr, then the addr + // is the line number of the single line the + // user wants. So, reset the end + // pointer to point at end of the "b" line + q = find_line (b); // what line is #b + r = end_line (q); + li = 1; + } + if (e >= 0) + { + // we were given two addrs. change the + // end pointer to the addr given by user. + r = find_line (e); // what line is #e + r = end_line (r); + li = e - b + 1; + } + // ------------ now look for the command ------------ + i = strlen ((char *) cmd); + if (i == 0) + { // :123CR goto line #123 + if (b >= 0) + { + dot = find_line (b); // what line is #b + dot_skip_over_ws (); + } + } + else if (0) + { + // } else if (strncmp((char *) cmd, "!", 1) == 0) { // run a cmd + // :!ls run the + // (void) alarm(0); // wait for input- no alarms + place_cursor (rows - 1, 0, FALSE); // go to Status line + clear_to_eol (); // clear the line + cookmode (); + system (orig_buf + 1); // run the cmd + rawmode (); + Hit_Return (); // let user see results + // (void) alarm(3); // done waiting for input + } + else if (strncmp ((char *) cmd, "=", i) == 0) + { // where is the address + if (b < 0) + { // no addr given- use defaults + b = e = count_lines (text, dot); + } + psb ("%d", b); + } + else if (strncasecmp ((char *) cmd, "delete", i) == 0) + { // delete lines + if (b < 0) + { // no addr given- use defaults + q = begin_line (dot); // assume .,. for the range + r = end_line (dot); + } + dot = yank_delete (q, r, 1, YANKDEL); // save, then delete lines + dot_skip_over_ws (); + } + else if (0) + { + // } else if (strncasecmp((char *) cmd, "edit", i) == 0) { // Edit a file + int sr; + sr = 0; + // don't edit, if the current file has been modified + if (file_modified == TRUE && useforce != TRUE) + { + psbs ("No write since last change (:edit! overrides)"); + goto vc1; + } + if (strlen (args) > 0) + { + // the user supplied a file name + fn = args; + } + else if (cfn != 0 && strlen (cfn) > 0) + { + // no user supplied name- use the current filename + fn = cfn; + goto vc5; + } + else + { + // no user file name, no current name- punt + psbs ("No current filename"); + goto vc1; + } + + // see if file exists- if not, its just a new file request + if ((sr = stat ((char *) fn, &st_buf)) < 0) + { + // This is just a request for a new file creation. + // The file_insert below will fail but we get + // an empty buffer with a file name. Then the "write" + // command can do the create. + } + else + { + if ((st_buf.st_mode & (S_IFREG)) == 0) + { + // This is not a regular file + psbs ("\"%s\" is not a regular file", fn); + goto vc1; + } + if ((st_buf.st_mode & (S_IRUSR | S_IRGRP | S_IROTH)) == 0) + { + // dont have any read permissions + psbs ("\"%s\" is not readable", fn); + goto vc1; + } + } + + // There is a read-able regular file + // make this the current file + q = (Byte *) strdup ((char *) fn); // save the cfn + if (cfn != 0) + free (cfn); // free the old name + cfn = q; // remember new cfn + + vc5: + // delete all the contents of text[] + new_text (2 * file_size (fn)); + screenbegin = dot = end = text; + + // insert new file + ch = file_insert (fn, text, file_size (fn)); + + if (ch < 1) + { + // start empty buf with dummy line + (void) char_insert (text, '\n'); + ch = 1; + } + file_modified = FALSE; #ifdef BB_FEATURE_VI_YANKMARK - if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) - { - free (reg[Ureg]); // free orig line reg- for 'U' - reg[Ureg] = 0; - } - if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0) - { - free (reg[YDreg]); // free default yank/delete register - reg[YDreg] = 0; - } - for (li = 0; li < 28; li++) - { - mark[li] = 0; - } // init the marks + if (Ureg >= 0 && Ureg < 28 && reg[Ureg] != 0) + { + free (reg[Ureg]); // free orig line reg- for 'U' + reg[Ureg] = 0; + } + if (YDreg >= 0 && YDreg < 28 && reg[YDreg] != 0) + { + free (reg[YDreg]); // free default yank/delete register + reg[YDreg] = 0; + } + for (li = 0; li < 28; li++) + { + mark[li] = 0; + } // init the marks #endif /* BB_FEATURE_VI_YANKMARK */ - // how many lines in text[]? - li = count_lines (text, end - 1); - psb ("\"%s\"%s" + // how many lines in text[]? + li = count_lines (text, end - 1); + psb ("\"%s\"%s" #ifdef BB_FEATURE_VI_READONLY - "%s" + "%s" #endif /* BB_FEATURE_VI_READONLY */ - " %dL, %dC", cfn, (sr < 0 ? " [New file]" : ""), + " %dL, %dC", cfn, (sr < 0 ? " [New file]" : ""), #ifdef BB_FEATURE_VI_READONLY - ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), + ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), #endif /* BB_FEATURE_VI_READONLY */ - li, ch); - } - else if (0) - { - // } else if (strncasecmp((char *) cmd, "file", i) == 0) { // what File is this - if (b != -1 || e != -1) - { - ni ((Byte *) "No address allowed on this command"); - goto vc1; - } - if (strlen ((char *) args) > 0) - { - // user wants a new filename - if (cfn != NULL) - free (cfn); - cfn = (Byte *) strdup ((char *) args); - } - else - { - // user wants file status info - edit_status (); - } - } - else if (strncasecmp ((char *) cmd, "features", i) == 0) - { // what features are available - // print out values of all features - place_cursor (rows - 1, 0, FALSE); // go to Status line, bottom of screen - clear_to_eol (); // clear the line - cookmode (); - show_help (); - rawmode (); - Hit_Return (); - } - else if (strncasecmp ((char *) cmd, "list", i) == 0) - { // literal print line - if (b < 0) - { // no addr given- use defaults - q = begin_line (dot); // assume .,. for the range - r = end_line (dot); - } - place_cursor (rows - 1, 0, FALSE); // go to Status line, bottom of screen - clear_to_eol (); // clear the line - write (1, "\r\n", 2); - for (; q <= r; q++) - { - c = *q; - if (c > '~') - standout_start (); - if (c == '\n') - { - write (1, "$\r", 2); - } - else if (*q < ' ') - { - write (1, "^", 1); - c += '@'; - } - write (1, &c, 1); - if (c > '~') - standout_end (); - } + li, ch); + } + else if (0) + { + // } else if (strncasecmp((char *) cmd, "file", i) == 0) { // what File is this + if (b != -1 || e != -1) + { + ni ((Byte *) "No address allowed on this command"); + goto vc1; + } + if (strlen ((char *) args) > 0) + { + // user wants a new filename + if (cfn != NULL) + free (cfn); + cfn = (Byte *) strdup ((char *) args); + } + else + { + // user wants file status info + edit_status (); + } + } + else if (strncasecmp ((char *) cmd, "features", i) == 0) + { // what features are available + // print out values of all features + place_cursor (rows - 1, 0, FALSE); // go to Status line, bottom of screen + clear_to_eol (); // clear the line + cookmode (); + show_help (); + rawmode (); + Hit_Return (); + } + else if (strncasecmp ((char *) cmd, "list", i) == 0) + { // literal print line + if (b < 0) + { // no addr given- use defaults + q = begin_line (dot); // assume .,. for the range + r = end_line (dot); + } + place_cursor (rows - 1, 0, FALSE); // go to Status line, bottom of screen + clear_to_eol (); // clear the line + write (1, "\r\n", 2); + for (; q <= r; q++) + { + c = *q; + if (c > '~') + standout_start (); + if (c == '\n') + { + write (1, "$\r", 2); + } + else if (*q < ' ') + { + write (1, "^", 1); + c += '@'; + } + write (1, &c, 1); + if (c > '~') + standout_end (); + } #ifdef BB_FEATURE_VI_SET - vc2: + vc2: #endif /* BB_FEATURE_VI_SET */ - Hit_Return (); - } - else if ((strncasecmp ((char *) cmd, "quit", i) == 0) || // Quit - (strncasecmp ((char *) cmd, "next", i) == 0)) - { // edit next file - if (useforce == TRUE) - { - // force end of argv list - if (*cmd == 'q') - { - optind = save_argc; - } - editing = 0; - goto vc1; - } - // don't exit if the file been modified - if (file_modified == TRUE) - { - psbs ("No write since last change (:%s! overrides)", - (*cmd == 'q' ? "quit" : "next")); - goto vc1; - } - // are there other file to edit - /* if (*cmd == 'q' && optind < save_argc - 1) { - psbs("%d more file to edit", (save_argc - optind - 1)); - goto vc1; - } - if (*cmd == 'n' && optind >= save_argc - 1) { - psbs("No more files to edit"); - goto vc1; - } */ - editing = 0; - } - else if (0) - { - // } else if (strncasecmp((char *) cmd, "read", i) == 0) { // read file into text[] - fn = args; - if (strlen ((char *) fn) <= 0) - { - psbs ("No filename given"); - goto vc1; - } - if (b < 0) - { // no addr given- use defaults - q = begin_line (dot); // assume "dot" - } - // read after current line- unless user said ":0r foo" - if (b != 0) - q = next_line (q); + Hit_Return (); + } + else if ((strncasecmp ((char *) cmd, "quit", i) == 0) || // Quit + (strncasecmp ((char *) cmd, "next", i) == 0)) + { // edit next file + if (useforce == TRUE) + { + // force end of argv list + if (*cmd == 'q') + { + optind = save_argc; + } + editing = 0; + goto vc1; + } + // don't exit if the file been modified + if (file_modified == TRUE) + { + psbs ("No write since last change (:%s! overrides)", + (*cmd == 'q' ? "quit" : "next")); + goto vc1; + } + // are there other file to edit + /* if (*cmd == 'q' && optind < save_argc - 1) { + psbs("%d more file to edit", (save_argc - optind - 1)); + goto vc1; + } + if (*cmd == 'n' && optind >= save_argc - 1) { + psbs("No more files to edit"); + goto vc1; + } */ + editing = 0; + } + else if (0) + { + // } else if (strncasecmp((char *) cmd, "read", i) == 0) { // read file into text[] + fn = args; + if (strlen ((char *) fn) <= 0) + { + psbs ("No filename given"); + goto vc1; + } + if (b < 0) + { // no addr given- use defaults + q = begin_line (dot); // assume "dot" + } + // read after current line- unless user said ":0r foo" + if (b != 0) + q = next_line (q); #ifdef BB_FEATURE_VI_READONLY - l = readonly; // remember current files' status + l = readonly; // remember current files' status #endif - ch = file_insert (fn, q, file_size (fn)); + ch = file_insert (fn, q, file_size (fn)); #ifdef BB_FEATURE_VI_READONLY - readonly = l; + readonly = l; #endif - if (ch < 0) - goto vc1; // nothing was inserted - // how many lines in text[]? - li = count_lines (q, q + ch - 1); - psb ("\"%s\"" + if (ch < 0) + goto vc1; // nothing was inserted + // how many lines in text[]? + li = count_lines (q, q + ch - 1); + psb ("\"%s\"" #ifdef BB_FEATURE_VI_READONLY - "%s" + "%s" #endif /* BB_FEATURE_VI_READONLY */ - " %dL, %dC", fn, + " %dL, %dC", fn, #ifdef BB_FEATURE_VI_READONLY - ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), + ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), #endif /* BB_FEATURE_VI_READONLY */ - li, ch); - if (ch > 0) - { - // if the insert is before "dot" then we need to update - if (q <= dot) - dot += ch; - file_modified = TRUE; - } - } - else if (strncasecmp ((char *) cmd, "rewind", i) == 0) - { // rewind cmd line args - if (file_modified == TRUE && useforce != TRUE) - { - psbs ("No write since last change (:rewind! overrides)"); - } - else - { - // reset the filenames to edit - optind = fn_start - 1; - editing = 0; - } + li, ch); + if (ch > 0) + { + // if the insert is before "dot" then we need to update + if (q <= dot) + dot += ch; + file_modified = TRUE; + } + } + else if (strncasecmp ((char *) cmd, "rewind", i) == 0) + { // rewind cmd line args + if (file_modified == TRUE && useforce != TRUE) + { + psbs ("No write since last change (:rewind! overrides)"); + } + else + { + // reset the filenames to edit + optind = fn_start - 1; + editing = 0; + } #ifdef BB_FEATURE_VI_SET - } - else if (strncasecmp ((char *) cmd, "set", i) == 0) - { // set or clear features - i = 0; // offset into args - if (strlen ((char *) args) == 0) - { - // print out values of all options - place_cursor (rows - 1, 0, FALSE); // go to Status line, bottom of screen - clear_to_eol (); // clear the line - printf ("----------------------------------------\r\n"); + } + else if (strncasecmp ((char *) cmd, "set", i) == 0) + { // set or clear features + i = 0; // offset into args + if (strlen ((char *) args) == 0) + { + // print out values of all options + place_cursor (rows - 1, 0, FALSE); // go to Status line, bottom of screen + clear_to_eol (); // clear the line + printf ("----------------------------------------\r\n"); #ifdef BB_FEATURE_VI_SETOPTS - if (!autoindent) - printf ("no"); - printf ("autoindent "); - if (!err_method) - printf ("no"); - printf ("flash "); - if (!ignorecase) - printf ("no"); - printf ("ignorecase "); - if (!showmatch) - printf ("no"); - printf ("showmatch "); - printf ("tabstop=%d ", tabstop); + if (!autoindent) + printf ("no"); + printf ("autoindent "); + if (!err_method) + printf ("no"); + printf ("flash "); + if (!ignorecase) + printf ("no"); + printf ("ignorecase "); + if (!showmatch) + printf ("no"); + printf ("showmatch "); + printf ("tabstop=%d ", tabstop); #endif /* BB_FEATURE_VI_SETOPTS */ - printf ("\r\n"); - goto vc2; - } - if (strncasecmp ((char *) args, "no", 2) == 0) - i = 2; // ":set noautoindent" + printf ("\r\n"); + goto vc2; + } + if (strncasecmp ((char *) args, "no", 2) == 0) + i = 2; // ":set noautoindent" #ifdef BB_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) - { - sscanf (strchr ((char *) args + i, '='), "=%d", &ch); - if (ch > 0 && ch < columns - 1) - tabstop = ch; - } + 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) + { + sscanf (strchr ((char *) args + i, '='), "=%d", &ch); + if (ch > 0 && ch < columns - 1) + tabstop = ch; + } #endif /* BB_FEATURE_VI_SETOPTS */ #endif /* BB_FEATURE_VI_SET */ #ifdef BB_FEATURE_VI_SEARCH - } - else if (strncasecmp ((char *) cmd, "s", 1) == 0) - { // substitute a pattern with a replacement pattern - Byte *ls, *F, *R; - int gflag; - - // F points to the "find" pattern - // R points to the "replace" pattern - // replace the cmd line delimiters "/" with NULLs - gflag = 0; // global replace flag - c = orig_buf[1]; // what is the delimiter - F = orig_buf + 2; // start of "find" - R = (Byte *) strchr ((char *) F, c); // middle delimiter - if (!R) - goto colon_s_fail; - *R++ = '\0'; // terminate "find" - buf1 = (Byte *) strchr ((char *) R, c); - if (!buf1) - goto colon_s_fail; - *buf1++ = '\0'; // terminate "replace" - if (*buf1 == 'g') - { // :s/foo/bar/g - buf1++; - gflag++; // turn on gflag - } - q = begin_line (q); - if (b < 0) - { // maybe :s/foo/bar/ - q = begin_line (dot); // start with cur line - b = count_lines (text, q); // cur line number - } - if (e < 0) - e = b; // maybe :.s/foo/bar/ - for (i = b; i <= e; i++) - { // so, :20,23 s \0 find \0 replace \0 - ls = q; // orig line start - vc4: - buf1 = char_search (q, F, FORWARD, LIMITED); // search cur line only for "find" - if (buf1 != NULL) - { - // we found the "find" pattern- delete it - (void) text_hole_delete (buf1, buf1 + strlen ((char *) F) - 1); - // inset the "replace" patern - (void) string_insert (buf1, R); // insert the string - // check for "global" :s/foo/bar/g - if (gflag == 1) - { - if ((buf1 + strlen ((char *) R)) < end_line (ls)) - { - q = buf1 + strlen ((char *) R); - goto vc4; // don't let q move past cur line - } - } - } - q = next_line (ls); - } + } + else if (strncasecmp ((char *) cmd, "s", 1) == 0) + { // substitute a pattern with a replacement pattern + Byte *ls, *F, *R; + int gflag; + + // F points to the "find" pattern + // R points to the "replace" pattern + // replace the cmd line delimiters "/" with NULLs + gflag = 0; // global replace flag + c = orig_buf[1]; // what is the delimiter + F = orig_buf + 2; // start of "find" + R = (Byte *) strchr ((char *) F, c); // middle delimiter + if (!R) + goto colon_s_fail; + *R++ = '\0'; // terminate "find" + buf1 = (Byte *) strchr ((char *) R, c); + if (!buf1) + goto colon_s_fail; + *buf1++ = '\0'; // terminate "replace" + if (*buf1 == 'g') + { // :s/foo/bar/g + buf1++; + gflag++; // turn on gflag + } + q = begin_line (q); + if (b < 0) + { // maybe :s/foo/bar/ + q = begin_line (dot); // start with cur line + b = count_lines (text, q); // cur line number + } + if (e < 0) + e = b; // maybe :.s/foo/bar/ + for (i = b; i <= e; i++) + { // so, :20,23 s \0 find \0 replace \0 + ls = q; // orig line start + vc4: + buf1 = char_search (q, F, FORWARD, LIMITED); // search cur line only for "find" + if (buf1 != NULL) + { + // we found the "find" pattern- delete it + (void) text_hole_delete (buf1, buf1 + strlen ((char *) F) - 1); + // inset the "replace" patern + (void) string_insert (buf1, R); // insert the string + // check for "global" :s/foo/bar/g + if (gflag == 1) + { + if ((buf1 + strlen ((char *) R)) < end_line (ls)) + { + q = buf1 + strlen ((char *) R); + goto vc4; // don't let q move past cur line + } + } + } + q = next_line (ls); + } #endif /* BB_FEATURE_VI_SEARCH */ - } - else if (strncasecmp ((char *) cmd, "version", i) == 0) - { // show software version - psb ("%s", vi_Version); - } - else if ((strncasecmp ((char *) cmd, "write", i) == 0) || // write text to file - (strncasecmp ((char *) cmd, "wq", i) == 0)) - { // write text to file - // is there a file name to write to? - /* if (strlen((char *) args) > 0) { - fn = args; - } */ + } + else if (strncasecmp ((char *) cmd, "version", i) == 0) + { // show software version + psb ("%s", vi_Version); + } + else if ((strncasecmp ((char *) cmd, "write", i) == 0) || // write text to file + (strncasecmp ((char *) cmd, "wq", i) == 0)) + { // write text to file + // is there a file name to write to? + /* if (strlen((char *) args) > 0) { + fn = args; + } */ #ifdef BB_FEATURE_VI_READONLY - if ((vi_readonly == TRUE || readonly == TRUE) && useforce == FALSE) - { - psbs ("\"%s\" File is read only", fn); - goto vc3; - } + if ((vi_readonly == TRUE || readonly == TRUE) && useforce == FALSE) + { + psbs ("\"%s\" File is read only", fn); + goto vc3; + } #endif /* BB_FEATURE_VI_READONLY */ - // how many lines in text[]? - li = count_lines (q, r); - ch = r - q + 1; - // see if file exists- if not, its just a new file request - if (useforce == TRUE) - { - // if "fn" is not write-able, chmod u+w - // sprintf(syscmd, "chmod u+w %s", fn); - // system(syscmd); - forced = TRUE; - } - l = file_write (fn, q, r); - if (useforce == TRUE && forced == TRUE) - { - // chmod u-w - // sprintf(syscmd, "chmod u-w %s", fn); - // system(syscmd); - forced = FALSE; - } - psb ("\"%s\" %dL, %dC", fn, li, l); - if (q == text && r == end - 1 && l == ch) - file_modified = FALSE; - if (cmd[1] == 'q' && l == ch) - { - editing = 0; - } + // how many lines in text[]? + li = count_lines (q, r); + ch = r - q + 1; + // see if file exists- if not, its just a new file request + if (useforce == TRUE) + { + // if "fn" is not write-able, chmod u+w + // sprintf(syscmd, "chmod u+w %s", fn); + // system(syscmd); + forced = TRUE; + } + l = file_write (fn, q, r); + if (useforce == TRUE && forced == TRUE) + { + // chmod u-w + // sprintf(syscmd, "chmod u-w %s", fn); + // system(syscmd); + forced = FALSE; + } + psb ("\"%s\" %dL, %dC", fn, li, l); + if (q == text && r == end - 1 && l == ch) + file_modified = FALSE; + if (cmd[1] == 'q' && l == ch) + { + editing = 0; + } #ifdef BB_FEATURE_VI_READONLY - vc3:; + vc3:; #endif /* BB_FEATURE_VI_READONLY */ #ifdef BB_FEATURE_VI_YANKMARK - } - else if (strncasecmp ((char *) cmd, "yank", i) == 0) - { // yank lines - if (b < 0) - { // no addr given- use defaults - q = begin_line (dot); // assume .,. for the range - r = end_line (dot); - } - text_yank (q, r, YDreg); - li = count_lines (q, r); - psb ("Yank %d lines (%d chars) into [%c]", - li, strlen ((char *) reg[YDreg]), what_reg ()); + } + else if (strncasecmp ((char *) cmd, "yank", i) == 0) + { // yank lines + if (b < 0) + { // no addr given- use defaults + q = begin_line (dot); // assume .,. for the range + r = end_line (dot); + } + text_yank (q, r, YDreg); + li = count_lines (q, r); + psb ("Yank %d lines (%d chars) into [%c]", + li, strlen ((char *) reg[YDreg]), what_reg ()); #endif /* BB_FEATURE_VI_YANKMARK */ - } - else - { - // cmd unknown - ni ((Byte *) cmd); - } + } + else + { + // cmd unknown + ni ((Byte *) cmd); + } vc1: - dot = bound_dot (dot); // make sure "dot" is valid - return; + dot = bound_dot (dot); // make sure "dot" is valid + return; #ifdef BB_FEATURE_VI_SEARCH colon_s_fail: - psb (":s expression missing delimiters"); - return; + psb (":s expression missing delimiters"); + return; #endif } @@ -2464,14 +2464,14 @@ colon_s_fail: static void Hit_Return (void) { - char c; - - standout_start (); // start reverse video - write (1, "[Hit return to continue]", 24); - standout_end (); // end reverse video - while ((c = get_one_char ()) != '\n' && c != '\r') /*do nothing */ - ; - redraw (TRUE); // force redraw all + char c; + + standout_start (); // start reverse video + write (1, "[Hit return to continue]", 24); + standout_end (); // end reverse video + while ((c = get_one_char ()) != '\n' && c != '\r') /*do nothing */ + ; + redraw (TRUE); // force redraw all } #endif /* BB_FEATURE_VI_COLON */ @@ -2479,326 +2479,326 @@ Hit_Return (void) static void sync_cursor (Byte * d, int *row, int *col) { - Byte *beg_cur, *end_cur; // begin and end of "d" line - Byte *beg_scr, *end_scr; // begin and end of screen - Byte *tp; - int cnt, ro, co; - - beg_cur = begin_line (d); // first char of cur line - end_cur = end_line (d); // last char of cur line - - beg_scr = end_scr = screenbegin; // first char of screen - end_scr = end_screen (); // last char of screen - - if (beg_cur < screenbegin) - { - // "d" is before top line on screen - // how many lines do we have to move - cnt = count_lines (beg_cur, screenbegin); - sc1: - screenbegin = beg_cur; - if (cnt > (rows - 1) / 2) - { - // we moved too many lines. put "dot" in middle of screen - for (cnt = 0; cnt < (rows - 1) / 2; cnt++) - { - screenbegin = prev_line (screenbegin); - } - } - } - else if (beg_cur > end_scr) - { - // "d" is after bottom line on screen - // how many lines do we have to move - cnt = count_lines (end_scr, beg_cur); - if (cnt > (rows - 1) / 2) - goto sc1; // too many lines - for (ro = 0; ro < cnt - 1; ro++) - { - // move screen begin the same amount - screenbegin = next_line (screenbegin); - // now, move the end of screen - end_scr = next_line (end_scr); - end_scr = end_line (end_scr); - } - } - // "d" is on screen- find out which row - tp = screenbegin; - for (ro = 0; ro < rows - 1; ro++) - { // drive "ro" to correct row - if (tp == beg_cur) - break; - tp = next_line (tp); - } - - // find out what col "d" is on - co = 0; - do - { // drive "co" to correct column - if (*tp == '\n' || *tp == '\0') - break; - if (*tp == '\t') - { - // 7 - (co % 8 ) - co += ((tabstop - 1) - (co % tabstop)); - } - else if (*tp < ' ') - { - co++; // display as ^X, use 2 columns - } - } - while (tp++ < d && ++co); - - // "co" is the column where "dot" is. - // The screen has "columns" columns. - // The currently displayed columns are 0+offset -- columns+ofset - // |-------------------------------------------------------------| - // ^ ^ ^ - // offset | |------- columns ----------------| - // - // If "co" is already in this range then we do not have to adjust offset - // but, we do have to subtract the "offset" bias from "co". - // If "co" is outside this range then we have to change "offset". - // If the first char of a line is a tab the cursor will try to stay - // in column 7, but we have to set offset to 0. - - if (co < 0 + offset) - { - offset = co; - } - if (co >= columns + offset) - { - offset = co - columns + 1; - } - // if the first char of the line is a tab, and "dot" is sitting on it - // force offset to 0. - if (d == beg_cur && *d == '\t') - { - offset = 0; - } - co -= offset; - - *row = ro; - *col = co; + Byte *beg_cur, *end_cur; // begin and end of "d" line + Byte *beg_scr, *end_scr; // begin and end of screen + Byte *tp; + int cnt, ro, co; + + beg_cur = begin_line (d); // first char of cur line + end_cur = end_line (d); // last char of cur line + + beg_scr = end_scr = screenbegin; // first char of screen + end_scr = end_screen (); // last char of screen + + if (beg_cur < screenbegin) + { + // "d" is before top line on screen + // how many lines do we have to move + cnt = count_lines (beg_cur, screenbegin); + sc1: + screenbegin = beg_cur; + if (cnt > (rows - 1) / 2) + { + // we moved too many lines. put "dot" in middle of screen + for (cnt = 0; cnt < (rows - 1) / 2; cnt++) + { + screenbegin = prev_line (screenbegin); + } + } + } + else if (beg_cur > end_scr) + { + // "d" is after bottom line on screen + // how many lines do we have to move + cnt = count_lines (end_scr, beg_cur); + if (cnt > (rows - 1) / 2) + goto sc1; // too many lines + for (ro = 0; ro < cnt - 1; ro++) + { + // move screen begin the same amount + screenbegin = next_line (screenbegin); + // now, move the end of screen + end_scr = next_line (end_scr); + end_scr = end_line (end_scr); + } + } + // "d" is on screen- find out which row + tp = screenbegin; + for (ro = 0; ro < rows - 1; ro++) + { // drive "ro" to correct row + if (tp == beg_cur) + break; + tp = next_line (tp); + } + + // find out what col "d" is on + co = 0; + do + { // drive "co" to correct column + if (*tp == '\n' || *tp == '\0') + break; + if (*tp == '\t') + { + // 7 - (co % 8 ) + co += ((tabstop - 1) - (co % tabstop)); + } + else if (*tp < ' ') + { + co++; // display as ^X, use 2 columns + } + } + while (tp++ < d && ++co); + + // "co" is the column where "dot" is. + // The screen has "columns" columns. + // The currently displayed columns are 0+offset -- columns+ofset + // |-------------------------------------------------------------| + // ^ ^ ^ + // offset | |------- columns ----------------| + // + // If "co" is already in this range then we do not have to adjust offset + // but, we do have to subtract the "offset" bias from "co". + // If "co" is outside this range then we have to change "offset". + // If the first char of a line is a tab the cursor will try to stay + // in column 7, but we have to set offset to 0. + + if (co < 0 + offset) + { + offset = co; + } + if (co >= columns + offset) + { + offset = co - columns + 1; + } + // if the first char of the line is a tab, and "dot" is sitting on it + // force offset to 0. + if (d == beg_cur && *d == '\t') + { + offset = 0; + } + co -= offset; + + *row = ro; + *col = co; } //----- Text Movement Routines --------------------------------- static Byte * -begin_line (Byte * p) // return pointer to first char cur line +begin_line (Byte * p) // return pointer to first char cur line { - while (p > text && p[-1] != '\n') - p--; // go to cur line B-o-l - return (p); + while (p > text && p[-1] != '\n') + p--; // go to cur line B-o-l + return (p); } static Byte * -end_line (Byte * p) // return pointer to NL of cur line line +end_line (Byte * p) // return pointer to NL of cur line line { - while (p < end - 1 && *p != '\n') - p++; // go to cur line E-o-l - return (p); + while (p < end - 1 && *p != '\n') + p++; // go to cur line E-o-l + return (p); } static Byte * -dollar_line (Byte * p) // return pointer to just before NL line +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 - // Try to stay off of the Newline - if (*p == '\n' && (p - begin_line (p)) > 0) - p--; - return (p); + while (p < end - 1 && *p != '\n') + p++; // go to cur line E-o-l + // Try to stay off of the Newline + if (*p == '\n' && (p - begin_line (p)) > 0) + p--; + return (p); } static Byte * -prev_line (Byte * p) // return pointer first char prev line +prev_line (Byte * p) // return pointer first char prev line { - p = begin_line (p); // goto begining of cur line - if (p[-1] == '\n' && p > text) - p--; // step to prev line - p = begin_line (p); // goto begining of prev line - return (p); + p = begin_line (p); // goto begining of cur line + if (p[-1] == '\n' && p > text) + p--; // step to prev line + p = begin_line (p); // goto begining of prev line + return (p); } static Byte * -next_line (Byte * p) // return pointer first char next line +next_line (Byte * p) // return pointer first char next line { - p = end_line (p); - if (*p == '\n' && p < end - 1) - p++; // step to next line - return (p); + p = end_line (p); + if (*p == '\n' && p < end - 1) + p++; // step to next line + return (p); } //----- Text Information Routines ------------------------------ static Byte * end_screen (void) { - Byte *q; - int cnt; - - // find new bottom line - q = screenbegin; - for (cnt = 0; cnt < rows - 2; cnt++) - q = next_line (q); - q = end_line (q); - return (q); + Byte *q; + int cnt; + + // find new bottom line + q = screenbegin; + for (cnt = 0; cnt < rows - 2; cnt++) + q = next_line (q); + q = end_line (q); + return (q); } static int -count_lines (Byte * start, Byte * stop) // count line from start to stop +count_lines (Byte * start, Byte * stop) // count line from start to stop { - Byte *q; - int cnt; - - if (stop < start) - { // start and stop are backwards- reverse them - q = start; - start = stop; - stop = q; - } - cnt = 0; - stop = end_line (stop); // get to end of this line - for (q = start; q <= stop && q <= end - 1; q++) - { - if (*q == '\n') - cnt++; - } - return (cnt); + Byte *q; + int cnt; + + if (stop < start) + { // start and stop are backwards- reverse them + q = start; + start = stop; + stop = q; + } + cnt = 0; + stop = end_line (stop); // get to end of this line + for (q = start; q <= stop && q <= end - 1; q++) + { + if (*q == '\n') + cnt++; + } + return (cnt); } static Byte * -find_line (int li) // find begining of line #li +find_line (int li) // find begining of line #li { - Byte *q; + Byte *q; - for (q = text; li > 1; li--) - { - q = next_line (q); - } - return (q); + for (q = text; li > 1; li--) + { + q = next_line (q); + } + return (q); } //----- Dot Movement Routines ---------------------------------- static void dot_left (void) { - if (dot > text && dot[-1] != '\n') - dot--; + if (dot > text && dot[-1] != '\n') + dot--; } static void dot_right (void) { - if (dot < end - 1 && *dot != '\n') - dot++; + if (dot < end - 1 && *dot != '\n') + dot++; } static void dot_begin (void) { - dot = begin_line (dot); // return pointer to first char cur line + dot = begin_line (dot); // return pointer to first char cur line } static void dot_end (void) { - dot = end_line (dot); // return pointer to last char cur line + dot = end_line (dot); // return pointer to last char cur line } static Byte * move_to_col (Byte * p, int l) { - int co; - - p = begin_line (p); - co = 0; - do - { - if (*p == '\n' || *p == '\0') - break; - if (*p == '\t') - { - // 7 - (co % 8 ) - co += ((tabstop - 1) - (co % tabstop)); - } - else if (*p < ' ') - { - co++; // display as ^X, use 2 columns - } - } - while (++co <= l && p++ < end); - return (p); + int co; + + p = begin_line (p); + co = 0; + do + { + if (*p == '\n' || *p == '\0') + break; + if (*p == '\t') + { + // 7 - (co % 8 ) + co += ((tabstop - 1) - (co % tabstop)); + } + else if (*p < ' ') + { + co++; // display as ^X, use 2 columns + } + } + while (++co <= l && p++ < end); + return (p); } static void dot_next (void) { - dot = next_line (dot); + dot = next_line (dot); } static void dot_prev (void) { - dot = prev_line (dot); + dot = prev_line (dot); } static void dot_scroll (int cnt, int dir) { - Byte *q; - - for (; cnt > 0; cnt--) - { - if (dir < 0) - { - // scroll Backwards - // ctrl-Y scroll up one line - screenbegin = prev_line (screenbegin); - } - else - { - // scroll Forwards - // ctrl-E scroll down one line - screenbegin = next_line (screenbegin); - } - } - // make sure "dot" stays on the screen so we dont scroll off - if (dot < screenbegin) - dot = screenbegin; - q = end_screen (); // find new bottom line - if (dot > q) - dot = begin_line (q); // is dot is below bottom line? - dot_skip_over_ws (); + Byte *q; + + for (; cnt > 0; cnt--) + { + if (dir < 0) + { + // scroll Backwards + // ctrl-Y scroll up one line + screenbegin = prev_line (screenbegin); + } + else + { + // scroll Forwards + // ctrl-E scroll down one line + screenbegin = next_line (screenbegin); + } + } + // make sure "dot" stays on the screen so we dont scroll off + if (dot < screenbegin) + dot = screenbegin; + q = end_screen (); // find new bottom line + if (dot > q) + dot = begin_line (q); // is dot is below bottom line? + dot_skip_over_ws (); } static void dot_skip_over_ws (void) { - // skip WS - while (isspace (*dot) && *dot != '\n' && dot < end - 1) - dot++; + // skip WS + while (isspace (*dot) && *dot != '\n' && dot < end - 1) + dot++; } static void -dot_delete (void) // delete the char at 'dot' +dot_delete (void) // delete the char at 'dot' { - (void) text_hole_delete (dot, dot); + (void) text_hole_delete (dot, dot); } static Byte * -bound_dot (Byte * p) // make sure text[0] <= P < "end" +bound_dot (Byte * p) // make sure text[0] <= P < "end" { - if (p >= end && end > text) - { - p = end - 1; - indicate_error ('1'); - } - if (p < text) - { - p = text; - indicate_error ('2'); - } - return (p); + if (p >= end && end > text) + { + p = end - 1; + indicate_error ('1'); + } + if (p < text) + { + p = text; + indicate_error ('2'); + } + return (p); } //----- Helper Utility Routines -------------------------------- @@ -2817,422 +2817,422 @@ bound_dot (Byte * p) // make sure text[0] <= P < "end" static Byte * new_screen (int ro, int co) { - int li; - - if (screen != 0) - free (screen); - screensize = ro * co + 8; - screen = (Byte *) malloc (screensize); - // initialize the new screen. assume this will be a empty file. - screen_erase (); - // non-existant text[] lines start with a tilde (~). - for (li = 1; li < ro - 1; li++) - { - screen[(li * co) + 0] = '~'; - } - return (screen); + int li; + + if (screen != 0) + free (screen); + screensize = ro * co + 8; + screen = (Byte *) malloc (screensize); + // initialize the new screen. assume this will be a empty file. + screen_erase (); + // non-existant text[] lines start with a tilde (~). + for (li = 1; li < ro - 1; li++) + { + screen[(li * co) + 0] = '~'; + } + return (screen); } static Byte * new_text (int size) { - if (size < 10240) - size = 10240; // have a minimum size for new files - if (text != 0) - { - //text -= 4; - free (text); - } - text = (Byte *) malloc (size + 8); - memset (text, '\0', size); // clear new text[] - //text += 4; // leave some room for "oops" - textend = text + size - 1; - //textend -= 4; // leave some root for "oops" - return (text); + if (size < 10240) + size = 10240; // have a minimum size for new files + if (text != 0) + { + //text -= 4; + free (text); + } + text = (Byte *) malloc (size + 8); + memset (text, '\0', size); // clear new text[] + //text += 4; // leave some room for "oops" + textend = text + size - 1; + //textend -= 4; // leave some root for "oops" + return (text); } #ifdef BB_FEATURE_VI_SEARCH static int mycmp (Byte * s1, Byte * s2, int len) { - int i; + int i; - i = strncmp ((char *) s1, (char *) s2, len); + i = strncmp ((char *) s1, (char *) s2, len); #ifdef BB_FEATURE_VI_SETOPTS - if (ignorecase) - { - i = strncasecmp ((char *) s1, (char *) s2, len); - } + if (ignorecase) + { + i = strncasecmp ((char *) s1, (char *) s2, len); + } #endif /* BB_FEATURE_VI_SETOPTS */ - return (i); + return (i); } static Byte * -char_search (Byte * p, Byte * pat, int dir, int range) // search for pattern starting at p +char_search (Byte * p, Byte * pat, int dir, int range) // search for pattern starting at p { #ifndef REGEX_SEARCH - Byte *start, *stop; - int len; - - len = strlen ((char *) pat); - if (dir == FORWARD) - { - stop = end - 1; // assume range is p - end-1 - if (range == LIMITED) - stop = next_line (p); // range is to next line - for (start = p; start < stop; start++) - { - if (mycmp (start, pat, len) == 0) - { - return (start); - } - } - } - else if (dir == BACK) - { - stop = text; // assume range is text - p - if (range == LIMITED) - stop = prev_line (p); // range is to prev line - for (start = p - len; start >= stop; start--) - { - if (mycmp (start, pat, len) == 0) - { - return (start); - } - } - } - // pattern not found - return (NULL); -#else /*REGEX_SEARCH */ - char *q; - struct re_pattern_buffer preg; - int i; - int size, range; - - re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; - preg.translate = 0; - preg.fastmap = 0; - preg.buffer = 0; - preg.allocated = 0; - - // assume a LIMITED forward search - q = next_line (p); - q = end_line (q); - q = end - 1; - if (dir == BACK) - { - q = prev_line (p); - q = text; - } - // count the number of chars to search over, forward or backward - size = q - p; - if (size < 0) - size = p - q; - // RANGE could be negative if we are searching backwards - range = q - p; - - q = (char *) re_compile_pattern (pat, strlen ((char *) pat), &preg); - if (q != 0) - { - // The pattern was not compiled - psbs ("bad search pattern: \"%s\": %s", pat, q); - i = 0; // return p if pattern not compiled - goto cs1; - } - - q = p; - if (range < 0) - { - q = p - size; - if (q < text) - q = text; - } - // search for the compiled pattern, preg, in p[] - // range < 0- search backward - // range > 0- search forward - // 0 < start < size - // re_search() < 0 not found or error - // re_search() > 0 index of found pattern - // struct pattern char int int int struct reg - // re_search (*pattern_buffer, *string, size, start, range, *regs) - i = re_search (&preg, q, size, 0, range, 0); - if (i == -1) - { - p = 0; - i = 0; // return NULL if pattern not found - } + Byte *start, *stop; + int len; + + len = strlen ((char *) pat); + if (dir == FORWARD) + { + stop = end - 1; // assume range is p - end-1 + if (range == LIMITED) + stop = next_line (p); // range is to next line + for (start = p; start < stop; start++) + { + if (mycmp (start, pat, len) == 0) + { + return (start); + } + } + } + else if (dir == BACK) + { + stop = text; // assume range is text - p + if (range == LIMITED) + stop = prev_line (p); // range is to prev line + for (start = p - len; start >= stop; start--) + { + if (mycmp (start, pat, len) == 0) + { + return (start); + } + } + } + // pattern not found + return (NULL); +#else /*REGEX_SEARCH */ + char *q; + struct re_pattern_buffer preg; + int i; + int size, range; + + re_syntax_options = RE_SYNTAX_POSIX_EXTENDED; + preg.translate = 0; + preg.fastmap = 0; + preg.buffer = 0; + preg.allocated = 0; + + // assume a LIMITED forward search + q = next_line (p); + q = end_line (q); + q = end - 1; + if (dir == BACK) + { + q = prev_line (p); + q = text; + } + // count the number of chars to search over, forward or backward + size = q - p; + if (size < 0) + size = p - q; + // RANGE could be negative if we are searching backwards + range = q - p; + + q = (char *) re_compile_pattern (pat, strlen ((char *) pat), &preg); + if (q != 0) + { + // The pattern was not compiled + psbs ("bad search pattern: \"%s\": %s", pat, q); + i = 0; // return p if pattern not compiled + goto cs1; + } + + q = p; + if (range < 0) + { + q = p - size; + if (q < text) + q = text; + } + // search for the compiled pattern, preg, in p[] + // range < 0- search backward + // range > 0- search forward + // 0 < start < size + // re_search() < 0 not found or error + // re_search() > 0 index of found pattern + // struct pattern char int int int struct reg + // re_search (*pattern_buffer, *string, size, start, range, *regs) + i = re_search (&preg, q, size, 0, range, 0); + if (i == -1) + { + p = 0; + i = 0; // return NULL if pattern not found + } cs1: - if (dir == FORWARD) - { - p = p + i; - } - else - { - p = p - i; - } - return (p); + if (dir == FORWARD) + { + p = p + i; + } + else + { + p = p - i; + } + return (p); #endif /*REGEX_SEARCH */ } #endif /* BB_FEATURE_VI_SEARCH */ static Byte * -char_insert (Byte * p, Byte c) // insert the char c at 'p' +char_insert (Byte * p, Byte c) // insert the char c at 'p' { - if (c == 22) - { // Is this an ctrl-V? - p = stupid_insert (p, '^'); // use ^ to indicate literal next - p--; // backup onto ^ - refresh (FALSE); // show the ^ - c = get_one_char (); - *p = c; - p++; - file_modified = TRUE; // has the file been modified - } - else if (c == 27) - { // Is this an ESC? - cmd_mode = 0; - cmdcnt = 0; - end_cmd_q (); // stop adding to q - strcpy ((char *) status_buffer, " "); // clear the status buffer - if ((p[-1] != '\n') && (dot > text)) - { - p--; - } - } - else if (c == erase_char) - { // Is this a BS - // 123456789 - if ((p[-1] != '\n') && (dot > text)) - { - p--; - p = text_hole_delete (p, p); // shrink buffer 1 char + if (c == 22) + { // Is this an ctrl-V? + p = stupid_insert (p, '^'); // use ^ to indicate literal next + p--; // backup onto ^ + refresh (FALSE); // show the ^ + c = get_one_char (); + *p = c; + p++; + file_modified = TRUE; // has the file been modified + } + else if (c == 27) + { // Is this an ESC? + cmd_mode = 0; + cmdcnt = 0; + end_cmd_q (); // stop adding to q + strcpy ((char *) status_buffer, " "); // clear the status buffer + if ((p[-1] != '\n') && (dot > text)) + { + p--; + } + } + else if (c == erase_char) + { // Is this a BS + // 123456789 + if ((p[-1] != '\n') && (dot > text)) + { + p--; + p = text_hole_delete (p, p); // shrink buffer 1 char #ifdef BB_FEATURE_VI_DOT_CMD - // also rmove char from last_modifying_cmd - if (strlen ((char *) last_modifying_cmd) > 0) - { - Byte *q; - - q = last_modifying_cmd; - q[strlen ((char *) q) - 1] = '\0'; // erase BS - q[strlen ((char *) q) - 1] = '\0'; // erase prev char - } + // also rmove char from last_modifying_cmd + if (strlen ((char *) last_modifying_cmd) > 0) + { + Byte *q; + + q = last_modifying_cmd; + q[strlen ((char *) q) - 1] = '\0'; // erase BS + q[strlen ((char *) q) - 1] = '\0'; // erase prev char + } #endif /* BB_FEATURE_VI_DOT_CMD */ - } - } - else - { - // insert a char into text[] - Byte *sp; // "save p" - - if (c == 13) - c = '\n'; // translate \r to \n - sp = p; // remember addr of insert - p = stupid_insert (p, c); // insert the char + } + } + else + { + // insert a char into text[] + Byte *sp; // "save p" + + if (c == 13) + c = '\n'; // translate \r to \n + sp = p; // remember addr of insert + p = stupid_insert (p, c); // insert the char #ifdef BB_FEATURE_VI_SETOPTS - if (showmatch && strchr (")]}", *sp) != NULL) - { - showmatching (sp); - } - if (autoindent && c == '\n') - { // auto indent the new line - Byte *q; - - q = prev_line (p); // use prev line as templet - for (; isblnk (*q); q++) - { - p = stupid_insert (p, *q); // insert the char - } - } + if (showmatch && strchr (")]}", *sp) != NULL) + { + showmatching (sp); + } + if (autoindent && c == '\n') + { // auto indent the new line + Byte *q; + + q = prev_line (p); // use prev line as templet + for (; isblnk (*q); q++) + { + p = stupid_insert (p, *q); // insert the char + } + } #endif /* BB_FEATURE_VI_SETOPTS */ - } - return (p); + } + return (p); } static Byte * -stupid_insert (Byte * p, Byte c) // stupidly insert the char c at 'p' +stupid_insert (Byte * p, Byte c) // stupidly insert the char c at 'p' { - p = text_hole_make (p, 1); - if (p != 0) - { - *p = c; - file_modified = TRUE; // has the file been modified - p++; - } - return (p); + p = text_hole_make (p, 1); + if (p != 0) + { + *p = c; + file_modified = TRUE; // has the file been modified + p++; + } + return (p); } static Byte find_range (Byte ** start, Byte ** stop, Byte c) { - Byte *save_dot, *p, *q; - int cnt; - - save_dot = dot; - p = q = dot; - - if (strchr ("cdy><", c)) - { - // these cmds operate on whole lines - p = q = begin_line (p); - for (cnt = 1; cnt < cmdcnt; cnt++) - { - q = next_line (q); - } - q = end_line (q); - } - else if (strchr ("^%$0bBeEft", c)) - { - // These cmds operate on char positions - do_cmd (c); // execute movement cmd - q = dot; - } - else if (strchr ("wW", c)) - { - do_cmd (c); // execute movement cmd - if (dot > text) - dot--; // move back off of next word - if (dot > text && *dot == '\n') - dot--; // stay off NL - q = dot; - } - else if (strchr ("H-k{", c)) - { - // these operate on multi-lines backwards - q = end_line (dot); // find NL - do_cmd (c); // execute movement cmd - dot_begin (); - p = dot; - } - else if (strchr ("L+j}\r\n", c)) - { - // these operate on multi-lines forwards - p = begin_line (dot); - do_cmd (c); // execute movement cmd - dot_end (); // find NL - q = dot; - } - else - { - c = 27; // error- return an ESC char - //break; - } - *start = p; - *stop = q; - if (q < p) - { - *start = q; - *stop = p; - } - dot = save_dot; - return (c); + Byte *save_dot, *p, *q; + int cnt; + + save_dot = dot; + p = q = dot; + + if (strchr ("cdy><", c)) + { + // these cmds operate on whole lines + p = q = begin_line (p); + for (cnt = 1; cnt < cmdcnt; cnt++) + { + q = next_line (q); + } + q = end_line (q); + } + else if (strchr ("^%$0bBeEft", c)) + { + // These cmds operate on char positions + do_cmd (c); // execute movement cmd + q = dot; + } + else if (strchr ("wW", c)) + { + do_cmd (c); // execute movement cmd + if (dot > text) + dot--; // move back off of next word + if (dot > text && *dot == '\n') + dot--; // stay off NL + q = dot; + } + else if (strchr ("H-k{", c)) + { + // these operate on multi-lines backwards + q = end_line (dot); // find NL + do_cmd (c); // execute movement cmd + dot_begin (); + p = dot; + } + else if (strchr ("L+j}\r\n", c)) + { + // these operate on multi-lines forwards + p = begin_line (dot); + do_cmd (c); // execute movement cmd + dot_end (); // find NL + q = dot; + } + else + { + c = 27; // error- return an ESC char + //break; + } + *start = p; + *stop = q; + if (q < p) + { + *start = q; + *stop = p; + } + dot = save_dot; + return (c); } static int st_test (Byte * p, int type, int dir, Byte * tested) { - Byte c, c0, ci; - int test, inc; - - inc = dir; - c = c0 = p[0]; - ci = p[inc]; - test = 0; - - if (type == S_BEFORE_WS) - { - c = ci; - test = ((!isspace (c)) || c == '\n'); - } - if (type == S_TO_WS) - { - c = c0; - test = ((!isspace (c)) || c == '\n'); - } - if (type == S_OVER_WS) - { - c = c0; - test = ((isspace (c))); - } - if (type == S_END_PUNCT) - { - c = ci; - test = ((ispunct (c))); - } - if (type == S_END_ALNUM) - { - c = ci; - test = ((isalnum (c)) || c == '_'); - } - *tested = c; - return (test); + Byte c, c0, ci; + int test, inc; + + inc = dir; + c = c0 = p[0]; + ci = p[inc]; + test = 0; + + if (type == S_BEFORE_WS) + { + c = ci; + test = ((!isspace (c)) || c == '\n'); + } + if (type == S_TO_WS) + { + c = c0; + test = ((!isspace (c)) || c == '\n'); + } + if (type == S_OVER_WS) + { + c = c0; + test = ((isspace (c))); + } + if (type == S_END_PUNCT) + { + c = ci; + test = ((ispunct (c))); + } + if (type == S_END_ALNUM) + { + c = ci; + test = ((isalnum (c)) || c == '_'); + } + *tested = c; + return (test); } static Byte * skip_thing (Byte * p, int linecnt, int dir, int type) { - Byte c; - - while (st_test (p, type, dir, &c)) - { - // make sure we limit search to correct number of lines - if (c == '\n' && --linecnt < 1) - break; - if (dir >= 0 && p >= end - 1) - break; - if (dir < 0 && p <= text) - break; - p += dir; // move to next char - } - return (p); + Byte c; + + while (st_test (p, type, dir, &c)) + { + // make sure we limit search to correct number of lines + if (c == '\n' && --linecnt < 1) + break; + if (dir >= 0 && p >= end - 1) + break; + if (dir < 0 && p <= text) + break; + p += dir; // move to next char + } + return (p); } // find matching char of pair () [] {} static Byte * find_pair (Byte * p, Byte c) { - Byte match, *q; - int dir, level; - - match = ')'; - level = 1; - dir = 1; // assume forward - switch (c) - { - case '(': - match = ')'; - break; - case '[': - match = ']'; - break; - case '{': - match = '}'; - break; - case ')': - match = '('; - dir = -1; - break; - case ']': - match = '['; - dir = -1; - break; - case '}': - match = '{'; - dir = -1; - break; - } - for (q = p + dir; text <= q && q < end; q += dir) - { - // look for match, count levels of pairs (( )) - if (*q == c) - level++; // increase pair levels - if (*q == match) - level--; // reduce pair level - if (level == 0) - break; // found matching pair - } - if (level != 0) - q = NULL; // indicate no match - return (q); + Byte match, *q; + int dir, level; + + match = ')'; + level = 1; + dir = 1; // assume forward + switch (c) + { + case '(': + match = ')'; + break; + case '[': + match = ']'; + break; + case '{': + match = '}'; + break; + case ')': + match = '('; + dir = -1; + break; + case ']': + match = '['; + dir = -1; + break; + case '}': + match = '{'; + dir = -1; + break; + } + for (q = p + dir; text <= q && q < end; q += dir) + { + // look for match, count levels of pairs (( )) + if (*q == c) + level++; // increase pair levels + if (*q == match) + level--; // reduce pair level + if (level == 0) + break; // found matching pair + } + if (level != 0) + q = NULL; // indicate no match + return (q); } #ifdef BB_FEATURE_VI_SETOPTS @@ -3240,87 +3240,87 @@ find_pair (Byte * p, Byte c) static void showmatching (Byte * p) { - Byte *q, *save_dot; - - // we found half of a pair - q = find_pair (p, *p); // get loc of matching char - if (q == NULL) - { - indicate_error ('3'); // no matching char - } - else - { - // "q" now points to matching pair - save_dot = dot; // remember where we are - dot = q; // go to new loc - refresh (FALSE); // let the user see it - (void) mysleep (40); // give user some time - dot = save_dot; // go back to old loc - refresh (FALSE); - } + Byte *q, *save_dot; + + // we found half of a pair + q = find_pair (p, *p); // get loc of matching char + if (q == NULL) + { + indicate_error ('3'); // no matching char + } + else + { + // "q" now points to matching pair + save_dot = dot; // remember where we are + dot = q; // go to new loc + refresh (FALSE); // let the user see it + (void) mysleep (40); // give user some time + dot = save_dot; // go back to old loc + refresh (FALSE); + } } #endif /* BB_FEATURE_VI_SETOPTS */ // open a hole in text[] static Byte * -text_hole_make (Byte * p, int size) // at "p", make a 'size' byte hole +text_hole_make (Byte * p, int size) // at "p", make a 'size' byte hole { - Byte *src, *dest; - int cnt; - - if (size <= 0) - goto thm0; - src = p; - dest = p + size; - cnt = end - src; // the rest of buffer - if (memmove (dest, src, cnt) != dest) - { - psbs ("can't create room for new characters"); - } - memset (p, ' ', size); // clear new hole - end = end + size; // adjust the new END - file_modified = TRUE; // has the file been modified + Byte *src, *dest; + int cnt; + + if (size <= 0) + goto thm0; + src = p; + dest = p + size; + cnt = end - src; // the rest of buffer + if (memmove (dest, src, cnt) != dest) + { + psbs ("can't create room for new characters"); + } + memset (p, ' ', size); // clear new hole + end = end + size; // adjust the new END + file_modified = TRUE; // has the file been modified thm0: - return (p); + return (p); } // close a hole in text[] static Byte * -text_hole_delete (Byte * p, Byte * q) // delete "p" thru "q", inclusive +text_hole_delete (Byte * p, Byte * q) // delete "p" thru "q", inclusive { - Byte *src, *dest; - int cnt, hole_size; - - // move forwards, from beginning - // assume p <= q - src = q + 1; - dest = p; - if (q < p) - { // they are backward- swap them - src = p + 1; - dest = q; - } - hole_size = q - p + 1; - cnt = end - src; - if (src < text || src > end) - goto thd0; - if (dest < text || dest >= end) - goto thd0; - if (src >= end) - goto thd_atend; // just delete the end of the buffer - if (memmove (dest, src, cnt) != dest) - { - psbs ("can't delete the character"); - } + Byte *src, *dest; + int cnt, hole_size; + + // move forwards, from beginning + // assume p <= q + src = q + 1; + dest = p; + if (q < p) + { // they are backward- swap them + src = p + 1; + dest = q; + } + hole_size = q - p + 1; + cnt = end - src; + if (src < text || src > end) + goto thd0; + if (dest < text || dest >= end) + goto thd0; + if (src >= end) + goto thd_atend; // just delete the end of the buffer + if (memmove (dest, src, cnt) != dest) + { + psbs ("can't delete the character"); + } thd_atend: - end = end - hole_size; // adjust the new END - if (dest >= end) - dest = end - 1; // make sure dest in below end-1 - if (end <= text) - dest = end = text; // keep pointers valid - file_modified = TRUE; // has the file been modified + end = end - hole_size; // adjust the new END + if (dest >= end) + dest = end - 1; // make sure dest in below end-1 + if (end <= text) + dest = end = text; // keep pointers valid + file_modified = TRUE; // has the file been modified thd0: - return (dest); + return (dest); } // copy text into register, then delete text. @@ -3329,272 +3329,272 @@ thd0: static Byte * yank_delete (Byte * start, Byte * stop, int dist, int yf) { - Byte *p; - - // make sure start <= stop - if (start > stop) - { - // they are backwards, reverse them - p = start; - start = stop; - stop = p; - } - if (dist <= 0) - { - // we can not cross NL boundaries - p = start; - if (*p == '\n') - return (p); - // dont go past a NewLine - for (; p + 1 <= stop; p++) - { - if (p[1] == '\n') - { - stop = p; // "stop" just before NewLine - break; - } - } - } - p = start; + Byte *p; + + // make sure start <= stop + if (start > stop) + { + // they are backwards, reverse them + p = start; + start = stop; + stop = p; + } + if (dist <= 0) + { + // we can not cross NL boundaries + p = start; + if (*p == '\n') + return (p); + // dont go past a NewLine + for (; p + 1 <= stop; p++) + { + if (p[1] == '\n') + { + stop = p; // "stop" just before NewLine + break; + } + } + } + p = start; #ifdef BB_FEATURE_VI_YANKMARK - text_yank (start, stop, YDreg); + text_yank (start, stop, YDreg); #endif /* BB_FEATURE_VI_YANKMARK */ - if (yf == YANKDEL) - { - p = text_hole_delete (start, stop); - } // delete lines - return (p); + if (yf == YANKDEL) + { + p = text_hole_delete (start, stop); + } // delete lines + return (p); } static void show_help (void) { - fprintf (stderr, "version: %s\n", vi_Version); - puts ("These features are available:" + fprintf (stderr, "version: %s\n", vi_Version); + puts ("These features are available:" #ifdef BB_FEATURE_VI_SEARCH - "\n\tPattern searches with / and ?" + "\n\tPattern searches with / and ?" #endif /* BB_FEATURE_VI_SEARCH */ #ifdef BB_FEATURE_VI_DOT_CMD - "\n\tLast command repeat with \'.\'" + "\n\tLast command repeat with \'.\'" #endif /* BB_FEATURE_VI_DOT_CMD */ #ifdef BB_FEATURE_VI_YANKMARK - "\n\tLine marking with 'x" "\n\tNamed buffers with \"x" + "\n\tLine marking with 'x" "\n\tNamed buffers with \"x" #endif /* BB_FEATURE_VI_YANKMARK */ #ifdef BB_FEATURE_VI_READONLY - "\n\tReadonly if vi is called as \"view\"" - "\n\tReadonly with -R command line arg" + "\n\tReadonly if vi is called as \"view\"" + "\n\tReadonly with -R command line arg" #endif /* BB_FEATURE_VI_READONLY */ #ifdef BB_FEATURE_VI_SET - "\n\tSome colon mode commands with \':\'" + "\n\tSome colon mode commands with \':\'" #endif /* BB_FEATURE_VI_SET */ #ifdef BB_FEATURE_VI_SETOPTS - "\n\tSettable options with \":set\"" + "\n\tSettable options with \":set\"" #endif /* BB_FEATURE_VI_SETOPTS */ #ifdef BB_FEATURE_VI_USE_SIGNALS - "\n\tSignal catching- ^C" "\n\tJob suspend and resume with ^Z" + "\n\tSignal catching- ^C" "\n\tJob suspend and resume with ^Z" #endif /* BB_FEATURE_VI_USE_SIGNALS */ #ifdef BB_FEATURE_VI_WIN_RESIZE - "\n\tAdapt to window re-sizes" + "\n\tAdapt to window re-sizes" #endif /* BB_FEATURE_VI_WIN_RESIZE */ - ); + ); } static void -print_literal (Byte * buf, Byte * s) // copy s to buf, convert unprintable +print_literal (Byte * buf, Byte * s) // copy s to buf, convert unprintable { - Byte c, b[2]; - - b[1] = '\0'; - strcpy ((char *) buf, ""); // init buf - if (strlen ((char *) s) <= 0) - s = (Byte *) "(NULL)"; - for (; *s > '\0'; s++) - { - c = *s; - if (*s > '~') - { - strcat ((char *) buf, SOs); - c = *s - 128; - } - if (*s < ' ') - { - strcat ((char *) buf, "^"); - c += '@'; - } - b[0] = c; - strcat ((char *) buf, (char *) b); - if (*s > '~') - strcat ((char *) buf, SOn); - if (*s == '\n') - { - strcat ((char *) buf, "$"); - } - } + Byte c, b[2]; + + b[1] = '\0'; + strcpy ((char *) buf, ""); // init buf + if (strlen ((char *) s) <= 0) + s = (Byte *) "(NULL)"; + for (; *s > '\0'; s++) + { + c = *s; + if (*s > '~') + { + strcat ((char *) buf, SOs); + c = *s - 128; + } + if (*s < ' ') + { + strcat ((char *) buf, "^"); + c += '@'; + } + b[0] = c; + strcat ((char *) buf, (char *) b); + if (*s > '~') + strcat ((char *) buf, SOn); + if (*s == '\n') + { + strcat ((char *) buf, "$"); + } + } } #ifdef BB_FEATURE_VI_DOT_CMD static void start_new_cmd_q (Byte c) { - // release old cmd - if (last_modifying_cmd != 0) - free (last_modifying_cmd); - // get buffer for new cmd - last_modifying_cmd = (Byte *) malloc (BUFSIZ); - memset (last_modifying_cmd, '\0', BUFSIZ); // clear new cmd queue - // if there is a current cmd count put it in the buffer first - if (cmdcnt > 0) - sprintf ((char *) last_modifying_cmd, "%d", cmdcnt); - // save char c onto queue - last_modifying_cmd[strlen ((char *) last_modifying_cmd)] = c; - adding2q = 1; - return; + // release old cmd + if (last_modifying_cmd != 0) + free (last_modifying_cmd); + // get buffer for new cmd + last_modifying_cmd = (Byte *) malloc (BUFSIZ); + memset (last_modifying_cmd, '\0', BUFSIZ); // clear new cmd queue + // if there is a current cmd count put it in the buffer first + if (cmdcnt > 0) + sprintf ((char *) last_modifying_cmd, "%d", cmdcnt); + // save char c onto queue + last_modifying_cmd[strlen ((char *) last_modifying_cmd)] = c; + adding2q = 1; + return; } static void end_cmd_q () { #ifdef BB_FEATURE_VI_YANKMARK - YDreg = 26; // go back to default Yank/Delete reg + YDreg = 26; // go back to default Yank/Delete reg #endif /* BB_FEATURE_VI_YANKMARK */ - adding2q = 0; - return; + adding2q = 0; + return; } #endif /* BB_FEATURE_VI_DOT_CMD */ #if defined(BB_FEATURE_VI_YANKMARK) || defined(BB_FEATURE_VI_COLON) || defined(BB_FEATURE_VI_CRASHME) static Byte * -string_insert (Byte * p, Byte * s) // insert the string at 'p' +string_insert (Byte * p, Byte * s) // insert the string at 'p' { - int cnt, i; - - i = strlen ((char *) s); - p = text_hole_make (p, i); - strncpy ((char *) p, (char *) s, i); - for (cnt = 0; *s != '\0'; s++) - { - if (*s == '\n') - cnt++; - } + int cnt, i; + + i = strlen ((char *) s); + p = text_hole_make (p, i); + strncpy ((char *) p, (char *) s, i); + for (cnt = 0; *s != '\0'; s++) + { + if (*s == '\n') + cnt++; + } #ifdef BB_FEATURE_VI_YANKMARK - psb ("Put %d lines (%d chars) from [%c]", cnt, i, what_reg ()); + psb ("Put %d lines (%d chars) from [%c]", cnt, i, what_reg ()); #endif /* BB_FEATURE_VI_YANKMARK */ - return (p); + return (p); } #endif /* BB_FEATURE_VI_YANKMARK || BB_FEATURE_VI_COLON || BB_FEATURE_VI_CRASHME */ #ifdef BB_FEATURE_VI_YANKMARK static Byte * -text_yank (Byte * p, Byte * q, int dest) // copy text into a register +text_yank (Byte * p, Byte * q, int dest) // copy text into a register { - Byte *t; - int cnt; - - if (q < p) - { // they are backwards- reverse them - t = q; - q = p; - p = t; - } - cnt = q - p + 1; - t = reg[dest]; - if (t != 0) - { // if already a yank register - free (t); // free it - } - t = (Byte *) malloc (cnt + 1); // get a new register - memset (t, '\0', cnt + 1); // clear new text[] - strncpy ((char *) t, (char *) p, cnt); // copy text[] into bufer - reg[dest] = t; - return (p); + Byte *t; + int cnt; + + if (q < p) + { // they are backwards- reverse them + t = q; + q = p; + p = t; + } + cnt = q - p + 1; + t = reg[dest]; + if (t != 0) + { // if already a yank register + free (t); // free it + } + t = (Byte *) malloc (cnt + 1); // get a new register + memset (t, '\0', cnt + 1); // clear new text[] + strncpy ((char *) t, (char *) p, cnt); // copy text[] into bufer + reg[dest] = t; + return (p); } static Byte what_reg (void) { - Byte c; - int i; - - i = 0; - c = 'D'; // default to D-reg - if (0 <= YDreg && YDreg <= 25) - c = 'a' + (Byte) YDreg; - if (YDreg == 26) - c = 'D'; - if (YDreg == 27) - c = 'U'; - return (c); + Byte c; + int i; + + i = 0; + c = 'D'; // default to D-reg + if (0 <= YDreg && YDreg <= 25) + c = 'a' + (Byte) YDreg; + if (YDreg == 26) + c = 'D'; + if (YDreg == 27) + c = 'U'; + return (c); } static void check_context (Byte cmd) { - // A context is defined to be "modifying text" - // Any modifying command establishes a new context. - - if (dot < context_start || dot > context_end) - { - if (strchr ((char *) modifying_cmds, cmd) != NULL) - { - // we are trying to modify text[]- make this the current context - mark[27] = mark[26]; // move cur to prev - mark[26] = dot; // move local to cur - context_start = prev_line (prev_line (dot)); - context_end = next_line (next_line (dot)); - //loiter= start_loiter= now; - } - } - return; + // A context is defined to be "modifying text" + // Any modifying command establishes a new context. + + if (dot < context_start || dot > context_end) + { + if (strchr ((char *) modifying_cmds, cmd) != NULL) + { + // we are trying to modify text[]- make this the current context + mark[27] = mark[26]; // move cur to prev + mark[26] = dot; // move local to cur + context_start = prev_line (prev_line (dot)); + context_end = next_line (next_line (dot)); + //loiter= start_loiter= now; + } + } + return; } static Byte * -swap_context (Byte * p) // goto new context for '' command make this the current context +swap_context (Byte * p) // goto new context for '' command make this the current context { - Byte *tmp; - - // the current context is in mark[26] - // the previous context is in mark[27] - // only swap context if other context is valid - if (text <= mark[27] && mark[27] <= end - 1) - { - tmp = mark[27]; - mark[27] = mark[26]; - mark[26] = tmp; - p = mark[26]; // where we are going- previous context - context_start = prev_line (prev_line (prev_line (p))); - context_end = next_line (next_line (next_line (p))); - } - return (p); + Byte *tmp; + + // the current context is in mark[26] + // the previous context is in mark[27] + // only swap context if other context is valid + if (text <= mark[27] && mark[27] <= end - 1) + { + tmp = mark[27]; + mark[27] = mark[26]; + mark[26] = tmp; + p = mark[26]; // where we are going- previous context + context_start = prev_line (prev_line (prev_line (p))); + context_end = next_line (next_line (next_line (p))); + } + return (p); } #endif /* BB_FEATURE_VI_YANKMARK */ static int -isblnk (Byte c) // is the char a blank or tab +isblnk (Byte c) // is the char a blank or tab { - return (c == ' ' || c == '\t'); + return (c == ' ' || c == '\t'); } //----- Set terminal attributes -------------------------------- static void rawmode (void) { - tcgetattr (0, &term_orig); - term_vi = term_orig; - term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG ON- allow intr's - term_vi.c_iflag &= (~IXON & ~ICRNL); - term_vi.c_oflag &= (~ONLCR); + tcgetattr (0, &term_orig); + term_vi = term_orig; + term_vi.c_lflag &= (~ICANON & ~ECHO); // leave ISIG ON- allow intr's + term_vi.c_iflag &= (~IXON & ~ICRNL); + term_vi.c_oflag &= (~ONLCR); #ifndef linux - term_vi.c_cc[VMIN] = 1; - term_vi.c_cc[VTIME] = 0; + term_vi.c_cc[VMIN] = 1; + term_vi.c_cc[VTIME] = 0; #endif - erase_char = term_vi.c_cc[VERASE]; - tcsetattr (0, TCSANOW, &term_vi); + erase_char = term_vi.c_cc[VERASE]; + tcsetattr (0, TCSANOW, &term_vi); } static void cookmode (void) { - tcsetattr (0, TCSANOW, &term_orig); + tcsetattr (0, TCSANOW, &term_orig); } #ifdef BB_FEATURE_VI_WIN_RESIZE @@ -3602,25 +3602,25 @@ cookmode (void) static void window_size_get (int sig) { - int i; - - i = ioctl (0, TIOCGWINSZ, &winsize); - if (i != 0) - { - // force 24x80 - winsize.ws_row = 24; - winsize.ws_col = 80; - } - if (winsize.ws_row <= 1) - { - winsize.ws_row = 24; - } - if (winsize.ws_col <= 1) - { - winsize.ws_col = 80; - } - rows = (int) winsize.ws_row; - columns = (int) winsize.ws_col; + int i; + + i = ioctl (0, TIOCGWINSZ, &winsize); + if (i != 0) + { + // force 24x80 + winsize.ws_row = 24; + winsize.ws_col = 80; + } + if (winsize.ws_row <= 1) + { + winsize.ws_row = 24; + } + if (winsize.ws_col <= 1) + { + winsize.ws_col = 80; + } + rows = (int) winsize.ws_row; + columns = (int) winsize.ws_col; } #endif /* BB_FEATURE_VI_WIN_RESIZE */ @@ -3629,429 +3629,429 @@ window_size_get (int sig) static void winch_sig (int sig) { - signal (SIGWINCH, winch_sig); + signal (SIGWINCH, winch_sig); #ifdef BB_FEATURE_VI_WIN_RESIZE - window_size_get (0); + window_size_get (0); #endif /* BB_FEATURE_VI_WIN_RESIZE */ - new_screen (rows, columns); // get memory for virtual screen - redraw (TRUE); // re-draw the screen + new_screen (rows, columns); // get memory for virtual screen + redraw (TRUE); // re-draw the screen } //----- Come here when we get a continue signal ------------------- static void cont_sig (int sig) { - rawmode (); // terminal to "raw" - *status_buffer = '\0'; // clear the status buffer - redraw (TRUE); // re-draw the screen + rawmode (); // terminal to "raw" + *status_buffer = '\0'; // clear the status buffer + redraw (TRUE); // re-draw the screen - signal (SIGTSTP, suspend_sig); - signal (SIGCONT, SIG_DFL); - kill (getpid (), SIGCONT); + signal (SIGTSTP, suspend_sig); + signal (SIGCONT, SIG_DFL); + kill (getpid (), SIGCONT); } //----- Come here when we get a Suspend signal ------------------- static void suspend_sig (int sig) { - place_cursor (rows - 1, 0, FALSE); // go to bottom of screen - clear_to_eol (); // Erase to end of line - cookmode (); // terminal to "cooked" + place_cursor (rows - 1, 0, FALSE); // go to bottom of screen + clear_to_eol (); // Erase to end of line + cookmode (); // terminal to "cooked" - signal (SIGCONT, cont_sig); - signal (SIGTSTP, SIG_DFL); - kill (getpid (), SIGTSTP); + signal (SIGCONT, cont_sig); + signal (SIGTSTP, SIG_DFL); + kill (getpid (), SIGTSTP); } //----- Come here when we get a signal --------------------------- static void catch_sig (int sig) { - signal (SIGHUP, catch_sig); - signal (SIGINT, catch_sig); - signal (SIGTERM, catch_sig); - longjmp (restart, 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); - longjmp (restart, sig); + signal (SIGALRM, catch_sig); + longjmp (restart, sig); } //----- Come here when we get a core dump signal ----------------- static void core_sig (int 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); + 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); + signal (SIGSYS, core_sig); #endif - dot = bound_dot (dot); // make sure "dot" is valid + dot = bound_dot (dot); // make sure "dot" is valid - longjmp (restart, sig); + longjmp (restart, sig); } #endif /* BB_FEATURE_VI_USE_SIGNALS */ static int -mysleep (int hund) // sleep for 'h' 1/100 seconds +mysleep (int hund) // sleep for 'h' 1/100 seconds { - // Don't hang- Wait 5/100 seconds- 1 Sec= 1000000 - FD_ZERO (&rfds); - FD_SET (0, &rfds); - tv.tv_sec = 0; - tv.tv_usec = hund * 10000; - select (1, &rfds, NULL, NULL, &tv); - return (FD_ISSET (0, &rfds)); + // Don't hang- Wait 5/100 seconds- 1 Sec= 1000000 + FD_ZERO (&rfds); + FD_SET (0, &rfds); + tv.tv_sec = 0; + tv.tv_usec = hund * 10000; + select (1, &rfds, NULL, NULL, &tv); + return (FD_ISSET (0, &rfds)); } //----- IO Routines -------------------------------------------- static Byte -readit (void) // read (maybe cursor) key from stdin +readit (void) // read (maybe cursor) key from stdin { - Byte c; - int i, bufsiz, cnt; - unsigned int cmdindex; - struct esc_cmds - { - Byte *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 - }; + Byte c; + int i, bufsiz, cnt; + unsigned int cmdindex; + struct esc_cmds + { + Byte *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 + }; #define ESCCMDS_COUNT (sizeof(esccmds)/sizeof(struct esc_cmds)) - // (void) alarm(0); // turn alarm OFF while we wait for input - // get input from User- are there already input chars in Q? - bufsiz = strlen ((char *) readbuffer); - if (bufsiz <= 0) - { - ri0: - // the Q is empty, wait for a typed char - bufsiz = read (0, readbuffer, BUFSIZ - 1); - if (bufsiz < 0) - { - if (errno == EINTR) - goto ri0; // interrupted sys call - if (errno == EBADF) - editing = 0; - if (errno == EFAULT) - editing = 0; - if (errno == EINVAL) - editing = 0; - 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; - - // 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 - // be a Function or Cursor Key sequence. - FD_ZERO (&rfds); - FD_SET (0, &rfds); - tv.tv_sec = 0; - 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)) - { - // 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 - } - } - // 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) - { - // 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'; - } - break; - } - } + // (void) alarm(0); // turn alarm OFF while we wait for input + // get input from User- are there already input chars in Q? + bufsiz = strlen ((char *) readbuffer); + if (bufsiz <= 0) + { + ri0: + // the Q is empty, wait for a typed char + bufsiz = read (0, readbuffer, BUFSIZ - 1); + if (bufsiz < 0) + { + if (errno == EINTR) + goto ri0; // interrupted sys call + if (errno == EBADF) + editing = 0; + if (errno == EFAULT) + editing = 0; + if (errno == EINVAL) + editing = 0; + 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; + + // 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 + // be a Function or Cursor Key sequence. + FD_ZERO (&rfds); + FD_SET (0, &rfds); + tv.tv_sec = 0; + 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)) + { + // 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 + } + } + // 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) + { + // 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'; + } + break; + } + } ri1: - c = readbuffer[0]; - // remove one char from Q - memmove (readbuffer, readbuffer + 1, BUFSIZ - 1); - readbuffer[BUFSIZ - 1] = '\0'; - // (void) alarm(3); // we are done waiting for input, turn alarm ON - return (c); + c = readbuffer[0]; + // remove one char from Q + memmove (readbuffer, readbuffer + 1, BUFSIZ - 1); + readbuffer[BUFSIZ - 1] = '\0'; + // (void) alarm(3); // we are done waiting for input, turn alarm ON + return (c); } //----- IO Routines -------------------------------------------- static Byte get_one_char () { - static Byte c; + static Byte c; #ifdef BB_FEATURE_VI_DOT_CMD - // ! adding2q && ioq == 0 read() - // ! adding2q && ioq != 0 *ioq - // adding2q *last_modifying_cmd= read() - if (!adding2q) - { - // we are not adding to the q. - // but, we may be reading from a q - if (ioq == 0) - { - // there is no current q, read from STDIN - c = readit (); // get the users input - } - else - { - // there is a queue to get chars from first - c = *ioq++; - if (c == '\0') - { - // the end of the q, read from STDIN - free (ioq_start); - ioq_start = ioq = 0; - c = readit (); // get the users input - } - } - } - else - { - // adding STDIN chars to q - c = readit (); // get the users input - if (last_modifying_cmd != 0) - { - // add new char to q - last_modifying_cmd[strlen ((char *) last_modifying_cmd)] = c; - } - } -#else /* BB_FEATURE_VI_DOT_CMD */ - c = readit (); // get the users input + // ! adding2q && ioq == 0 read() + // ! adding2q && ioq != 0 *ioq + // adding2q *last_modifying_cmd= read() + if (!adding2q) + { + // we are not adding to the q. + // but, we may be reading from a q + if (ioq == 0) + { + // there is no current q, read from STDIN + c = readit (); // get the users input + } + else + { + // there is a queue to get chars from first + c = *ioq++; + if (c == '\0') + { + // the end of the q, read from STDIN + free (ioq_start); + ioq_start = ioq = 0; + c = readit (); // get the users input + } + } + } + else + { + // adding STDIN chars to q + c = readit (); // get the users input + if (last_modifying_cmd != 0) + { + // add new char to q + last_modifying_cmd[strlen ((char *) last_modifying_cmd)] = c; + } + } +#else /* BB_FEATURE_VI_DOT_CMD */ + c = readit (); // get the users input #endif /* BB_FEATURE_VI_DOT_CMD */ - return (c); // return the char, where ever it came from + return (c); // return the char, where ever it came from } static Byte * -get_input_line (Byte * prompt) // get input line- use "status line" +get_input_line (Byte * prompt) // get input line- use "status line" { - Byte buf[BUFSIZ]; - Byte c; - int i; - static Byte *obufp = NULL; - - strcpy ((char *) buf, (char *) prompt); - *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 - - for (i = strlen ((char *) buf); i < BUFSIZ;) - { - c = get_one_char (); // read user input - if (c == '\n' || c == '\r' || c == 27) - break; // is this end of input - if (c == erase_char) - { // user wants to erase prev char - 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 - 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 - i++; - } - } - refresh (FALSE); - if (obufp != NULL) - free (obufp); - obufp = (Byte *) strdup ((char *) buf); - return (obufp); + Byte buf[BUFSIZ]; + Byte c; + int i; + static Byte *obufp = NULL; + + strcpy ((char *) buf, (char *) prompt); + *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 + + for (i = strlen ((char *) buf); i < BUFSIZ;) + { + c = get_one_char (); // read user input + if (c == '\n' || c == '\r' || c == 27) + break; // is this end of input + if (c == erase_char) + { // user wants to erase prev char + 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 + 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 + i++; + } + } + refresh (FALSE); + if (obufp != NULL) + free (obufp); + obufp = (Byte *) strdup ((char *) buf); + return (obufp); } static int -file_size (Byte * fn) // what is the byte size of "fn" +file_size (Byte * fn) // what is the byte size of "fn" { - struct stat st_buf; - int cnt, sr; - - if (fn == 0 || strlen (fn) <= 0) - return (-1); - cnt = -1; - sr = stat ((char *) fn, &st_buf); // see if file exists - if (sr >= 0) - { - cnt = (int) st_buf.st_size; - } - return (cnt); + struct stat st_buf; + int cnt, sr; + + if (fn == 0 || strlen (fn) <= 0) + return (-1); + cnt = -1; + sr = stat ((char *) fn, &st_buf); // see if file exists + if (sr >= 0) + { + cnt = (int) st_buf.st_size; + } + return (cnt); } static int file_insert (Byte * fn, Byte * p, int size) { - int fd, cnt; + int fd, cnt; - cnt = -1; + cnt = -1; #ifdef BB_FEATURE_VI_READONLY - readonly = FALSE; + readonly = FALSE; #endif /* BB_FEATURE_VI_READONLY */ - if (fn == 0 || strlen ((char *) fn) <= 0) - { - psbs ("No filename given"); - goto fi0; - } - if (size == 0) - { - // OK- this is just a no-op - cnt = 0; - goto fi0; - } - if (size < 0) - { - psbs ("Trying to insert a negative number (%d) of characters", size); - goto fi0; - } - if (p < text || p > end) - { - psbs ("Trying to insert file outside of memory"); - goto fi0; - } - - // see if we can open the file + if (fn == 0 || strlen ((char *) fn) <= 0) + { + psbs ("No filename given"); + goto fi0; + } + if (size == 0) + { + // OK- this is just a no-op + cnt = 0; + goto fi0; + } + if (size < 0) + { + psbs ("Trying to insert a negative number (%d) of characters", size); + goto fi0; + } + if (p < text || p > end) + { + psbs ("Trying to insert file outside of memory"); + goto fi0; + } + + // see if we can open the file #ifdef BB_FEATURE_VI_READONLY - if (vi_readonly == TRUE) - goto fi1; // do not try write-mode + if (vi_readonly == TRUE) + goto fi1; // do not try write-mode #endif - fd = open ((char *) fn, O_RDWR); // assume read & write - if (fd < 0) - { - // could not open for writing- maybe file is read only + fd = open ((char *) fn, O_RDWR); // assume read & write + if (fd < 0) + { + // could not open for writing- maybe file is read only #ifdef BB_FEATURE_VI_READONLY - fi1: + fi1: #endif - fd = open ((char *) fn, O_RDONLY); // try read-only - if (fd < 0) - { - psbs ("\"%s\" %s", fn, "could not open file"); - goto fi0; - } + fd = open ((char *) fn, O_RDONLY); // try read-only + if (fd < 0) + { + psbs ("\"%s\" %s", fn, "could not open file"); + goto fi0; + } #ifdef BB_FEATURE_VI_READONLY - // got the file- read-only - readonly = TRUE; + // got the file- read-only + readonly = TRUE; #endif /* BB_FEATURE_VI_READONLY */ - } - p = text_hole_make (p, size); - cnt = read (fd, p, size); - close (fd); - if (cnt < 0) - { - cnt = -1; - p = text_hole_delete (p, p + size - 1); // un-do buffer insert - psbs ("could not read file \"%s\"", fn); - } - else if (cnt < size) - { - // There was a partial read, shrink unused space text[] - p = text_hole_delete (p + cnt, p + (size - cnt) - 1); // un-do buffer insert - psbs ("could not read all of file \"%s\"", fn); - } - if (cnt >= size) - file_modified = TRUE; + } + p = text_hole_make (p, size); + cnt = read (fd, p, size); + close (fd); + if (cnt < 0) + { + cnt = -1; + p = text_hole_delete (p, p + size - 1); // un-do buffer insert + psbs ("could not read file \"%s\"", fn); + } + else if (cnt < size) + { + // There was a partial read, shrink unused space text[] + p = text_hole_delete (p + cnt, p + (size - cnt) - 1); // un-do buffer insert + psbs ("could not read all of file \"%s\"", fn); + } + if (cnt >= size) + file_modified = TRUE; fi0: - return (cnt); + return (cnt); } static int file_write (Byte * fn, Byte * first, Byte * last) { - int fd, cnt, charcnt; - - if (fn == 0) - { - psbs ("No current filename"); - return (-1); - } - charcnt = 0; - // FIXIT- use the correct umask() - fd = open ((char *) fn, (O_WRONLY | O_CREAT | O_TRUNC), 0664); - if (fd < 0) - return (-1); - cnt = last - first + 1; - charcnt = write (fd, first, cnt); - if (charcnt == cnt) - { - // good write - //file_modified= FALSE; // the file has not been modified - } - else - { - charcnt = 0; - } - close (fd); - return (charcnt); + int fd, cnt, charcnt; + + if (fn == 0) + { + psbs ("No current filename"); + return (-1); + } + charcnt = 0; + // FIXIT- use the correct umask() + fd = open ((char *) fn, (O_WRONLY | O_CREAT | O_TRUNC), 0664); + if (fd < 0) + return (-1); + cnt = last - first + 1; + charcnt = write (fd, first, cnt); + if (charcnt == cnt) + { + // good write + //file_modified= FALSE; // the file has not been modified + } + else + { + charcnt = 0; + } + close (fd); + return (charcnt); } //----- Terminal Drawing --------------------------------------- @@ -4070,136 +4070,136 @@ file_write (Byte * fn, Byte * first, Byte * last) static void place_cursor (int row, int col, int opti) { - char cm1[BUFSIZ]; - char *cm; - int l; + char cm1[BUFSIZ]; + char *cm; + int l; #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - char cm2[BUFSIZ]; - Byte *screenp; - // char cm3[BUFSIZ]; - int Rrow = last_row; + char cm2[BUFSIZ]; + Byte *screenp; + // char cm3[BUFSIZ]; + int Rrow = last_row; #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - memset (cm1, '\0', BUFSIZ - 1); // clear the buffer + memset (cm1, '\0', BUFSIZ - 1); // clear the buffer - if (row < 0) - row = 0; - if (row >= rows) - row = rows - 1; - if (col < 0) - col = 0; - if (col >= columns) - col = columns - 1; + if (row < 0) + row = 0; + if (row >= rows) + row = rows - 1; + if (col < 0) + col = 0; + if (col >= columns) + col = columns - 1; - //----- 1. Try the standard terminal ESC sequence - sprintf ((char *) cm1, CMrc, row + 1, col + 1); - cm = cm1; - if (opti == FALSE) - goto pc0; + //----- 1. Try the standard terminal ESC sequence + sprintf ((char *) cm1, CMrc, row + 1, col + 1); + cm = cm1; + if (opti == FALSE) + goto pc0; #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - //----- find the minimum # of chars to move cursor ------------- - //----- 2. Try moving with discreet chars (Newline, [back]space, ...) - memset (cm2, '\0', BUFSIZ - 1); // clear the buffer - - // move to the correct row - while (row < Rrow) - { - // the cursor has to move up - strcat (cm2, CMup); - Rrow--; - } - while (row > Rrow) - { - // the cursor has to move down - strcat (cm2, CMdown); - Rrow++; - } - - // now move to the correct column - strcat (cm2, "\r"); // start at col 0 - // just send out orignal source char to get to correct place - screenp = &screen[row * columns]; // start of screen line - strncat (cm2, screenp, col); - - //----- 3. Try some other way of moving cursor - //--------------------------------------------- - - // pick the shortest cursor motion to send out - cm = cm1; - if (strlen (cm2) < strlen (cm)) - { - cm = cm2; - } /* else if (strlen(cm3) < strlen(cm)) { - cm= cm3; - } */ + //----- find the minimum # of chars to move cursor ------------- + //----- 2. Try moving with discreet chars (Newline, [back]space, ...) + memset (cm2, '\0', BUFSIZ - 1); // clear the buffer + + // move to the correct row + while (row < Rrow) + { + // the cursor has to move up + strcat (cm2, CMup); + Rrow--; + } + while (row > Rrow) + { + // the cursor has to move down + strcat (cm2, CMdown); + Rrow++; + } + + // now move to the correct column + strcat (cm2, "\r"); // start at col 0 + // just send out orignal source char to get to correct place + screenp = &screen[row * columns]; // start of screen line + strncat (cm2, screenp, col); + + //----- 3. Try some other way of moving cursor + //--------------------------------------------- + + // pick the shortest cursor motion to send out + cm = cm1; + if (strlen (cm2) < strlen (cm)) + { + cm = cm2; + } /* else if (strlen(cm3) < strlen(cm)) { + cm= cm3; + } */ #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ pc0: - l = strlen (cm); - if (l) - write (1, cm, l); // move the cursor + l = strlen (cm); + if (l) + write (1, cm, l); // 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 + write (1, Ceol, strlen (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 + write (1, Ceos, strlen (Ceos)); // Erase from cursor to end of screen } //----- Start standout mode ------------------------------------ static void -standout_start () // send "start reverse video" sequence +standout_start () // send "start reverse video" sequence { - write (1, SOs, strlen (SOs)); // Start reverse video mode + write (1, SOs, strlen (SOs)); // Start reverse video mode } //----- End standout mode -------------------------------------- static void -standout_end () // send "end reverse video" sequence +standout_end () // send "end reverse video" sequence { - write (1, SOn, strlen (SOn)); // End reverse video mode + write (1, SOn, strlen (SOn)); // End reverse video mode } //----- Flash the screen -------------------------------------- static void flash (int h) { - standout_start (); // send "start reverse video" sequence - redraw (TRUE); - (void) mysleep (h); - standout_end (); // send "end reverse video" sequence - redraw (TRUE); + standout_start (); // send "start reverse video" sequence + redraw (TRUE); + (void) mysleep (h); + standout_end (); // send "end reverse video" sequence + redraw (TRUE); } static void beep () { - write (1, bell, strlen (bell)); // send out a bell character + write (1, bell, strlen (bell)); // send out a bell character } static void indicate_error (char c) { #ifdef BB_FEATURE_VI_CRASHME - if (crashme > 0) - return; // generate a random command + if (crashme > 0) + return; // generate a random command #endif /* BB_FEATURE_VI_CRASHME */ - if (err_method == 0) - { - beep (); - } - else - { - flash (10); - } + if (err_method == 0) + { + beep (); + } + else + { + flash (10); + } } //----- Screen[] Routines -------------------------------------- @@ -4207,30 +4207,30 @@ indicate_error (char c) static void screen_erase () { - memset (screen, ' ', screensize); // clear new screen + memset (screen, ' ', screensize); // clear new screen } //----- Draw the status line at bottom of the screen ------------- static void show_status_line (void) { - static int last_cksum; - int l, cnt, cksum; - - cnt = strlen ((char *) status_buffer); - for (cksum = l = 0; l < cnt; l++) - { - cksum += (int) (status_buffer[l]); - } - // don't write the status line unless it changes - 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); - clear_to_eol (); - place_cursor (crow, ccol, FALSE); // put cursor back in correct place - } + static int last_cksum; + int l, cnt, cksum; + + cnt = strlen ((char *) status_buffer); + for (cksum = l = 0; l < cnt; l++) + { + cksum += (int) (status_buffer[l]); + } + // don't write the status line unless it changes + 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); + clear_to_eol (); + place_cursor (crow, ccol, FALSE); // put cursor back in correct place + } } //----- format the status buffer, the bottom line of screen ------ @@ -4238,124 +4238,124 @@ show_status_line (void) static void psbs (char *format, ...) { - va_list args; + va_list args; - va_start (args, format); - strcpy ((char *) status_buffer, SOs); // Terminal standout mode on - vsprintf ((char *) status_buffer + strlen ((char *) status_buffer), format, - args); - strcat ((char *) status_buffer, SOn); // Terminal standout mode off - va_end (args); + va_start (args, format); + strcpy ((char *) status_buffer, SOs); // Terminal standout mode on + vsprintf ((char *) status_buffer + strlen ((char *) status_buffer), format, + args); + strcat ((char *) status_buffer, SOn); // Terminal standout mode off + va_end (args); - return; + return; } // print status buffer static void psb (char *format, ...) { - va_list args; + va_list args; - va_start (args, format); - vsprintf ((char *) status_buffer, format, args); - va_end (args); - return; + va_start (args, format); + vsprintf ((char *) status_buffer, format, args); + va_end (args); + return; } static void -ni (Byte * s) // display messages +ni (Byte * s) // display messages { - Byte buf[BUFSIZ]; + Byte buf[BUFSIZ]; - print_literal (buf, s); - psbs ("\'%s\' is not implemented", buf); + print_literal (buf, s); + psbs ("\'%s\' is not implemented", buf); } static void -edit_status (void) // show file status on status line +edit_status (void) // show file status on status line { - int cur, tot, percent; - - cur = count_lines (text, dot); - tot = count_lines (text, end - 1); - // current line percent - // ------------- ~~ ---------- - // total lines 100 - if (tot > 0) - { - percent = (100 * cur) / tot; - } - else - { - cur = tot = 0; - percent = 100; - } - psb ("\"%s\"" + int cur, tot, percent; + + cur = count_lines (text, dot); + tot = count_lines (text, end - 1); + // current line percent + // ------------- ~~ ---------- + // total lines 100 + if (tot > 0) + { + percent = (100 * cur) / tot; + } + else + { + cur = tot = 0; + percent = 100; + } + psb ("\"%s\"" #ifdef BB_FEATURE_VI_READONLY - "%s" + "%s" #endif /* BB_FEATURE_VI_READONLY */ - "%s line %d of %d --%d%%--", (cfn != 0 ? (char *) cfn : "No file"), + "%s line %d of %d --%d%%--", (cfn != 0 ? (char *) cfn : "No file"), #ifdef BB_FEATURE_VI_READONLY - ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), + ((vi_readonly == TRUE || readonly == TRUE) ? " [Read only]" : ""), #endif /* BB_FEATURE_VI_READONLY */ - (file_modified == TRUE ? " [modified]" : ""), cur, tot, percent); + (file_modified == TRUE ? " [modified]" : ""), cur, tot, percent); } //----- Force refresh of all Lines ----------------------------- static void redraw (int full_screen) { - place_cursor (0, 0, FALSE); // put cursor in correct place - clear_to_eos (); // tel terminal to erase display - screen_erase (); // erase the internal screen buffer - refresh (full_screen); // this will redraw the entire display + place_cursor (0, 0, FALSE); // put cursor in correct place + clear_to_eos (); // tel terminal to erase display + screen_erase (); // erase the internal screen buffer + refresh (full_screen); // this will redraw the entire display } //----- Format a text[] line into a buffer --------------------- static void format_line (Byte * dest, Byte * src, int li) { - int co; - Byte c; - - for (co = 0; co < MAX_SCR_COLS; co++) - { - c = ' '; // assume blank - if (li > 0 && co == 0) - { - c = '~'; // not first line, assume Tilde - } - // are there chars in text[] and have we gone past the end - if (text < end && src < end) - { - c = *src++; - } - if (c == '\n') - break; - if (c < ' ' || c > '~') - { - if (c == '\t') - { - c = ' '; - // co % 8 != 7 - for (; (co % tabstop) != (tabstop - 1); co++) - { - dest[co] = c; - } - } - else - { - dest[co++] = '^'; - c |= '@'; // make it visible - c &= 0x7f; // get rid of hi bit - } - } - // the co++ is done here so that the column will - // not be overwritten when we blank-out the rest of line - dest[co] = c; - if (src >= end) - break; - } + int co; + Byte c; + + for (co = 0; co < MAX_SCR_COLS; co++) + { + c = ' '; // assume blank + if (li > 0 && co == 0) + { + c = '~'; // not first line, assume Tilde + } + // are there chars in text[] and have we gone past the end + if (text < end && src < end) + { + c = *src++; + } + if (c == '\n') + break; + if (c < ' ' || c > '~') + { + if (c == '\t') + { + c = ' '; + // co % 8 != 7 + for (; (co % tabstop) != (tabstop - 1); co++) + { + dest[co] = c; + } + } + else + { + dest[co++] = '^'; + c |= '@'; // make it visible + c &= 0x7f; // get rid of hi bit + } + } + // the co++ is done here so that the column will + // not be overwritten when we blank-out the rest of line + dest[co] = c; + if (src >= end) + break; + } } //----- Refresh the changed screen lines ----------------------- @@ -4366,122 +4366,122 @@ format_line (Byte * dest, Byte * src, int li) static void refresh (int full_screen) { - static int old_offset; - int li, changed; - Byte buf[MAX_SCR_COLS]; - Byte *tp, *sp; // pointer into text[] and screen[] + static int old_offset; + int li, changed; + Byte buf[MAX_SCR_COLS]; + Byte *tp, *sp; // pointer into text[] and screen[] #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - int last_li = -2; // last line that changed- for optimizing cursor movement + int last_li = -2; // last line that changed- for optimizing cursor movement #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ #ifdef BB_FEATURE_VI_WIN_RESIZE - window_size_get (0); + window_size_get (0); #endif /* BB_FEATURE_VI_WIN_RESIZE */ - sync_cursor (dot, &crow, &ccol); // where cursor will be (on "dot") - tp = screenbegin; // index into text[] of top line - - // compare text[] to screen[] and mark screen[] lines that need updating - for (li = 0; li < rows - 1; li++) - { - int cs, ce; // column start & end - memset (buf, ' ', MAX_SCR_COLS); // blank-out the buffer - buf[MAX_SCR_COLS - 1] = 0; // NULL terminate the buffer - // format current text line into buf - format_line (buf, tp, li); - - // skip to the end of the current text[] line - while (tp < end && *tp++ != '\n') /*no-op */ ; - - // see if there are any changes between vitual screen and buf - changed = FALSE; // assume no change - cs = 0; - ce = columns - 1; - sp = &screen[li * columns]; // start of screen line - if (full_screen == TRUE) - { - // force re-draw of every single column from 0 - columns-1 - goto re0; - } - // compare newly formatted buffer with virtual screen - // look forward for first difference between buf and screen - for (; cs <= ce; cs++) - { - if (buf[cs + offset] != sp[cs]) - { - changed = TRUE; // mark for redraw - break; - } - } - - // look backward for last difference between buf and screen - for (; ce >= cs; ce--) - { - if (buf[ce + offset] != sp[ce]) - { - changed = TRUE; // mark for redraw - break; - } - } - // now, cs is index of first diff, and ce is index of last diff - - // if horz offset has changed, force a redraw - if (offset != old_offset) - { - re0: - changed = TRUE; - } - - // make a sanity check of columns indexes - if (cs < 0) - cs = 0; - if (ce > columns - 1) - ce = columns - 1; - if (cs > ce) - { - cs = 0; - ce = columns - 1; - } - // is there a change between vitual screen and buf - if (changed == TRUE) - { - // copy changed part of buffer to virtual screen - memmove (sp + cs, buf + (cs + offset), ce - cs + 1); - - // move cursor to column of first change - if (offset != old_offset) - { - // opti_cur_move is still too stupid - // to handle offsets correctly - place_cursor (li, cs, FALSE); - } - else - { + sync_cursor (dot, &crow, &ccol); // where cursor will be (on "dot") + tp = screenbegin; // index into text[] of top line + + // compare text[] to screen[] and mark screen[] lines that need updating + for (li = 0; li < rows - 1; li++) + { + int cs, ce; // column start & end + memset (buf, ' ', MAX_SCR_COLS); // blank-out the buffer + buf[MAX_SCR_COLS - 1] = 0; // NULL terminate the buffer + // format current text line into buf + format_line (buf, tp, li); + + // skip to the end of the current text[] line + while (tp < end && *tp++ != '\n') /*no-op */ ; + + // see if there are any changes between vitual screen and buf + changed = FALSE; // assume no change + cs = 0; + ce = columns - 1; + sp = &screen[li * columns]; // start of screen line + if (full_screen == TRUE) + { + // force re-draw of every single column from 0 - columns-1 + goto re0; + } + // compare newly formatted buffer with virtual screen + // look forward for first difference between buf and screen + for (; cs <= ce; cs++) + { + if (buf[cs + offset] != sp[cs]) + { + changed = TRUE; // mark for redraw + break; + } + } + + // look backward for last difference between buf and screen + for (; ce >= cs; ce--) + { + if (buf[ce + offset] != sp[ce]) + { + changed = TRUE; // mark for redraw + break; + } + } + // now, cs is index of first diff, and ce is index of last diff + + // if horz offset has changed, force a redraw + if (offset != old_offset) + { + re0: + changed = TRUE; + } + + // make a sanity check of columns indexes + if (cs < 0) + cs = 0; + if (ce > columns - 1) + ce = columns - 1; + if (cs > ce) + { + cs = 0; + ce = columns - 1; + } + // is there a change between vitual screen and buf + if (changed == TRUE) + { + // copy changed part of buffer to virtual screen + memmove (sp + cs, buf + (cs + offset), ce - cs + 1); + + // move cursor to column of first change + if (offset != old_offset) + { + // opti_cur_move is still too stupid + // to handle offsets correctly + place_cursor (li, cs, FALSE); + } + else + { #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - // if this just the next line - // try to optimize cursor movement - // otherwise, use standard ESC sequence - place_cursor (li, cs, li == (last_li + 1) ? TRUE : FALSE); - last_li = li; -#else /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - place_cursor (li, cs, FALSE); // use standard ESC sequence + // if this just the next line + // try to optimize cursor movement + // otherwise, use standard ESC sequence + place_cursor (li, cs, li == (last_li + 1) ? TRUE : FALSE); + last_li = li; +#else /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ + place_cursor (li, cs, FALSE); // use standard ESC sequence #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - } + } - // write line out to terminal - write (1, sp + cs, ce - cs + 1); + // write line out to terminal + write (1, sp + cs, ce - cs + 1); #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - last_row = li; + last_row = li; #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - } - } + } + } #ifdef BB_FEATURE_VI_OPTIMIZE_CURSOR - place_cursor (crow, ccol, (crow == last_row) ? TRUE : FALSE); - last_row = crow; + place_cursor (crow, ccol, (crow == last_row) ? TRUE : FALSE); + last_row = crow; #else - place_cursor (crow, ccol, FALSE); + place_cursor (crow, ccol, FALSE); #endif /* BB_FEATURE_VI_OPTIMIZE_CURSOR */ - if (offset != old_offset) - old_offset = offset; + if (offset != old_offset) + old_offset = offset; }