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