home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / elvis184.zip / src / main.c < prev    next >
C/C++ Source or Header  |  1995-05-26  |  13KB  |  623 lines

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