NetBSD/usr.bin/elvis/main.c

511 lines
9.8 KiB
C

/* main.c */
/* Author:
* Steve Kirkendall
* 14407 SW Teal Blvd. #C
* Beaverton, OR 97005
* kirkenda@cs.pdx.edu
*/
/* This file contains the main() function of vi */
/* HACK! bcc needs to disable use of precompiled headers for this file,
or else command line args will not be passed to elvis */
#if __BORLANDC__
#include "borland.h"
#endif
#include "config.h"
#include <setjmp.h>
#include "vi.h"
extern SIGTYPE trapint(); /* defined below */
jmp_buf jmpenv;
#ifndef NO_DIGRAPH
static init_digraphs();
#endif
/*---------------------------------------------------------------------*/
#if AMIGA
# include "amiwild.c"
main (argc, argv)
#else
# if VMS
# include "vmswild.c"
main (argc, argv)
# else
void main(argc, argv)
# endif
#endif
int argc;
char *argv[];
{
int i;
char *cmd = (char *)0;
char *err = (char *)0;
char *str;
char *tag = (char *)0;
/* set mode to MODE_VI or MODE_EX depending on program name */
switch (argv[0][strlen(argv[0]) - 1])
{
case 'x': /* "ex" */
mode = MODE_EX;
break;
case 'w': /* "view" */
mode = MODE_VI;
*o_readonly = TRUE;
break;
#ifndef NO_EXTENSIONS
case 't': /* "edit" or "input" */
mode = MODE_VI;
*o_inputmode = TRUE;
break;
#endif
default: /* "vi" or "elvis" */
mode = MODE_VI;
}
#ifndef DEBUG
# ifdef SIGQUIT
/* normally, we ignore SIGQUIT. SIGINT is trapped later */
signal(SIGQUIT, SIG_IGN);
# endif
#endif
/* temporarily ignore SIGINT */
signal(SIGINT, SIG_IGN);
/* start curses */
initscr();
cbreak();
noecho();
scrollok(stdscr, TRUE);
/* arrange for deadly signals to be caught */
# ifdef SIGHUP
signal(SIGHUP, deathtrap);
# endif
# ifndef DEBUG
# ifdef SIGILL
signal(SIGILL, deathtrap);
# endif
# ifdef SIGBUS
signal(SIGBUS, deathtrap);
# endif
# ifdef SIGSEGV
signal(SIGSEGV, deathtrap);
# endif
# ifdef SIGSYS
signal(SIGSYS, deathtrap);
# endif
# endif /* !DEBUG */
# ifdef SIGPIPE
signal(SIGPIPE, deathtrap);
# endif
# ifdef SIGTERM
signal(SIGTERM, deathtrap);
# endif
# ifdef SIGUSR1
signal(SIGUSR1, deathtrap);
# endif
# ifdef SIGUSR2
signal(SIGUSR2, deathtrap);
# endif
/* initialize the options - must be done after initscr(), so that
* we can alter LINES and COLS if necessary.
*/
initopts();
/* map the arrow keys. The KU,KD,KL,and KR variables correspond to
* the :ku=: (etc.) termcap capabilities. The variables are defined
* as part of the curses package.
*/
if (has_KU) mapkey(has_KU, "k", WHEN_VICMD|WHEN_INMV, "<Up>");
if (has_KD) mapkey(has_KD, "j", WHEN_VICMD|WHEN_INMV, "<Down>");
if (has_KL) mapkey(has_KL, "h", WHEN_VICMD|WHEN_INMV, "<Left>");
if (has_KR) mapkey(has_KR, "l", WHEN_VICMD|WHEN_INMV, "<Right>");
if (has_HM) mapkey(has_HM, "^", WHEN_VICMD|WHEN_INMV, "<Home>");
if (has_EN) mapkey(has_EN, "$", WHEN_VICMD|WHEN_INMV, "<End>");
if (has_PU) mapkey(has_PU, "\002", WHEN_VICMD|WHEN_INMV, "<PageUp>");
if (has_PD) mapkey(has_PD, "\006", WHEN_VICMD|WHEN_INMV, "<PageDn>");
if (has_KI) mapkey(has_KI, "i", WHEN_VICMD|WHEN_INMV, "<Insert>");
#if MSDOS
# if RAINBOW
if (!strcmp("rainbow", o_term))
{
mapkey("\033[1~", "/", WHEN_VICMD, "<Find>");
mapkey("\033[3~", "x", WHEN_VICMD|WHEN_INMV, "<Remove>");
mapkey("\033[4~", "v", WHEN_VICMD|WHEN_INMV, "<Select>");
mapkey("\033[17~", ":sh\n", WHEN_VICMD, "<Intrpt>");
mapkey("\033[19~", ":q\n", WHEN_VICMD, "<Cancel>");
mapkey("\033[21~", "ZZ", WHEN_VICMD, "<Exit>");
mapkey("\033[26~", "V", WHEN_VICMD|WHEN_INMV, "<AddlOp>");
mapkey("\033[28~", "\\", WHEN_VICMD|WHEN_INMV, "<Help>");
mapkey("\033[29~", "K", WHEN_VICMD|WHEN_INMV, "<Do>");
}
else
# endif /* RAINBOW */
{
mapkey("#S", "x", WHEN_VICMD|WHEN_INMV, "<Delete>");
mapkey("#s", "B", WHEN_VICMD|WHEN_INMV, "^<Left>");
mapkey("#t", "W", WHEN_VICMD|WHEN_INMV, "^<Right>");
}
#else /* not MSDOS */
# if COHERENT
mapkey("\033[P", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
# else
#if AMIGA
mapkey("\233?~", "\\", WHEN_VICMD|WHEN_INMV, "<Help>");
#endif
if (ERASEKEY != '\177')
{
mapkey("\177", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
}
# endif
#endif
#ifndef NO_DIGRAPH
init_digraphs();
#endif /* NO_DIGRAPH */
/* process any flags */
for (i = 1; i < argc && *argv[i] == '-'; i++)
{
switch (argv[i][1])
{
case 'R': /* readonly */
*o_readonly = TRUE;
break;
case 'L':
case 'r': /* recover */
msg("Use the `elvrec` program to recover lost files");
endmsgs();
refresh();
endwin();
exit(1);
break;
case 't': /* tag */
if (argv[i][2])
{
tag = argv[i] + 2;
}
else
{
tag = argv[++i];
}
break;
case 'v': /* vi mode */
mode = MODE_VI;
break;
case 'e': /* ex mode */
mode = MODE_EX;
break;
#ifndef NO_EXTENSIONS
case 'i': /* input mode */
*o_inputmode = TRUE;
break;
#endif
#ifndef NO_ERRLIST
case 'm': /* use "errlist" as the errlist */
if (argv[i][2])
{
err = argv[i] + 2;
}
else if (i + 1 < argc)
{
err = argv[++i];
}
else
{
err = "";
}
break;
#endif
#ifndef CRUNCH
case 'c': /* run the following command, later */
if (argv[i][2])
{
cmd = argv[i] + 2;
}
else
{
cmd = argv[++i];
}
break;
case 'w': /* set the window size */
if (argv[i][2])
{
*o_window = atoi(argv[i] + 2);
wset = TRUE;
}
else
{
*o_window = atoi(argv[++i]);
wset = TRUE;
}
break;
#endif
default:
msg("Ignoring unknown flag \"%s\"", argv[i]);
}
}
/* if we were given an initial ex command, save it... */
if (i < argc && *argv[i] == '+')
{
if (argv[i][1])
{
cmd = argv[i++] + 1;
}
else
{
cmd = "$"; /* "vi + file" means start at EOF */
i++;
}
}
/* the remaining args are file names. */
if (i < argc)
{
strcpy(args, argv[i]);
while (++i < argc && strlen(args) + 1 + strlen(argv[i]) < sizeof args)
{
strcat(args, " ");
strcat(args, argv[i]);
}
#if MSDOS || TOS
/* expand wildcard characters, if necessary */
if (strchr(args, '*') || strchr(args, '?'))
{
strcpy(args, wildcard(args));
}
#endif
strcpy(tmpblk.c, args);
cmd_args(MARK_UNSET, MARK_UNSET, CMD_ARGS, TRUE, tmpblk.c);
}
else
{
/* empty args list */
args[0] = '\0';
nargs = 1;
argno = -1;
}
/* perform the .exrc files and EXINIT environment variable */
#ifdef SYSEXRC
doexrc(SYSEXRC);
#endif
#ifdef HMEXRC
str = gethome(argv[0]);
if (str && *str)
{
strcpy(tmpblk.c, str);
str = tmpblk.c + strlen(tmpblk.c);
#if !VMS
# if AMIGA /* Don't SLASH a device. "Elvis:.exrc" */
if (str[-1] != COLON && str[-1] != SLASH)
# else
if (str[-1] != SLASH)
# endif
{
*str++ = SLASH;
}
#endif
strcpy(str, HMEXRC);
doexrc(tmpblk.c);
}
#endif
#ifndef CRUNCH
if (*o_exrc)
#endif
{
doexrc(EXRC);
}
#ifdef EXINIT
str = getenv(EXINIT);
if (str)
{
exstring(str, strlen(str), ctrl('V'));
}
#endif
/* search for a tag (or an error) now, if desired */
blkinit();
if (tag)
{
cmd_tag(MARK_UNSET, MARK_FIRST, CMD_TAG, 0, tag);
}
#ifndef NO_ERRLIST
else if (err)
{
cmd_errlist(MARK_FIRST, MARK_FIRST, CMD_ERRLIST, 0, err);
}
#endif
/* if no tag/err, or tag failed, then start with first arg */
if (tmpfd < 0)
{
/* start with first arg */
cmd_next(MARK_UNSET, MARK_UNSET, CMD_NEXT, FALSE, "");
/* pretend to do something, just to force a recoverable
* version of the file out to disk
*/
ChangeText
{
}
clrflag(file, MODIFIED);
}
/* now we do the immediate ex command that we noticed before */
if (cmd)
{
doexcmd(cmd);
}
/* repeatedly call ex() or vi() (depending on the mode) until the
* mode is set to MODE_QUIT
*/
while (mode != MODE_QUIT)
{
if (setjmp(jmpenv))
{
/* Maybe we just aborted a change? */
abortdo();
}
signal(SIGINT, trapint);
switch (mode)
{
case MODE_VI:
vi();
break;
case MODE_EX:
ex();
break;
#ifdef DEBUG
default:
msg("mode = %d?", mode);
mode = MODE_QUIT;
#endif
}
}
/* free up the cut buffers */
cutend();
/* end curses */
#ifndef NO_CURSORSHAPE
if (has_CQ)
do_CQ();
#endif
endmsgs();
move(LINES - 1, 0);
clrtoeol();
refresh();
endwin();
exit(exitcode);
/*NOTREACHED*/
}
/*ARGSUSED*/
SIGTYPE trapint(signo)
int signo;
{
beep();
resume_curses(FALSE);
abortdo();
#if OSK
sigmask(-1);
#endif
signal(signo, trapint);
doingglobal = FALSE;
longjmp(jmpenv, 1);
/*NOTREACHED*/
}
#ifndef NO_DIGRAPH
/* This stuff us used to build the default digraphs table. */
static char digtable[][4] =
{
# ifdef CS_IBMPC
"C,\200", "u\"\1", "e'\2", "a^\3",
"a\"\4", "a`\5", "a@\6", "c,\7",
"e^\10", "e\"\211", "e`\12", "i\"\13",
"i^\14", "i`\15", "A\"\16", "A@\17",
"E'\20", "ae\21", "AE\22", "o^\23",
"o\"\24", "o`\25", "u^\26", "u`\27",
"y\"\30", "O\"\31", "U\"\32", "a'\240",
"i'!", "o'\"", "u'#", "n~$",
"N~%", "a-&", "o-'", "~?(",
"~!-", "\"<.", "\">/",
# ifdef CS_SPECIAL
"2/+", "4/,", "^+;", "^q<",
"^c=", "^r>", "^t?", "pp]",
"^^^", "oo_", "*a`", "*ba",
"*pc", "*Sd", "*se", "*uf",
"*tg", "*Ph", "*Ti", "*Oj",
"*dk", "*Hl", "*hm", "*En",
"*No", "eqp", "pmq", "ger",
"les", "*It", "*iu", "*/v",
"*=w", "sq{", "^n|", "^2}",
"^3~", "^_\377",
# endif /* CS_SPECIAL */
# endif /* CS_IBMPC */
# ifdef CS_LATIN1
"~!!", "a-*", "\">+", "o-:",
"\"<>", "~??",
"A`@", "A'A", "A^B", "A~C",
"A\"D", "A@E", "AEF", "C,G",
"E`H", "E'I", "E^J", "E\"K",
"I`L", "I'M", "I^N", "I\"O",
"-DP", "N~Q", "O`R", "O'S",
"O^T", "O~U", "O\"V", "O/X",
"U`Y", "U'Z", "U^[", "U\"\\",
"Y'_",
"a``", "a'a", "a^b", "a~c",
"a\"d", "a@e", "aef", "c,g",
"e`h", "e'i", "e^j", "e\"k",
"i`l", "i'm", "i^n", "i\"o",
"-dp", "n~q", "o`r", "o's",
"o^t", "o~u", "o\"v", "o/x",
"u`y", "u'z", "u^{", "u\"|",
"y'~",
# endif /* CS_LATIN1 */
""
};
static int init_digraphs()
{
int i;
for (i = 0; *digtable[i]; i++)
{
do_digraph(FALSE, digtable[i]);
}
do_digraph(FALSE, (char *)0);
return 0;
}
#endif /* NO_DIGRAPH */