home *** CD-ROM | disk | FTP | other *** search
/ Crawly Crypt Collection 2 / crawlyvol2.bin / apps / text_ed / elv16b2 / st / main.c < prev    next >
C/C++ Source or Header  |  1992-05-13  |  11KB  |  549 lines

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