home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / x / xvisrc.zoo / startup.c < prev    next >
C/C++ Source or Header  |  1992-07-28  |  10KB  |  409 lines

  1. /* Copyright (c) 1990,1991,1992 Chris and John Downey */
  2. #ifndef lint
  3. static char *sccsid = "@(#)startup.c    2.3 (Chris & John Downey) 9/4/92";
  4. #endif
  5.  
  6. /***
  7.  
  8. * program name:
  9.     xvi
  10. * function:
  11.     PD version of UNIX "vi" editor, with extensions.
  12. * module name:
  13.     main.c
  14. * module function:
  15.     Entry point for xvi; setup, argument parsing and signal handling.
  16. * history:
  17.     STEVIE - ST Editor for VI Enthusiasts, Version 3.10
  18.     Originally by Tim Thompson (twitch!tjt)
  19.     Extensive modifications by Tony Andrews (onecom!wldrdg!tony)
  20.     Heavily modified by Chris & John Downey
  21.  
  22. ***/
  23.  
  24. #include "xvi.h"
  25.  
  26. /*
  27.  * References to the current cursor position, and the window
  28.  * and buffer into which it references. These make the code a
  29.  * lot simpler, but we have to be a bit careful to update them
  30.  * whenever necessary.
  31.  */
  32. Buffer    *curbuf;
  33. Xviwin    *curwin;
  34.  
  35. /*
  36.  * Global variables.
  37.  */
  38. state_t        State = NORMAL;    /* This is the current state of the command */
  39.                 /* interpreter. */
  40.  
  41. unsigned    echo;        /*
  42.                  * bitmap controlling the verbosity of
  43.                  * screen output (see xvi.h for details).
  44.                  */
  45.  
  46. int        indentchars;    /* number of chars indented on current line */
  47.  
  48. volatile unsigned char
  49.         kbdintr;    /*
  50.                  * global flag set when a keyboard interrupt
  51.                  * is received
  52.                  */
  53.  
  54. bool_t        imessage;    /*
  55.                  * global flag to indicate whether we should
  56.                  * display the "Interrupted" message
  57.                  */
  58.  
  59. /*
  60.  * Internal routines.
  61.  */
  62. static    void    usage P((void));
  63.  
  64. Xviwin *
  65. xvi_startup(vs, argc, argv, envp)
  66. VirtScr    *vs;
  67. int    argc;
  68. char    *argv[];
  69. char    *envp;                /* init string from the environment */
  70. {
  71.     char    *tag = NULL;        /* tag from command line */
  72.     char    *pat = NULL;        /* pattern from command line */
  73.     long    line = -1;        /* line number from command line */
  74.     char    **files;
  75.     int        numfiles = 0;
  76.     int        count;
  77.     char    *env;
  78.  
  79.     ignore_signals();
  80.  
  81.     /*
  82.      * Initialise parameter module.
  83.      */
  84.     init_params();
  85.  
  86.     /*
  87.      * Initialise yank/put module.
  88.      */
  89.     init_yankput();
  90.  
  91.     /*
  92.      * The critical path this code has to follow is quite tricky.
  93.      * We can't really run the "env" string until after we've set
  94.      * up the first screen window because we don't know what the
  95.      * commands in "env" might do: they might, for all we know,
  96.      * want to display something. And we can't set up the first
  97.      * screen window until we've set up the terminal interface.
  98.      *
  99.      * Also, we can't read the command line arguments until after
  100.      * we've run the "env" string because a "-s param=value" argument
  101.      * should override any setting of that parameter in the environment.
  102.      *
  103.      * All this means that the usage() function, which tells the
  104.      * user that the command line syntax was wrong, can only be
  105.      * called after the display interface has already been set up,
  106.      * which means we must be in visual mode. So usage() has to
  107.      * switch back to system mode (otherwise, on systems where
  108.      * sys_startv() & sys_endv() switch display pages,
  109.      * the user will never see the output of usage()). So ...
  110.      */
  111.  
  112.     /*
  113.      * Set up the first buffer and screen window.
  114.      * Must call sys_init first.
  115.      */
  116.     curbuf = new_buffer();
  117.     if (curbuf == NULL) {
  118.     sys_endv();
  119.     (void) fputs("Can't allocate buffer memory.\n", stderr);
  120.     sys_exit(2);
  121.     }
  122.     curwin = init_window(vs);
  123.     if (curwin == NULL) {
  124.     sys_endv();
  125.     (void) fputs("Can't allocate buffer memory.\n", stderr);
  126.     sys_exit(2);
  127.     }
  128.  
  129.     /*
  130.      * Connect the two together.
  131.      */
  132.     map_window_onto_buffer(curwin, curbuf);
  133.  
  134.     init_sline(curwin);
  135.  
  136.     /*
  137.      * Save a copy of the passed environment string in case it was
  138.      * obtained from getenv(), so that the subsequent call we make
  139.      * to get the SHELL parameter value does not overwrite it.
  140.      */
  141.     if (envp != NULL) {
  142.     env = strsave(envp);
  143.     } else {
  144.         env = NULL;
  145.     }
  146.  
  147.     /*
  148.      * Try to obtain a value for the "shell" parameter from the
  149.      * environment variable SHELL. If this is NULL, do not override
  150.      * any existing value. The system interface code (sys_init()) is
  151.      * free to set up a default value, and the initialisation string
  152.      * in the next part of the startup is free to override both that
  153.      * value and the one from the environment.
  154.      */
  155.     {
  156.     char    *sh;
  157.  
  158.     sh = getenv("SHELL");
  159.     if (sh != NULL) {
  160.         set_param(P_shell, sh);
  161.     }
  162.     }
  163.  
  164.     /*
  165.      * Run any initialisation string passed to us.
  166.      *
  167.      * We can't really do this until we have set up the terminal
  168.      * because we don't know what the initialisation string might do.
  169.      */
  170.     if (env != NULL) {
  171.     register char    *ep;
  172.     register bool_t    escaped = FALSE;
  173.  
  174.     /*
  175.      * Commands in the initialization string can be
  176.      * separated by '|' (or '\n'), but a literal '|' or
  177.      * '\n' can be escaped by a preceding '\\', so we have
  178.      * to process the string, looking for all three
  179.      * characters.
  180.      */
  181.     for (ep = env; *ep;) {
  182.         switch (*ep++) {
  183.         case '\\':
  184.         escaped = TRUE;
  185.         continue;
  186.         case '|':
  187.         case '\n':
  188.         if (escaped) {
  189.             register char *s, *d;
  190.  
  191.             for (d = (s = --ep) - 1; (*d++ = *s++) != '\0'; )
  192.             ;
  193.         } else {
  194.             ep[-1] = '\0';
  195.             do_colon(env, FALSE);
  196.             env = ep;
  197.         }
  198.         /* fall through ... */
  199.         default:
  200.         escaped = FALSE;
  201.         }
  202.     }
  203.     if (ep > env) {
  204.         do_colon(env, FALSE);
  205.     }
  206.     }
  207.  
  208.     /*
  209.      * Process the command line arguments.
  210.      *
  211.      * We can't really do this until we have run the "env" string,
  212.      * because "-s param=value" on the command line should override
  213.      * parameter setting in the environment.
  214.      *
  215.      * This is a bit awkward because it means usage() is called
  216.      * when we're already in vi mode (which means, among other
  217.      * things, that display pages may have been swapped).
  218.      */
  219.     for (count = 1;
  220.      count < argc && (argv[count][0] == '-' || argv[count][0] == '+');
  221.                                 count++) {
  222.  
  223.     if (argv[count][0] == '-') {
  224.         switch (argv[count][1]) {
  225.         case 't':
  226.         /*
  227.          * -t tag or -ttag
  228.          */
  229.         if (numfiles != 0)
  230.             usage();
  231.         if (argv[count][2] != '\0') {
  232.             tag = &(argv[count][2]);
  233.         } else if (count < (argc - 1)) {
  234.             count += 1;
  235.             tag = argv[count];
  236.         } else {
  237.             usage();
  238.         }
  239.         break;
  240.  
  241.         case 's':
  242.         /*
  243.          * -s param=value or
  244.          * -sparam=value
  245.          */
  246.         if (argv[count][2] != '\0') {
  247.             argv[count] += 2;
  248.         } else if (count < (argc - 1)) {
  249.             count += 1;
  250.         } else {
  251.             usage();
  252.         }
  253.         do_set(curwin, 1, &argv[count], FALSE);
  254.         break;
  255.  
  256.         default:
  257.         usage();
  258.         }
  259.  
  260.     } else /* argv[count][0] == '+' */ {
  261.         char    nc;
  262.  
  263.         /*
  264.          * "+n file" or "+/pat file"
  265.          */
  266.         if (count >= (argc - 1))
  267.         usage();
  268.  
  269.         nc = argv[count][1];
  270.         if (nc == '/') {
  271.         pat = &(argv[count][2]);
  272.         } else if (is_digit(nc)) {
  273.         line = atol(&(argv[count][1]));
  274.         } else if (nc == '\0') {
  275.         line = 0;
  276.         } else {
  277.         usage();
  278.         }
  279.         count += 1;
  280.         files = &argv[count];
  281.         numfiles = 1;
  282.     }
  283.     }
  284.     if (numfiles != 0 || tag != NULL) {
  285.     /*
  286.      * If we found "-t tag", "+n file" or "+/pat file" on
  287.      * the command line, we don't want to see any more
  288.      * file names.
  289.      */
  290.     if (count < argc)
  291.         usage();
  292.     } else {
  293.     /*
  294.      * Otherwise, file names are valid.
  295.      */
  296.     numfiles = argc - count;
  297.     if (numfiles > 0) {
  298.         files = &(argv[count]);
  299.     }
  300.     }
  301.  
  302.     /*
  303.      * Initialise the cursor and top of screen pointers
  304.      * to the start of the first buffer. Note that the
  305.      * bottom of screen pointer is also set up, as some
  306.      * code (e.g. move_window_to_cursor) depends on it.
  307.      */
  308.     curwin->w_topline = curbuf->b_file;
  309.     curwin->w_botline = curbuf->b_file->l_next;
  310.     move_cursor(curwin, curbuf->b_file, 0);
  311.     curwin->w_col = 0;
  312.     curwin->w_row = 0;
  313.  
  314.     /*
  315.      * Clear the window.
  316.      *
  317.      * It doesn't make sense to do this until we have a value for
  318.      * Pn(P_colour).
  319.      */
  320.     clear(curwin);
  321.  
  322.     if (numfiles != 0) {
  323.     if (line < 0 && pat == NULL)
  324.         echo = e_CHARUPDATE | e_SHOWINFO;
  325.  
  326.     do_next(curwin, numfiles, files, FALSE);
  327.  
  328.     if (pat != NULL) {
  329.         echo = e_CHARUPDATE | e_SHOWINFO | e_REGERR | e_NOMATCH;
  330.         (void) dosearch(curwin, pat, '/');
  331.     } else if (line >= 0) {
  332.         echo = e_CHARUPDATE | e_SHOWINFO;
  333.         do_goto((line > 0) ? line : MAX_LINENO);
  334.     }
  335.  
  336.     } else if (tag != NULL) {
  337.     echo = e_CHARUPDATE | e_SHOWINFO | e_REGERR | e_NOMATCH;
  338.     if (do_tag(curwin, tag, FALSE, TRUE, FALSE) == FALSE) {
  339.         /*
  340.          * Failed to find tag - wait for a while
  341.          * to allow user to read tags error and then
  342.          * display the "no file" message.
  343.          */
  344.         sleep(2);
  345.         show_file_info(curwin);
  346.     }
  347.     } else {
  348.     echo = e_CHARUPDATE | e_SHOWINFO;
  349.     show_file_info(curwin);
  350.     }
  351.  
  352.     setpcmark(curwin);
  353.  
  354.     echo = e_CHARUPDATE;
  355.  
  356.     /*
  357.      * Ensure we are at the right screen position.
  358.      */
  359.     move_window_to_cursor(curwin);
  360.  
  361.     /*
  362.      * Draw the screen.
  363.      */
  364.     update_all();
  365.  
  366.     /*
  367.      * Update the cursor position on the screen, and go there.
  368.      */
  369.     cursupdate(curwin);
  370.     wind_goto(curwin);
  371.  
  372.     /*
  373.      * Allow everything.
  374.      */
  375.     echo = e_ANY;
  376.  
  377.     catch_signals();
  378.  
  379.     if (env != NULL) {
  380.     free(env);
  381.     }
  382.  
  383.     return(curwin);
  384. }
  385.  
  386. /*
  387.  * Print usage message and die.
  388.  *
  389.  * This function is only called after we have set the terminal to vi
  390.  * mode.
  391.  *
  392.  * The system interface functions have to ensure that it's safe to
  393.  * call sys_exit() when sys_endv() has already been called (& there
  394.  * hasn't necessarily been any intervening sys_startv()).
  395.  */
  396. static void
  397. usage()
  398. {
  399.     sys_endv();
  400.     (void) fputs("Usage: xvi { options } [ file ... ]\n", stderr);
  401.     (void) fputs("       xvi { options } -t tag\n", stderr);
  402.     (void) fputs("       xvi { options } +[num] file\n", stderr);
  403.     (void) fputs("       xvi { options } +/pat  file\n", stderr);
  404.     (void) fputs("\nOptions are:\n", stderr);
  405.     (void) fputs("       -s [no]boolean-parameter\n", stderr);
  406.     (void) fputs("       -s parameter=value\n", stderr);
  407.     sys_exit(1);
  408. }
  409.