home *** CD-ROM | disk | FTP | other *** search
- /* 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 trapint(); /* defined below */
- extern char *getenv();
- 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, (void(*)()) deathtrap);
- # endif
- # ifndef DEBUG
- # ifdef SIGILL
- signal(SIGILL, (void(*)()) deathtrap);
- # endif
- # ifdef SIGBUS
- signal(SIGBUS, (void(*)()) deathtrap);
- # endif
- # ifdef SIGSEGV
- signal(SIGSEGV, (void(*)()) deathtrap);
- # endif
- # ifdef SIGSYS
- signal(SIGSYS, (void(*)()) deathtrap);
- # endif
- # endif /* !DEBUG */
- # ifdef SIGPIPE
- signal(SIGPIPE, (void(*)()) deathtrap);
- # endif
- # ifdef SIGTERM
- signal(SIGTERM, (void(*)()) deathtrap);
- # endif
- # ifdef SIGUSR1
- signal(SIGUSR1, (void(*)()) deathtrap);
- # endif
- # ifdef SIGUSR2
- signal(SIGUSR2, (void(*)()) 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(0);
- 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 = getenv("HOME");
- 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_FIRST, 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, (void(*)()) 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(0);
- /*NOTREACHED*/
- }
-
-
- /*ARGSUSED*/
- int trapint(signo)
- int signo;
- {
- beep();
- resume_curses(FALSE);
- abortdo();
- #if OSK
- sigmask(-1);
- #endif
- #if TURBOC || __GNUC__
- signal(signo, (void (*)())trapint);
- #else
- signal(signo, trapint);
- #endif
- doingglobal = FALSE;
-
- longjmp(jmpenv, 1);
-
- return 0;
- }
-
-
-
- #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 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 */
-