home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / util / vim-2.0.lha / Vim-2.0 / src / main.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-15  |  11.3 KB  |  503 lines

  1. /* vi:ts=4:sw=4
  2.  *
  3.  * VIM - Vi IMproved
  4.  *
  5.  * Code Contributions By:    Bram Moolenaar            mool@oce.nl
  6.  *                            Tim Thompson            twitch!tjt
  7.  *                            Tony Andrews            onecom!wldrdg!tony 
  8.  *                            G. R. (Fred) Walter        watmath!watcgl!grwalter 
  9.  */
  10.  
  11. #define EXTERN
  12. #include "vim.h"
  13. #include "globals.h"
  14. #include "proto.h"
  15. #include "param.h"
  16.  
  17. static void usage __PARMS((int));
  18.  
  19.     static void
  20. usage(n)
  21.     int n;
  22. {
  23.     register int i;
  24.     static char *(use[]) = {"[file ..]\n",
  25.                             "-t tag\n",
  26.                             "+[command] file ..\n",
  27.                             "-c {command} file ..\n",
  28.                             "-e [errorfile]\n"};
  29.     static char *(errors[]) =  {"Unknown option\n",            /* 0 */
  30.                                 "Too many arguments\n",        /* 1 */
  31.                                 "Argument missing\n",        /* 2 */
  32.                                 };
  33.  
  34.     fprintf(stderr, errors[n]);
  35.     fprintf(stderr, "usage:");
  36.     for (i = 0; ; ++i)
  37.     {
  38.         fprintf(stderr, " vim [options] ");
  39.         fprintf(stderr, use[i]);
  40.         if (i == (sizeof(use) / sizeof(char *)) - 1)
  41.             break;
  42.         fprintf(stderr, "   or:");
  43.     }
  44. #ifdef AMIGA
  45.     fprintf(stderr, "\noptions: -v -n -b -r -x -d device -s scriptin -w scriptout -T terminal\n");
  46. #else
  47.     fprintf(stderr, "\noptions: -v -n -b -r -s scriptin -w scriptout -T terminal\n");
  48. #endif
  49.     mch_windexit(1);
  50. }
  51.  
  52. #ifdef USE_LOCALE
  53. # include <locale.h>
  54. #endif
  55.  
  56.     void
  57. main(argc, argv)
  58.     int                argc;
  59.     char          **argv;
  60. {
  61.     char           *initstr;        /* init string from the environment */
  62.     char           *term = NULL;    /* specified terminal name */
  63.     char           *fname = NULL;    /* file name from command line */
  64.     char           *command = NULL;    /* command from + option */
  65.     char           *tagname = NULL;    /* tag from -t option */
  66.     int             c;
  67.     int                doqf = 0;
  68.     int                i;
  69.     int                bin_mode = FALSE;    /* -b option used */
  70.  
  71. #ifdef DEBUG
  72. # ifdef MSDOS
  73.     OPENDEBUG("#debug#");
  74. # else
  75.     OPENDEBUG("/tmp/debug/vim");
  76. # endif
  77. #endif
  78.  
  79. /*
  80.  * Check if we have an interactive window.
  81.  * If not, open one with a newcli command (needed for :! to work).
  82.  * check_win will also handle the -d argument (for the Amiga).
  83.  */
  84.     check_win(argc, argv);
  85.  
  86. /*
  87.  * If the executable is called "view" we start in readonly mode.
  88.  */
  89.     if (strcmp(gettail(argv[0]), "view") == 0)
  90.     {
  91.         readonlymode = TRUE;
  92.         p_ro = TRUE;
  93.         p_uc = 0;
  94.     }
  95.  
  96.     ++argv;
  97.     /*
  98.      * Process the command line arguments
  99.      *         '-s scriptin'    read from script file
  100.      *        '-w scriptout'    write to script file
  101.      *        '-v'            view
  102.      *        '-b'            binary
  103.      *        '-n'            no .vim file
  104.      *        '-r'            recovery mode
  105.      *        '-x'            open window directly, not with newcli
  106.      *        '-T terminal'    terminal name
  107.      */
  108.     while (argc > 1 && argv[0][0] == '-' &&
  109.             strchr("vnbrxswTd", c = argv[0][1]) != NULL && c)
  110.     {
  111.         --argc;
  112.         switch (c)
  113.         {
  114.         case 'v':
  115.             readonlymode = TRUE;
  116.             p_ro = TRUE;
  117.             /*FALLTHROUGH*/
  118.  
  119.         case 'n':
  120.             p_uc = 0;
  121.             break;
  122.  
  123.         case 'b':
  124.             bin_mode = TRUE;        /* postpone to after reading .exrc files */
  125.             break;
  126.  
  127.         case 'r':
  128.             recoverymode = 1;
  129.             break;
  130.         
  131.         case 'x':
  132.             break;    /* This is ignored as it is handled in check_win() */
  133.  
  134.         default:    /* options with argument */
  135.             ++argv;
  136.             --argc;
  137.             if (argc < 1)
  138.                 usage(2);
  139.  
  140.             switch (c)
  141.             {
  142.             case 's':
  143.                 if ((scriptin[0] = fopen(argv[0], READBIN)) == NULL)
  144.                 {
  145.                         fprintf(stderr, "cannot open %s for reading\n", argv[0]);
  146.                         mch_windexit(2);
  147.                 }
  148.                 break;
  149.             
  150.             case 'w':
  151.                 if ((scriptout = fopen(argv[0],
  152. #ifdef MSDOS
  153.                                                     "ab"
  154. #else
  155.                                                     "a"
  156. #endif
  157.                                                         )) == NULL)
  158.                 {
  159.                         fprintf(stderr, "cannot open %s for output\n", argv[0]);
  160.                         mch_windexit(2);
  161.                 }
  162.                 break;
  163.  
  164. /*
  165.  * The -T term option is always available and when TERMCAP is supported it
  166.  * overrides the environment variable TERM.
  167.  */
  168.             case 'T':
  169.                 term = *argv;
  170.                 break;
  171.             
  172.         /*    case 'd':        This is ignored as it is handled in check_win() */
  173.             }
  174.         }
  175.         ++argv;
  176.     }
  177.  
  178.     /*
  179.      * Allocate space for the generic buffer
  180.      */
  181.     if ((IObuff = alloc(IOSIZE)) == NULL)
  182.         mch_windexit(0);
  183.  
  184.     /* note that we may use mch_windexit() before mch_windinit()! */
  185.     mch_windinit();
  186.     set_init();            /* after mch_windinit because Rows is used */
  187.  
  188.     /*
  189.      * Process the other command line arguments.
  190.      */
  191.     if (argc > 1)
  192.     {
  193.         c = argv[0][1];
  194.         switch (argv[0][0])
  195.         {
  196.           case '-':
  197.             switch (c)
  198.             {
  199.               case 'e':            /* -e QuickFix mode */
  200.                 switch (argc)
  201.                 {
  202.                     case 2:
  203.                             if (argv[0][2])        /* -eerrorfile */
  204.                                 p_ef = argv[0] + 2;
  205.                             break;                /* -e */
  206.  
  207.                     case 3:                        /* -e errorfile */
  208.                             ++argv;
  209.                             p_ef = argv[0];
  210.                             break;
  211.  
  212.                     default:                    /* argc > 3: too many arguments */
  213.                             usage(1);
  214.                 }
  215.                 doqf = 1;
  216.                 break;
  217.  
  218.             case 'c':            /* -c {command} file .. */
  219.                 if (argc <= 3)
  220.                     usage(2);
  221.                 ++argv;
  222.                 --argc;
  223.                 command = &(argv[0][0]);
  224.                 goto getfiles;
  225.  
  226.             case 't':            /* -t tag  or -ttag */
  227.                 switch (argc)
  228.                 {
  229.                     case 2:
  230.                             if (argv[0][2])        /* -ttag */
  231.                             {
  232.                                 tagname = argv[0] + 2;
  233.                                 break;
  234.                             }
  235.                             usage(2);            /* argument missing */
  236.                             break;
  237.  
  238.                     case 3:                        /* -t tag */
  239.                             ++argv;
  240.                             tagname = argv[0];
  241.                             break;
  242.  
  243.                     default:                    /* argc > 3: too many arguments */
  244.                             usage(1);
  245.                 }
  246.                 break;
  247.  
  248.             default:
  249.                 usage(0);
  250.             }
  251.             break;
  252.  
  253.           case '+':             /* + or +{number} or +/{pat} or +{command} */
  254.             if (argc < 3)        /* no filename */
  255.                     usage(2);
  256.             if (c == NUL)
  257.                 command = "$";
  258.             else
  259.                 command = &(argv[0][1]);
  260.  
  261. getfiles:
  262.             ++argv;
  263.             --argc;
  264.             /*FALLTHROUGH*/
  265.  
  266.           default:                /* must be a file name */
  267. #if !defined(UNIX)
  268.             ExpandWildCards(argc - 1, argv, &numfiles, &files, TRUE, TRUE);
  269.             if (numfiles != 0)
  270.             {
  271.                 fname = files[0];
  272.                 files_exp = TRUE;
  273.             }
  274. #else
  275.             files = argv;
  276.             numfiles = argc - 1;
  277.             fname = argv[0];
  278. #endif
  279.             if (numfiles > 1)
  280.                 printf("%d files to edit\n", numfiles);
  281.             break;
  282.         }
  283.     }
  284.  
  285.     RedrawingDisabled = TRUE;
  286.     filealloc();                /* Initialize storage structure */
  287.     init_yank();                /* init yank buffers */
  288.     termcapinit(term);            /* get terminal capabilities */
  289.  
  290. #ifdef USE_LOCALE
  291.     setlocale(LC_ALL, "");        /* for ctype() and the like */
  292. #endif
  293.  
  294. #ifdef MSDOS /* default mapping for some often used keys */
  295.     domap(0, "#1 :help\r", NORMAL);            /* F1 is help key */
  296.     domap(0, "\316R i", NORMAL);            /* INSERT is 'i' */
  297.     domap(0, "\316S \177", NORMAL);            /* DELETE is 0x7f */
  298.     domap(0, "\316G 0", NORMAL);            /* HOME is '0' */
  299.     domap(0, "\316w H", NORMAL);            /* CTRL-HOME is 'H' */
  300.     domap(0, "\316O $", NORMAL);            /* END is '$' */
  301.     domap(0, "\316u L", NORMAL);            /* CTRL-END is 'L' */
  302.     domap(0, "\316I \002", NORMAL);            /* PageUp is '^B' */
  303.     domap(0, "\316\204 1G", NORMAL);        /* CTRL-PageUp is '1G' */
  304.     domap(0, "\316Q \006", NORMAL);            /* PageDown is '^F' */
  305.     domap(0, "\316v G", NORMAL);            /* CTRL-PageDown is 'G' */
  306.             /* insert mode */
  307.     domap(0, "#1 \017:help\r", INSERT);        /* F1 is help key */
  308.     domap(0, "\316R \033", INSERT);            /* INSERT is ESC */
  309.             /* note: extra space needed to avoid the same memory used for this
  310.                and the one above, domap() will add a NUL to it */
  311.     domap(0, "\316S  \177", INSERT+CMDLINE);    /* DELETE is 0x7f */
  312.     domap(0, "\316G \017""0", INSERT);        /* HOME is '^O0' */
  313.     domap(0, "\316w \017H", INSERT);        /* CTRL-HOME is '^OH' */
  314.     domap(0, "\316O \017$", INSERT);        /* END is '^O$' */
  315.     domap(0, "\316u \017L", INSERT);        /* CTRL-END is '^OL' */
  316.     domap(0, "\316I \017\002", INSERT);        /* PageUp is '^O^B' */
  317.     domap(0, "\316\204 \017\061G", INSERT);    /* CTRL-PageUp is '^O1G' */
  318.     domap(0, "\316Q \017\006", INSERT);        /* PageDown is '^O^F' */
  319.     domap(0, "\316v \017G", INSERT);        /* CTRL-PageDown is '^OG' */
  320. #endif
  321.  
  322. /*
  323.  * get system wide defaults (for unix)
  324.  */
  325. #ifdef DEFVIMRC_FILE
  326.     dosource(DEFVIMRC_FILE);
  327. #endif
  328.  
  329. /*
  330.  * Try to read initialization commands from the following places:
  331.  * - environment variable VIMINIT
  332.  * - file s:.vimrc ($HOME/.vimrc for Unix)
  333.  * - environment variable EXINIT
  334.  * - file s:.exrc ($HOME/.exrc for Unix)
  335.  * The first that exists is used, the rest is ignored.
  336.  */
  337.     if ((initstr = (char *)vimgetenv("VIMINIT")) != NULL)
  338.         docmdline((u_char *)initstr);
  339.     else if (dosource(SYSVIMRC_FILE))
  340.     {
  341.         if ((initstr = (char *)vimgetenv("EXINIT")) != NULL)
  342.             docmdline((u_char *)initstr);
  343.         else
  344.             dosource(SYSEXRC_FILE);
  345.     }
  346.  
  347. /*
  348.  * Read initialization commands from ".vimrc" or ".exrc" in current directory.
  349.  * This is only done if the 'exrc' option is set.
  350.  * Because of security reasons we disallow shell and write commands now,
  351.  * except for unix if the file is owned by the user or 'secure' option has been
  352.  * reset in environmet of global ".exrc" or ".vimrc".
  353.  * Only do this if VIMRC_FILE is not the same as SYSVIMRC_FILE or DEFVIMRC_FILE.
  354.  */
  355.     if (p_exrc)
  356.     {
  357. #ifdef UNIX
  358.         {
  359.             struct stat s;
  360.  
  361.                 /* if ".vimrc" file is not owned by user, set 'secure' mode */
  362.             if (stat(VIMRC_FILE, &s) || s.st_uid != getuid())
  363.                 secure = p_secure;
  364.         }
  365. #else
  366.         secure = p_secure;
  367. #endif
  368.  
  369.         i = 1;
  370.         if (fullpathcmp(SYSVIMRC_FILE, VIMRC_FILE)
  371. #ifdef DEFVIMRC_FILE
  372.                 && fullpathcmp(DEFVIMRC_FILE, VIMRC_FILE)
  373. #endif
  374.                 )
  375.             i = dosource(VIMRC_FILE);
  376. #ifdef UNIX
  377.         if (i)
  378.         {
  379.             struct stat s;
  380.  
  381.                 /* if ".exrc" file is not owned by user set 'secure' mode */
  382.             if (stat(EXRC_FILE, &s) || s.st_uid != getuid())
  383.                 secure = p_secure;
  384.             else
  385.                 secure = 0;
  386.         }
  387. #endif
  388.         if (i && fullpathcmp(SYSEXRC_FILE, EXRC_FILE))
  389.             dosource(EXRC_FILE);
  390.     }
  391.  
  392. /*
  393.  * Call settmode and starttermcap here, so the T_KS and T_TS may be defined
  394.  * by termcapinit and redifined in .exrc.
  395.  */
  396.     settmode(1);
  397.     starttermcap();
  398.  
  399.     if (secure == 2)        /* done something that is not allowed */
  400.         wait_return(TRUE);        /* must be called after settmode(1) */
  401.     secure = 0;
  402.  
  403. #ifdef AMIGA
  404.     fname_case(fname);        /* set correct case for file name */
  405. #endif
  406.     setfname(fname, NULL);
  407.     maketitle();
  408.  
  409.     if (bin_mode)            /* -b option used */
  410.     {
  411.         p_bin = 1;            /* binary file I/O */
  412.         p_tw = 0;            /* no automatic line wrap */
  413.         p_tx = 0;            /* no text mode */
  414.         p_ta = 0;            /* no text auto */
  415.         p_ml = 0;            /* no modelines */
  416.         p_et = 0;            /* no expand tab */
  417.     }
  418.  
  419. /*
  420.  * Start putting things on the screen.
  421.  * Clear screen first, so file message will not be cleared.
  422.  */
  423.     starting = FALSE;
  424.     screenclear();
  425.     if (Filename != NULL)
  426.         readfile(Filename, sFilename, (linenr_t)0, TRUE);
  427.     else
  428.         msg("Empty Buffer");
  429.     UNCHANGED;
  430.  
  431.     setpcmark();
  432.     if (!tagname)
  433.         startscript();                /* start writing to auto script file */
  434.  
  435.     if (recoverymode && !scriptin[curscript])    /* first do script file, then recover */
  436.         openrecover();
  437.  
  438.     /* position the display and the cursor at the top of the file. */
  439.     Topline = 1;
  440.     Curpos.lnum = 1;
  441.     Curpos.col = 0;
  442.     Cursrow = Curscol = 0;
  443.  
  444.     if (doqf && qf_init())        /* if reading error file fails: exit */
  445.         mch_windexit(3);
  446.  
  447.     if (command)
  448.         docmdline((u_char *)command);
  449.     /*
  450.      * put the :ta command in the stuff buffer here, so that it will not
  451.      * be erased by an emsg().
  452.      */
  453.     if (tagname)
  454.     {
  455.         stuffReadbuff(":ta ");
  456.         stuffReadbuff(tagname);
  457.         stuffReadbuff("\n");
  458.     }
  459.  
  460.     RedrawingDisabled = FALSE;
  461.     updateScreen(NOT_VALID);
  462.  
  463.         /* start in insert mode (already taken care of for :ta command) */
  464.     if (p_im && stuff_empty())
  465.         stuffReadbuff("i");
  466. /*
  467.  * main command loop
  468.  */
  469.     for (;;)
  470.     {
  471.         if (got_int)
  472.         {
  473.             (void)vgetc();                /* flush all buffers */
  474.             got_int = FALSE;
  475.         }
  476.         adjustCurpos();
  477.         if (stuff_empty())                /* only when no command pending */
  478.         {
  479.             cursupdate();    /* Figure out where the cursor is based on Curpos. */
  480.             showruler(0);
  481.  
  482.             if (Visual.lnum)
  483.                 updateScreen(INVERTED);        /* update inverted part */
  484.             if (must_redraw)
  485.                 updateScreen(VALID);
  486.             setcursor();
  487.         }
  488.  
  489.         normal();                        /* get and execute a command */
  490.     }
  491.     /*NOTREACHED*/
  492. }
  493.  
  494.     void
  495. getout(r)
  496.     int             r;
  497. {
  498.     windgoto((int)Rows - 1, 0);
  499.     outchar('\r');
  500.     outchar('\n');
  501.     mch_windexit(r);
  502. }
  503.