Initial revision
[nvi.git] / common / main.c
blobd287274875b74a9e77f607d3f9dc90a2d8846e1e
1 /* main.c */
3 /* Author:
4 * Steve Kirkendall
5 * 14407 SW Teal Blvd. #C
6 * Beaverton, OR 97005
7 * kirkenda@cs.pdx.edu
8 */
11 /* This file contains the main() function of vi */
13 /* HACK! bcc needs to disable use of precompiled headers for this file,
14 or else command line args will not be passed to elvis */
15 #if __BORLANDC__
16 #include "borland.h"
17 #endif
19 #include "config.h"
20 #include <signal.h>
21 #include <setjmp.h>
22 #include "vi.h"
24 extern trapint(); /* defined below */
25 extern char *getenv();
26 jmp_buf jmpenv;
28 #ifndef NO_DIGRAPH
29 static init_digraphs();
30 #endif
32 /*---------------------------------------------------------------------*/
34 #if VMS
35 # include "vmswild.c"
36 main (argc, argv)
37 #else
38 void main(argc, argv)
39 #endif
40 int argc;
41 char *argv[];
43 int i;
44 char *cmd = (char *)0;
45 char *err = (char *)0;
46 char *str;
47 char *tag = (char *)0;
49 /* set mode to MODE_VI or MODE_EX depending on program name */
50 switch (argv[0][strlen(argv[0]) - 1])
52 case 'x': /* "ex" */
53 mode = MODE_EX;
54 break;
56 case 'w': /* "view" */
57 mode = MODE_VI;
58 *o_readonly = TRUE;
59 break;
60 #ifndef NO_EXTENSIONS
61 case 't': /* "edit" or "input" */
62 mode = MODE_VI;
63 *o_inputmode = TRUE;
64 break;
65 #endif
66 default: /* "vi" or "elvis" */
67 mode = MODE_VI;
70 #ifndef DEBUG
71 # ifdef SIGQUIT
72 /* normally, we ignore SIGQUIT. SIGINT is trapped later */
73 signal(SIGQUIT, SIG_IGN);
74 # endif
75 #endif
77 /* temporarily ignore SIGINT */
78 signal(SIGINT, SIG_IGN);
80 /* start curses */
81 initscr();
82 cbreak();
83 noecho();
84 scrollok(stdscr, TRUE);
86 /* arrange for deadly signals to be caught */
87 # ifdef SIGHUP
88 signal(SIGHUP, (void(*)()) deathtrap);
89 # endif
90 # ifndef DEBUG
91 # ifdef SIGILL
92 signal(SIGILL, (void(*)()) deathtrap);
93 # endif
94 # ifdef SIGBUS
95 signal(SIGBUS, (void(*)()) deathtrap);
96 # endif
97 # ifdef SIGSEGV
98 signal(SIGSEGV, (void(*)()) deathtrap);
99 # endif
100 # ifdef SIGSYS
101 signal(SIGSYS, (void(*)()) deathtrap);
102 # endif
103 # endif /* !DEBUG */
104 # ifdef SIGPIPE
105 signal(SIGPIPE, (void(*)()) deathtrap);
106 # endif
107 # ifdef SIGTERM
108 signal(SIGTERM, (void(*)()) deathtrap);
109 # endif
110 # ifdef SIGUSR1
111 signal(SIGUSR1, (void(*)()) deathtrap);
112 # endif
113 # ifdef SIGUSR2
114 signal(SIGUSR2, (void(*)()) deathtrap);
115 # endif
117 /* initialize the options - must be done after initscr(), so that
118 * we can alter LINES and COLS if necessary.
120 initopts();
122 /* map the arrow keys. The KU,KD,KL,and KR variables correspond to
123 * the :ku=: (etc.) termcap capabilities. The variables are defined
124 * as part of the curses package.
126 if (has_KU) mapkey(has_KU, "k", WHEN_VICMD|WHEN_INMV, "<Up>");
127 if (has_KD) mapkey(has_KD, "j", WHEN_VICMD|WHEN_INMV, "<Down>");
128 if (has_KL) mapkey(has_KL, "h", WHEN_VICMD|WHEN_INMV, "<Left>");
129 if (has_KR) mapkey(has_KR, "l", WHEN_VICMD|WHEN_INMV, "<Right>");
130 if (has_HM) mapkey(has_HM, "^", WHEN_VICMD|WHEN_INMV, "<Home>");
131 if (has_EN) mapkey(has_EN, "$", WHEN_VICMD|WHEN_INMV, "<End>");
132 if (has_PU) mapkey(has_PU, "\002", WHEN_VICMD|WHEN_INMV, "<PageUp>");
133 if (has_PD) mapkey(has_PD, "\006", WHEN_VICMD|WHEN_INMV, "<PageDn>");
134 if (has_KI) mapkey(has_KI, "i", WHEN_VICMD|WHEN_INMV, "<Insert>");
135 #if MSDOS
136 # if RAINBOW
137 if (!strcmp("rainbow", o_term))
139 mapkey("\033[1~", "/", WHEN_VICMD, "<Find>");
140 mapkey("\033[3~", "x", WHEN_VICMD|WHEN_INMV, "<Remove>");
141 mapkey("\033[4~", "v", WHEN_VICMD|WHEN_INMV, "<Select>");
142 mapkey("\033[17~", ":sh\n", WHEN_VICMD, "<Intrpt>");
143 mapkey("\033[19~", ":q\n", WHEN_VICMD, "<Cancel>");
144 mapkey("\033[21~", "ZZ", WHEN_VICMD, "<Exit>");
145 mapkey("\033[26~", "V", WHEN_VICMD|WHEN_INMV, "<AddlOp>");
146 mapkey("\033[28~", "\\", WHEN_VICMD|WHEN_INMV, "<Help>");
147 mapkey("\033[29~", "K", WHEN_VICMD|WHEN_INMV, "<Do>");
149 else
150 # endif /* RAINBOW */
152 mapkey("#S", "x", WHEN_VICMD|WHEN_INMV, "<Delete>");
153 mapkey("#s", "B", WHEN_VICMD|WHEN_INMV, "^<Left>");
154 mapkey("#t", "W", WHEN_VICMD|WHEN_INMV, "^<Right>");
156 #else /* not MSDOS */
157 # if COHERENT
158 mapkey("\033[P", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
159 # else
160 if (ERASEKEY != '\177')
162 mapkey("\177", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
164 # endif
165 #endif
167 #ifndef NO_DIGRAPH
168 init_digraphs();
169 #endif /* NO_DIGRAPH */
171 /* process any flags */
172 for (i = 1; i < argc && *argv[i] == '-'; i++)
174 switch (argv[i][1])
176 case 'R': /* readonly */
177 *o_readonly = TRUE;
178 break;
180 #ifdef SYSV_COMPAT
181 case 'L':
182 #endif
183 case 'r': /* recover */
184 msg("Use the `elvrec` program to recover lost files");
185 endmsgs();
186 refresh();
187 endwin();
188 exit(0);
189 break;
191 case 't': /* tag */
192 if (argv[i][2])
194 tag = argv[i] + 2;
196 else
198 tag = argv[++i];
200 break;
202 case 'v': /* vi mode */
203 mode = MODE_VI;
204 break;
206 case 'e': /* ex mode */
207 mode = MODE_EX;
208 break;
209 #ifndef NO_EXTENSIONS
210 case 'i': /* input mode */
211 *o_inputmode = TRUE;
212 break;
213 #endif
214 #ifndef NO_ERRLIST
215 case 'm': /* use "errlist" as the errlist */
216 if (argv[i][2])
218 err = argv[i] + 2;
220 else if (i + 1 < argc)
222 err = argv[++i];
224 else
226 err = "";
228 break;
229 #endif
230 #ifdef SYSV_COMPAT
231 case 'c': /* run the following command, later */
232 if (argv[i][2])
234 cmd = argv[i] + 2;
236 else
238 cmd = argv[++i];
240 break;
241 #endif
242 default:
243 msg("Ignoring unknown flag \"%s\"", argv[i]);
247 /* if we were given an initial ex command, save it... */
248 if (i < argc && *argv[i] == '+')
250 if (argv[i][1])
252 cmd = argv[i++] + 1;
254 else
256 cmd = "$"; /* "vi + file" means start at EOF */
257 i++;
261 /* the remaining args are file names. */
262 if (i < argc)
264 strcpy(args, argv[i]);
265 while (++i < argc && strlen(args) + 1 + strlen(argv[i]) < sizeof args)
267 strcat(args, " ");
268 strcat(args, argv[i]);
270 #if MSDOS || TOS
271 /* expand wildcard characters, if necessary */
272 if (strchr(args, '*') || strchr(args, '?'))
274 strcpy(args, wildcard(args));
276 #endif
277 strcpy(tmpblk.c, args);
278 cmd_args(MARK_UNSET, MARK_UNSET, CMD_ARGS, TRUE, tmpblk.c);
280 else
282 /* empty args list */
283 args[0] = '\0';
284 nargs = 1;
285 argno = -1;
288 /* perform the .exrc files and EXINIT environment variable */
289 #ifdef SYSEXRC
290 doexrc(SYSEXRC);
291 #endif
292 #ifdef HMEXRC
293 str = getenv("HOME");
294 if (str && *str)
296 strcpy(tmpblk.c, str);
297 str = tmpblk.c + strlen(tmpblk.c);
298 #if !VMS
299 if (str[-1] != SLASH)
301 *str++ = SLASH;
303 #endif
304 strcpy(str, HMEXRC);
305 doexrc(tmpblk.c);
307 #endif
308 #ifndef CRUNCH
309 if (*o_exrc)
310 #endif
312 doexrc(EXRC);
314 #ifdef EXINIT
315 str = getenv(EXINIT);
316 if (str)
318 exstring(str, strlen(str));
320 #endif
322 /* search for a tag (or an error) now, if desired */
323 blkinit();
324 if (tag)
326 cmd_tag(MARK_FIRST, MARK_FIRST, CMD_TAG, 0, tag);
328 #ifndef NO_ERRLIST
329 else if (err)
331 cmd_errlist(MARK_FIRST, MARK_FIRST, CMD_ERRLIST, 0, err);
333 #endif
335 /* if no tag/err, or tag failed, then start with first arg */
336 if (tmpfd < 0)
338 /* start with first arg */
339 cmd_next(MARK_UNSET, MARK_UNSET, CMD_NEXT, FALSE, "");
341 /* pretend to do something, just to force a recoverable
342 * version of the file out to disk
344 ChangeText
347 clrflag(file, MODIFIED);
350 /* now we do the immediate ex command that we noticed before */
351 if (cmd)
353 doexcmd(cmd);
356 /* repeatedly call ex() or vi() (depending on the mode) until the
357 * mode is set to MODE_QUIT
359 while (mode != MODE_QUIT)
361 if (setjmp(jmpenv))
363 /* Maybe we just aborted a change? */
364 abortdo();
366 signal(SIGINT, (void(*)()) trapint);
368 switch (mode)
370 case MODE_VI:
371 vi();
372 break;
374 case MODE_EX:
375 ex();
376 break;
377 #ifdef DEBUG
378 default:
379 msg("mode = %d?", mode);
380 mode = MODE_QUIT;
381 #endif
385 /* free up the cut buffers */
386 cutend();
388 /* end curses */
389 #ifndef NO_CURSORSHAPE
390 if (has_CQ)
391 do_CQ();
392 #endif
393 endmsgs();
394 move(LINES - 1, 0);
395 clrtoeol();
396 refresh();
397 endwin();
399 exit(0);
400 /*NOTREACHED*/
404 /*ARGSUSED*/
405 int trapint(signo)
406 int signo;
408 resume_curses(FALSE);
409 abortdo();
410 #if OSK
411 sigmask(-1);
412 #endif
413 #if TURBOC || __GNUC__
414 signal(signo, (void (*)())trapint);
415 #else
416 signal(signo, trapint);
417 #endif
418 doingglobal = FALSE;
420 longjmp(jmpenv, 1);
422 return 0;
427 #ifndef NO_DIGRAPH
429 /* This stuff us used to build the default digraphs table. */
430 static char digtable[][4] =
432 # ifdef CS_IBMPC
433 "C,\200", "u\"\1", "e'\2", "a^\3",
434 "a\"\4", "a`\5", "a@\6", "c,\7",
435 "e^\10", "e\"\211", "e`\12", "i\"\13",
436 "i^\14", "i`\15", "A\"\16", "A@\17",
437 "E'\20", "ae\21", "AE\22", "o^\23",
438 "o\"\24", "o`\25", "u^\26", "u`\27",
439 "y\"\30", "O\"\31", "U\"\32", "a'\240",
440 "i'!", "o'\"", "u'#", "n~$",
441 "N~%", "a-&", "o-'", "~?(",
442 "~!-", "\"<.", "\">/",
443 # ifdef CS_SPECIAL
444 "2/+", "4/,", "^+;", "^q<",
445 "^c=", "^r>", "^t?", "pp]",
446 "^^^", "oo_", "*a`", "*ba",
447 "*pc", "*Sd", "*se", "*uf",
448 "*tg", "*Ph", "*Ti", "*Oj",
449 "*dk", "*Hl", "*hm", "*En",
450 "*No", "eqp", "pmq", "ger",
451 "les", "*It", "*iu", "*/v",
452 "*=w", "sq{", "^n|", "^2}",
453 "^3~", "^_\377",
454 # endif /* CS_SPECIAL */
455 # endif /* CS_IBMPC */
456 # ifdef CS_LATIN1
457 "~!!", "a-*", "\">+", "o-:",
458 "\"<>", "~??",
460 "A`@", "A'A", "A^B", "A~C",
461 "A\"D", "A@E", "AEF", "C,G",
462 "E`H", "E'I", "E^J", "E\"K",
463 "I`L", "I'M", "I^N", "I\"O",
464 "-DP", "N~Q", "O`R", "O'S",
465 "O^T", "O~U", "O\"V", "O/X",
466 "U`Y", "U'Z", "U^[", "U\"\\",
467 "Y'_",
469 "a``", "a'a", "a^b", "a~c",
470 "a\"d", "a@e", "aef", "c,g",
471 "e`h", "e'i", "e^j", "e\"k",
472 "i`l", "i'm", "i^n", "i\"o",
473 "-dp", "n~q", "o`r", "o's",
474 "o^t", "o~u", "o\"v", "o/x",
475 "u`y", "u'z", "u^{", "u\"|",
476 "y'~",
477 # endif /* CS_LATIN1 */
481 static init_digraphs()
483 int i;
485 for (i = 0; *digtable[i]; i++)
487 do_digraph(FALSE, digtable[i]);
489 do_digraph(FALSE, (char *)0);
491 #endif /* NO_DIGRAPH */