Commit | Line | Data |
---|---|---|
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 | 23 | extern SIGTYPE trapint(); /* defined below */ |
15637ed4 RG |
24 | jmp_buf jmpenv; |
25 | ||
26 | #ifndef NO_DIGRAPH | |
27 | static init_digraphs(); | |
28 | #endif | |
29 | ||
30 | /*---------------------------------------------------------------------*/ | |
31 | ||
32 | #if AMIGA | |
33 | # include "amiwild.c" | |
34 | main (argc, argv) | |
35 | #else | |
36 | # if VMS | |
37 | # include "vmswild.c" | |
38 | main (argc, argv) | |
39 | # else | |
40 | void 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 | 427 | SIGTYPE 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. */ | |
448 | static 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 | 499 | static 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 */ |