home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / main.c < prev    next >
C/C++ Source or Header  |  1998-10-01  |  51KB  |  2,208 lines

  1. /*
  2.  *    This used to be MicroEMACS 3.9
  3.  *            written by Dave G. Conroy.
  4.  *            substantially modified by Daniel M. Lawrence
  5.  *
  6.  *    Turned into "VI Like Emacs", a.k.a. vile, by Paul Fox
  7.  *
  8.  *    (C)opyright 1987 by Daniel M. Lawrence
  9.  *    MicroEMACS 3.9 can be copied and distributed freely for any
  10.  *    non-commercial purposes. MicroEMACS 3.9 can only be incorporated
  11.  *    into commercial software with the permission of the current author.
  12.  *
  13.  *    The same goes for vile.  -pgf, 1990-1995
  14.  *
  15.  *
  16.  * $Header: /usr/build/vile/vile/RCS/main.c,v 1.338 1998/10/01 09:17:03 tom Exp $
  17.  *
  18.  */
  19.  
  20. /* Make global definitions not external */
  21. #define realdef
  22. #include    "estruct.h"    /* global structures and defines */
  23. #include    "edef.h"    /* global definitions */
  24. #include    "nevars.h"
  25. #include    "nefunc.h"
  26.  
  27. #if OPT_LOCALE
  28. #include    <locale.h>
  29. #include    <ctype.h>
  30. #endif
  31.  
  32. #if CC_NEWDOSCC
  33. #include <io.h>
  34. #if CC_DJGPP
  35. #include <dpmi.h>
  36. #include <go32.h>
  37. #endif
  38. #endif
  39.  
  40. #if SYS_VMS
  41. #include <processes.h>
  42. #endif
  43.  
  44. extern char *exec_pathname;
  45. extern const char *const pathname[];    /* startup file path/name array */
  46.  
  47. /* for MSDOS, increase the default stack space */
  48. #if    SYS_MSDOS && CC_TURBO
  49. unsigned _stklen = 32768U;
  50. #endif
  51.  
  52. static    void    get_executable_dir (void);
  53. static    void    global_val_init (void);
  54. static    void    loop (void);
  55. static    void    siginit (void);
  56. static    void    start_debug_log(int ac, char **av);
  57. static    int    cmd_mouse_motion(const CMDFUNC *cfp);
  58.  
  59. extern const int nametblsize;
  60.  
  61. /*--------------------------------------------------------------------------*/
  62. #define    GetArgVal(param)    if (!*(++param))\
  63.                     param = argv[++carg];\
  64.                 if (param == 0)\
  65.                     print_usage()
  66.  
  67. int
  68. MainProgram(int argc, char *argv[])
  69. {
  70.     int tt_opened;
  71.     register BUFFER *bp;        /* temp buffer pointer */
  72.     register int    carg;        /* current arg to scan */
  73.     char *vileinit = NULL;        /* the startup file or VILEINIT var */
  74.     int startstat = TRUE;        /* result of running startup */
  75.     BUFFER *firstbp = NULL;     /* ptr to first buffer in cmd line */
  76.     char *firstname = NULL;        /* name of first buffer in cmd line */
  77.     int gotoflag = FALSE;        /* do we need to goto line at start? */
  78.     int gline = FALSE;        /* if so, what line? */
  79.     int helpflag = FALSE;        /* do we need help at start? */
  80.     REGEXVAL *search_exp = 0;    /* initial search-pattern */
  81.     const char *msg;
  82. #ifdef VILE_OLE
  83.     int ole_register = FALSE;
  84. #endif
  85. #if DISP_X11 && !XTOOLKIT
  86.     int do_newgroup = FALSE;    /* do we spawn at start? */
  87. #endif
  88. #if OPT_TAGS
  89.     int didtag = FALSE;        /* look up a tag to start? */
  90.     char *tname = NULL;
  91. #endif
  92. #if    OPT_ENCRYPT
  93.     char ekey[NPAT];        /* startup encryption key */
  94.     *ekey = EOS;
  95. #endif
  96.  
  97. #if OPT_LOCALE
  98.     setlocale(LC_CTYPE, "");
  99. #endif
  100.  
  101. #if OPT_NAMEBST
  102.     build_namebst(nametbl, 0, nametblsize - 1);
  103. #endif
  104.     global_val_init();    /* global buffer values */
  105.     charinit();        /* character types -- we need these early  */
  106.     winit(FALSE);        /* command-line */
  107. #if !SYS_UNIX
  108.     expand_wild_args(&argc, &argv);
  109. #endif
  110.     prog_arg = argv[0];    /* this contains our only clue to exec-path */
  111.  
  112.     start_debug_log(argc,argv);
  113.  
  114.     get_executable_dir();
  115.  
  116.     if (strcmp(pathleaf(prog_arg), "view") == 0)
  117.         set_global_b_val(MDREADONLY,TRUE);
  118.  
  119. #if DISP_X11
  120.     if (argc != 2 || strcmp(argv[1], "-V") != 0)
  121.         x_preparse_args(&argc, &argv);
  122. #endif
  123.     /*
  124.      * Allow for I/O to the command-line before we initialize the screen
  125.      * driver.
  126.      *
  127.      * FIXME: we only know how to do this for displays that open the
  128.      * terminal in the same way for command-line and screen.
  129.      */
  130.     siginit();
  131. #if OPT_DUMBTERM
  132.     if (isatty(fileno(stdin))
  133.      && isatty(fileno(stdout))) {
  134.         tt_opened = open_terminal(&dumb_term);
  135.     } else
  136. #endif
  137.      tt_opened = open_terminal(&null_term);
  138.  
  139.     /* Parse the command line */
  140.     for (carg = 1; carg < argc; ++carg) {
  141.         register char *param = argv[carg];
  142. #if DISP_X11 && !XTOOLKIT
  143.         if (*param == '=') {
  144.             x_set_geometry(param);
  145.             continue;
  146.         }
  147. #endif
  148.  
  149.         /* Process Switches */
  150.         if (*param == '-') {
  151.             ++param;
  152. #if DISP_IBMPC || DISP_BORLAND
  153.                 /* if it's a digit, it's probably a screen
  154.                 resolution */
  155.             if (isDigit(*param)) {
  156.                 current_res_name = param;
  157.                 continue;
  158.             } else
  159. #endif    /* DISP_IBMPC */
  160.             switch (*param) {
  161. #if DISP_X11 && !XTOOLKIT
  162.             case 'd':
  163.                 if ((param = argv[++carg]) != 0)
  164.                     x_set_dpy(param);
  165.                 else
  166.                     print_usage();
  167.                 break;
  168.             case 'r':
  169.                 x_set_rv();
  170.                 break;
  171.             case 'f':
  172.                 if (argv[++carg] != 0) {
  173.                     if (strcmp(param, "foreground") == 0
  174.                      || strcmp(param, "fg") == 0)
  175.                         x_setforeground(argv[carg]);
  176.                     else if (!strcmp(param, "fork"))
  177.                         do_newgroup = TRUE;
  178.                     else
  179.                         x_setfont(argv[carg]);
  180.                 } else
  181.                     print_usage();
  182.                 break;
  183.             case 'b':
  184.                 if (argv[++carg] != 0) {
  185.                     if (strcmp(param, "background") == 0
  186.                      || strcmp(param, "bg") == 0)
  187.                         x_setbackground(argv[carg]);
  188.                 } else
  189.                     print_usage();
  190.                 break;
  191.             case 'n':
  192.                 if (strcmp(param, "name") == 0
  193.                  && argv[++carg] != 0)
  194.                     x_setname(argv[carg]);
  195.                 else
  196.                     print_usage();
  197.                 break;
  198.             case 'w':
  199.                 if (strcmp(param, "wm") == 0
  200.                  && argv[++carg] != 0)
  201.                     x_set_wm_title(argv[carg]);
  202.                 else
  203.                     print_usage();
  204.                 break;
  205. #endif /* DISP_X11 */
  206.             case 'e':    /* -e for Edit file */
  207.             case 'E':
  208.                 set_global_b_val(MDVIEW,FALSE);
  209.                 break;
  210.             case 'g':    /* -g for initial goto */
  211.             case 'G':
  212.                 gotoflag = TRUE;
  213.                 GetArgVal(param);
  214.                 gline = atoi(param);
  215.                 break;
  216.             case 'h':    /* -h for initial help */
  217.             case 'H':
  218.                 helpflag = TRUE;
  219.                 break;
  220. #if    OPT_ENCRYPT
  221.             case 'k':    /* -k<key> for code key */
  222.             case 'K':
  223.                 GetArgVal(param);
  224.                 (void)strcpy(ekey, param);
  225.                 (void)memset(param, '.', strlen(param));
  226.                 ue_crypt((char *)0, 0);
  227.                 ue_crypt(ekey, strlen(ekey));
  228.                 break;
  229. #endif
  230. #ifdef VILE_OLE
  231.             case 'O':
  232.                 if (param[1] == 'r')
  233.                     ole_register = TRUE;
  234.                 else
  235.                     print_usage();
  236.                 break;
  237. #endif
  238.             case 's':  /* -s for initial search string */
  239.             case 'S':
  240.         dosearch:
  241.                 GetArgVal(param);
  242.                 search_exp = new_regexval(param, global_b_val(MDMAGIC));
  243.                 break;
  244. #if OPT_TAGS
  245.             case 't':  /* -t for initial tag lookup */
  246.             case 'T':
  247.                 GetArgVal(param);
  248.                 tname = param;
  249.                 break;
  250. #endif
  251.             case 'v':    /* -v is view mode */
  252.                 set_global_b_val(MDVIEW,TRUE);
  253.                 break;
  254.  
  255.             case 'R':    /* -R is readonly mode (like "view") */
  256.                 set_global_b_val(MDREADONLY,TRUE);
  257.                 break;
  258.  
  259.             case 'V':
  260. #if DISP_NTWIN
  261.                 gui_version(prog_arg);
  262. #else
  263.                 (void)printf("%s\n", getversion());
  264. #endif
  265.                 tidy_exit(GOODEXIT);
  266.  
  267.                 /* FALLTHROUGH */
  268.  
  269.             case '?':
  270.             default:    /* unknown switch */
  271.                 print_usage();
  272.             }
  273.  
  274.         } else if (*param == '+') { /* alternate form of -g */
  275.             if (*(++param) == '/') {
  276.                 int len = strlen(param);
  277.                 if (len > 0 && param[len-1] == '/')
  278.                     param[--len] = EOS;
  279.                 if (len == 0)
  280.                     print_usage();
  281.                 goto dosearch;
  282.             }
  283.             gotoflag = TRUE;
  284.             gline = atoi(param);
  285.         } else if (*param == '@') {
  286.             vileinit = ++param;
  287.         } else if (*param != EOS) {
  288.  
  289.             /* Process an input file */
  290. #if OPT_ENCRYPT
  291.             cryptkey = (*ekey != EOS) ? ekey : 0;
  292. #endif
  293.             /* set up a buffer for this file */
  294.             bp = getfile2bp(param,FALSE,TRUE);
  295.             if (bp) {
  296.                 bp->b_flag |= BFARGS;    /* treat this as an argument */
  297.                 make_current(bp); /* pull it to the front */
  298.                 if (firstbp == 0) {
  299.                     firstbp = bp;
  300.                     firstname = param;
  301.                 }
  302.             }
  303. #if OPT_ENCRYPT
  304.             cryptkey = 0;
  305. #endif
  306.         }
  307.     }
  308. #ifdef VILE_OLE
  309.     if (ole_register)
  310.     {
  311.         /*
  312.          * Now that all command line options have been successfully
  313.          * parsed, register the OLE automation server and exit.
  314.          */
  315.  
  316.         ntwinio_oleauto_reg();
  317.         /* NOT REACHED */
  318.     }
  319. #endif
  320.  
  321.  
  322.     /* if stdin isn't a terminal, assume the user is trying to pipe a
  323.      * file into a buffer.
  324.      */
  325. #if SYS_UNIX || SYS_VMS || SYS_MSDOS || SYS_WIN31 || SYS_OS2 || SYS_WINNT
  326. #if DISP_NTWIN
  327.     if (stdin_data_available())
  328. #else
  329.     if (!isatty(fileno(stdin)))
  330. #endif
  331.     {
  332.  
  333. #if !DISP_X11
  334. #if SYS_UNIX
  335. # if HAS_TTYNAME
  336.         char    *tty = ttyname(fileno(stderr));
  337. # else
  338.         char    *tty = "/dev/tty";
  339. # endif
  340. #else
  341.           FILE    *in;
  342.           int    fd;
  343. #endif /* SYS_UNIX */
  344. #endif /* DISP_X11 */
  345.         BUFFER    *lastbp = firstbp;
  346.         int    nline = 0;
  347.  
  348.         bp = bfind(STDIN_BufName, BFARGS);
  349.         make_current(bp); /* pull it to the front */
  350.         if (firstbp == 0)
  351.             firstbp = bp;
  352.         ffp = fdopen(dup(fileno(stdin)), "r");
  353. #if !DISP_X11
  354. # if SYS_UNIX
  355.         /*
  356.          * Note: On Linux, the low-level close/dup operation
  357.          * doesn't work, since something hangs, apparently
  358.          * because substituting the file descriptor doesn't communicate
  359.          * properly up to the stdio routines.
  360.          */
  361.         if ((freopen(tty, "r", stdin)) == 0
  362.          || !isatty(fileno(stdin))) {
  363.             fputs("cannot open a terminal\n", stderr);
  364.             tidy_exit(BADEXIT);
  365.         }
  366. #else
  367. # if SYS_WINNT
  368. #  if DISP_NTCONS
  369.         /*
  370.          * The editor must reopen the console, not fd 0.  If the console
  371.          * is not reopened, the nt console I/O routines die immediately
  372.          * when attempting to fetch a STDIN handle.
  373.          */
  374.         freopen("con", "r", stdin);
  375. #  endif
  376. # else
  377. #  if SYS_VMS
  378.           fd = open("tt:", O_RDONLY, S_IREAD); /* or sys$command */
  379. #  else                    /* e.g., DOS-based systems */
  380.           fd = fileno(stderr);    /* this normally cannot be redirected */
  381. #  endif
  382.           if ((fd >= 0)
  383.            && (close(0) >= 0)
  384.            && (fd = dup(fd)) == 0
  385.            && (in = fdopen(fd, "r")) != 0)
  386.               *stdin = *in;
  387. #  endif /* SYS_WINNT */
  388. # endif /* SYS_UNIX */
  389. #endif /* DISP_X11 */
  390.  
  391.           (void)slowreadf(bp, &nline);
  392.         set_rdonly(bp, bp->b_fname, MDREADONLY);
  393.         (void)ffclose();
  394.  
  395.         if (is_empty_buf(bp)) {
  396.             (void)zotbuf(bp);
  397.             curbp = firstbp = lastbp;
  398.         }
  399. #if OPT_FINDERR
  400.           else {
  401.             set_febuff(bp->b_bname);
  402.         }
  403. #endif
  404.     }
  405. #endif
  406.  
  407. #if DISP_X11 && !XTOOLKIT
  408.     if (do_newgroup)
  409.         (void) newprocessgroup(TRUE,1);
  410. #endif
  411.     /* initialize the editor */
  412.  
  413.     if (!tt_opened)
  414.         siginit();
  415.     (void)open_terminal((TERM *)0);
  416.     TTkopen();        /* open the keyboard */
  417.     TTrev(FALSE);
  418.  
  419.     if (vtinit() != TRUE)    /* allocate display memory */
  420.         tidy_exit(BADEXIT);
  421.  
  422.     winit(TRUE);        /* windows */
  423.  
  424.     /* this comes out to 70 on an 80 (or greater) column display */
  425.     {    register int fill;
  426.         fill = (7 * term.t_ncol) / 8;  /* must be done after vtinit() */
  427.         if (fill > 70) fill = 70;
  428.         set_global_b_val(VAL_FILL, fill);
  429.     }
  430.  
  431.     /* Create an unnamed buffer, so that the initialization-file will have
  432.      * something to work on.  We don't pull in any of the command-line
  433.      * filenames yet, because some of the initialization stuff has to be
  434.      * triggered by switching buffers after reading the .vilerc file.
  435.      *
  436.      * If nothing modifies it, this buffer will be automatically removed
  437.      * when we switch to the first file (e.g., firstbp), because it is
  438.      * empty (and presumably isn't named the same as an actual file).
  439.      */
  440.     bp = bfind(UNNAMED_BufName, 0);
  441.     bp->b_active = TRUE;
  442. #if OPT_DOSFILES
  443.     /* an empty non-existent buffer defaults to line-style
  444.         favored by the OS */
  445.     make_local_b_val(bp, MDDOS);
  446.     set_b_val(bp, MDDOS, CRLF_LINES);
  447. #endif
  448.     fix_cmode(bp, FALSE);
  449.     swbuffer(bp);
  450.  
  451.     /* run the specified, or the system startup file here.
  452.        if vileinit is set, it's the name of the user's
  453.        command-line startup file, i.e. 'vile @mycmds'
  454.      */
  455.     if (vileinit && *vileinit) {
  456.         if ((startstat = do_source(vileinit,1, FALSE)) != TRUE)
  457.             goto begin;
  458.         free(startup_file);
  459.         startup_file = strmalloc(vileinit);
  460.     } else {
  461.  
  462.         /* now vileinit is the contents of their VILEINIT variable */
  463.         vileinit = getenv("VILEINIT");
  464.         if (vileinit != NULL) { /* set... */
  465.             int odiscmd;
  466.             BUFFER *vbp, *obp;
  467.             UINT oflags = 0;
  468.             if (*vileinit) { /* ...and not null */
  469.                 /* mark as modified, to prevent
  470.                  * undispbuff() from clobbering */
  471.                 obp = curbp;
  472.                 if (obp) {
  473.                     oflags = obp->b_flag;
  474.                     b_set_changed(obp);
  475.                 }
  476.  
  477.                 if ((vbp=bfind(VILEINIT_BufName, BFEXEC)) == 0)
  478.                     tidy_exit(BADEXIT);
  479.  
  480.                 /* don't want swbuffer to try to read it */
  481.                 vbp->b_active = TRUE;
  482.                 swbuffer(vbp);
  483.                 b_set_scratch(vbp);
  484.                 bprintf("%s", vileinit);
  485.                 /* if we leave it scratch, swbuffer(obp)
  486.                     may zot it, and we may zot it again */
  487.                 b_clr_scratch(vbp);
  488.                 set_rdonly(vbp, vbp->b_fname, MDVIEW);
  489.  
  490.                 /* go execute it! */
  491.                 odiscmd = discmd;
  492.                 discmd = FALSE;
  493.                 startstat = dobuf(vbp);
  494.                 discmd = odiscmd;
  495.                 if (startstat != TRUE)
  496.                     goto begin;
  497.                 if (obp) {
  498.                     swbuffer(obp);
  499.                     obp->b_flag = oflags;
  500.                 }
  501.                 /* remove the now unneeded buffer */
  502.                 b_set_scratch(vbp);  /* make sure it will go */
  503.                 (void)zotbuf(vbp);
  504.             }
  505.         } else {  /* find and run .vilerc */
  506.             startstat = do_source(startup_file, 1, TRUE);
  507.             if (startstat != TRUE)
  508.                 goto begin;
  509.         }
  510.     }
  511.  
  512.     /* If there are any files to read, read the first one!  Double-check,
  513.      * however, since a startup-script may have removed the first buffer.
  514.      */
  515.     if (firstbp != 0
  516.      && find_bp(firstbp)) {
  517.         if (find_bp(bp) && is_empty_buf(bp) && !b_is_changed(bp))
  518.             b_set_scratch(bp);    /* remove the unnamed-buffer */
  519.         startstat = swbuffer(firstbp);
  520.         if (firstname)
  521.             set_last_file_edited(firstname);
  522.         if (bp2any_wp(bp) && bp2any_wp(firstbp))
  523.             zotwp(bp);
  524.     }
  525. #if OPT_TAGS
  526.     else if (tname) {
  527.         cmdlinetag(tname);
  528.         didtag = TRUE;
  529.     }
  530. #endif
  531.     msg = s_NULL;
  532.     if (helpflag) {
  533.         if (help(TRUE,1) != TRUE) {
  534.             msg =
  535.     "[Problem with help information. Type \":quit\" to exit if you wish]";
  536.         }
  537.     } else {
  538.         msg = "[Use ^A-h, ^X-h, or :help to get help]";
  539.     }
  540.  
  541.     /* Deal with startup gotos and searches */
  542.     if (gotoflag + (search_exp != 0)
  543. #if OPT_TAGS
  544.          + (tname?1:0)
  545. #endif
  546.         > 1) {
  547. #if OPT_TAGS
  548.         msg = "[Search, goto and tag are used one at a time]";
  549. #else
  550.         msg = "[Cannot search and goto at the same time]";
  551. #endif
  552.     } else if (gotoflag) {
  553.         if (gotoline(gline != 0, gline) == FALSE) {
  554.             msg = "[Not that many lines in buffer]";
  555.             (void)gotoeob(FALSE,1);
  556.         }
  557.     } else if (search_exp) {
  558.         FreeIfNeeded(gregexp);
  559.         (void)strncpy0(pat, search_exp->pat, NPAT);
  560.         gregexp = search_exp->reg;
  561.         (void)forwhunt(FALSE, 0);
  562. #if OPT_TAGS
  563.     } else if (tname && !didtag) {
  564.         cmdlinetag(tname);
  565. #endif
  566.     }
  567.  
  568. #if OPT_POPUP_MSGS
  569.     purge_msgs();
  570. #endif
  571.     if (startstat == TRUE)  /* else there's probably an error message */
  572.         mlforce(msg);
  573.  
  574.  begin:
  575.     (void)update(FALSE);
  576.  
  577. #if OPT_POPUP_MSGS
  578.     if (global_g_val(GMDPOPUP_MSGS) && (startstat != TRUE)) {
  579.         bp = bfind(MESSAGES_BufName, BFSCRTCH);
  580.         bsizes(bp);
  581.         TRACE(("Checking size of popup messages: %d\n", bp->b_linecount))
  582.         if (bp->b_linecount > 1) {
  583.             popup_msgs();
  584.             *mlsave = EOS;
  585.         }
  586.     }
  587.     if (global_g_val(GMDPOPUP_MSGS) == -TRUE)
  588.         set_global_g_val(GMDPOPUP_MSGS, FALSE);
  589. #endif
  590.  
  591.     /* We won't always be able to show messages before the screen is
  592.      * initialized.  Give it one last chance.
  593.      */
  594.     if ((startstat != TRUE) && *mlsave)
  595.         mlforce("%s", mlsave);
  596.  
  597.     /* process commands */
  598.     loop();
  599.  
  600.     /* NOTREACHED */
  601.     return BADEXIT;
  602. }
  603.  
  604. /* this is nothing but the main command loop */
  605. static void
  606. loop(void)
  607. {
  608.     const CMDFUNC
  609.         *cfp = NULL,
  610.         *last_cfp = NULL,
  611.         *last_failed_motion_cfp = NULL;
  612.     int s,c,f,n;
  613.  
  614.  
  615.     for_ever {
  616.  
  617.         /* vi doesn't let the cursor rest on the newline itself.  This
  618.             takes care of that. */
  619.         /* if we're inserting, or will be inserting again, then
  620.             suppress.  this happens if we're using arrow keys
  621.             during insert */
  622.         if (is_at_end_of_line(DOT) && (DOT.o > w_left_margin(curwp)) &&
  623.                 !insertmode && !cmd_mouse_motion(cfp))
  624.             backchar(TRUE,1);
  625.  
  626.         /* same goes for end-of-file -- I'm actually not sure if
  627.             this can ever happen, but I _am_ sure that it's
  628.             a lot safer not to let it... */
  629.         if (is_header_line(DOT,curbp) && !is_empty_buf(curbp))
  630.             (void)backline(TRUE,1);
  631.  
  632.         /* start recording for '.' command */
  633.         dotcmdbegin();
  634.  
  635.         /* Fix up the screen    */
  636.         s = update(FALSE);
  637.  
  638.         /* get the next command from the keyboard */
  639.         c = kbd_seq();
  640.  
  641.         /* if there is something on the command line, clear it */
  642.         if (kbd_length() > 0) {
  643.             mlerase();
  644.             if (s != SORTOFTRUE) /* did nothing due to typeahead */
  645.                 (void)update(FALSE);
  646.         }
  647.  
  648.         f = FALSE;
  649.         n = 1;
  650.  
  651. #if LATERMAYBE
  652. /* insertion is too complicated to pop in
  653.     and out of so glibly...   -pgf */
  654. #ifdef insertmode
  655.         /* FIXME: Paul and Tom should check this over. */
  656.         if (insertmode != FALSE) {
  657.             if (!kbd_replaying(FALSE))
  658.                 mayneedundo();
  659.             unkeystroke(c);
  660.             insert(f,n);
  661.             dotcmdfinish();
  662.             continue;
  663.         }
  664. #endif /* insertmode */
  665. #endif /* LATERMAYBE */
  666.  
  667.         do_repeats(&c,&f,&n);
  668.  
  669.         kregflag = 0;
  670.  
  671.         /* flag the first time through for some commands -- e.g. subst
  672.             must know to not prompt for strings again, and pregion
  673.             must only restart the p-lines buffer once for each
  674.             command. */
  675.         calledbefore = FALSE;
  676.  
  677.         /* and execute the command */
  678.         cfp = kcod2fnc(c);
  679.  
  680.         if (cfp == &f_dotcmdplay &&
  681.             (last_cfp == &f_undo ||
  682.              last_cfp == &f_forwredo ||
  683.              last_cfp == &f_backundo ||
  684.              last_cfp == &f_inf_undo))
  685.             cfp = &f_inf_undo;
  686.  
  687.         s = execute(cfp, f, n);
  688.  
  689.         last_cfp = cfp;
  690.  
  691.         /* stop recording for '.' command */
  692.         dotcmdfinish();
  693.  
  694.         /* If this was a motion that failed, sound the alarm (like vi),
  695.          * but limit it to once, in case the user is holding down the
  696.          * autorepeat-key.
  697.          */
  698.         if ( (cfp != NULL)
  699.          && ((cfp->c_flags & MOTION) != 0)
  700.          && (s == FALSE) ) {
  701.             if (cfp != last_failed_motion_cfp ||
  702.                     global_g_val(GMDMULTIBEEP)) {
  703.                 last_failed_motion_cfp = cfp;
  704.                 kbd_alarm();
  705.             }
  706.         } else {
  707.             last_failed_motion_cfp = NULL; /* avoid noise! */
  708.         }
  709.  
  710.         attrib_matches();
  711.         regionshape = EXACT;
  712.  
  713.     }
  714. }
  715.  
  716. /* attempt to locate the executable that contains our code.
  717. * leave its directory name in exec_pathname and shorten prog_arg
  718. * to the simple filename (no path).
  719. */
  720. static void
  721. get_executable_dir(void)
  722. {
  723. #if SYS_UNIX || SYS_VMS
  724.     char    temp[NFILEN];
  725.     char    *s, *t;
  726.  
  727.     if (last_slash(prog_arg) == NULL) {
  728.         /* If there are no slashes, we can guess where we came from,
  729.          */
  730.         if ((s = flook(prog_arg, FL_PATH|FL_EXECABLE)) != 0)
  731.             s = strmalloc(s);
  732.     } else {
  733.         /* if there _are_ slashes, then argv[0] was either
  734.          * absolute or relative. lengthen_path figures it out.
  735.          */
  736.         s = strmalloc(lengthen_path(strcpy(temp, prog_arg)));
  737.     }
  738.     if (s == 0)
  739.         return;
  740.  
  741.     t = pathleaf(s);
  742.     if (t != s) {
  743. # if SYS_UNIX    /* 't' points past slash */
  744.         t[-1] = EOS;
  745.         prog_arg = t;
  746. # else        /* 't' points to ']' */
  747.         *t = EOS;
  748.         prog_arg = t+1;
  749. # endif
  750.         exec_pathname = s;
  751.     } else
  752.         free(s);
  753. #endif
  754. }
  755.  
  756. void
  757. tidy_exit(int code)
  758. {
  759.     ttclean (TRUE);
  760. #if SYS_UNIX
  761.     setup_handler(SIGHUP,SIG_IGN);
  762. #endif
  763.     ExitProgram(code);
  764. }
  765.  
  766. #ifndef strmalloc
  767. char *
  768. strmalloc(const char *s)
  769. {
  770.     register char *ns = castalloc(char,strlen(s)+1);
  771.     if (ns != 0)
  772.         (void)strcpy(ns,s);
  773.     return ns;
  774. }
  775. #endif
  776.  
  777. int
  778. no_memory(const char *s)
  779. {
  780.     mlforce("[%s] %s", out_of_mem, s);
  781.     return FALSE;
  782. }
  783.  
  784. static void
  785. global_val_init(void)
  786. {
  787.     static const char expand_chars[] =
  788.         { EXPC_THIS, EXPC_THAT, EXPC_SHELL, EXPC_TOKEN, EXPC_RPAT, 0 };
  789.     register int i;
  790.     char *s;
  791.  
  792.     /* set up so the global value pointers point at the global
  793.         values.  we never actually use the global pointers
  794.         directly, but when buffers get a copy of the
  795.         global_b_values structure, the pointers will still point
  796.         back at the global values, which is what we want */
  797.     for (i = 0; i <= NUM_G_VALUES; i++)
  798.         make_local_val(global_g_values.gv, i);
  799.  
  800.     for (i = 0; i <= NUM_B_VALUES; i++)
  801.         make_local_val(global_b_values.bv, i);
  802.  
  803.     for (i = 0; i <= NUM_W_VALUES; i++)
  804.         make_local_val(global_w_values.wv, i);
  805.  
  806. #if OPT_MAJORMODE
  807.     /*
  808.      * Built-in majormodes
  809.      */
  810.     alloc_mode("c", TRUE);
  811. #endif
  812.  
  813.     /*
  814.      * Universal-mode defaults
  815.      */
  816.     set_global_g_val(GMDABUFF,    TRUE);     /* auto-buffer */
  817.     set_global_g_val(GMDALTTABPOS,    FALSE); /* emacs-style tab
  818.                             positioning */
  819. #ifdef GMDDIRC
  820.     set_global_g_val(GMDDIRC,    FALSE); /* directory-completion */
  821. #endif
  822.     set_global_g_val(GMDERRORBELLS, TRUE);    /* alarms are noticeable */
  823. #if OPT_FLASH
  824.     set_global_g_val(GMDFLASH,      FALSE);    /* beeps beep by default */
  825. #endif
  826. #ifdef GMDW32PIPES
  827.     set_global_g_val(GMDW32PIPES,      is_winnt()); /* use native pipes? */
  828. #endif
  829. #if SYS_WINNT && defined(DISP_NTWIN)
  830.     /* Allocate console before spawning piped process? */
  831.     set_global_g_val(GMDFORCE_CONSOLE, is_win95());
  832. #endif
  833. #ifdef GMDHISTORY
  834.     set_global_g_val(GMDHISTORY,    TRUE);
  835. #endif
  836.     set_global_g_val(GMDMULTIBEEP,    TRUE); /* multiple beeps for multiple
  837.                         motion failures */
  838. #if OPT_WORKING
  839.     set_global_g_val(GMDWORKING,      TRUE);    /* we put up "working..." */
  840. #endif
  841.     /* which 8 bit chars are printable? */
  842.     set_global_g_val(GVAL_PRINT_LOW, 0);
  843.     set_global_g_val(GVAL_PRINT_HIGH, 0);
  844.  
  845.  
  846.     /* catnap times: */
  847.     /* how long to wait for ESC seq */
  848.     set_global_g_val(GVAL_TIMEOUTVAL, 500);
  849.     /* how long to wait for user seq */
  850. #if SYS_MSDOS    /* actually, 16-bit ints */
  851.     set_global_g_val(GVAL_TIMEOUTUSERVAL, 30000);
  852. #else
  853.     set_global_g_val(GVAL_TIMEOUTUSERVAL, 60000);
  854. #endif
  855.  
  856. #if SYS_WINNT
  857.     set_global_g_val(GVAL_SCROLLPAUSE, 0);
  858. #endif
  859.  
  860.     /* allow remapping by default */
  861.     set_global_g_val(GMDREMAP, TRUE);
  862.  
  863.     set_global_g_val(GVAL_MAPLENGTH, 1200);
  864.  
  865.     /* set noresolve-links by default in case we've got NFS problems */
  866. #ifdef GMDRESOLVE_LINKS
  867.     set_global_g_val(GMDRESOLVE_LINKS, FALSE);
  868. #endif
  869.  
  870.     set_global_g_val_ptr(GVAL_EXPAND_CHARS, strmalloc(expand_chars));
  871.     set_global_g_val(GMDEXPAND_PATH,FALSE);
  872. #ifdef GMDGLOB
  873.     set_global_g_val(GMDGLOB, TRUE);
  874. #endif
  875. #ifdef GVAL_GLOB
  876.     set_global_g_val_ptr(GVAL_GLOB, strmalloc("!echo %s"));
  877. #endif
  878.  
  879.     set_global_g_val(GMDIMPLYBUFF,    FALSE); /* imply-buffer */
  880. #if    OPT_POPUPCHOICE
  881. # if    OPT_ENUM_MODES
  882.     set_global_g_val(GVAL_POPUP_CHOICES, POPUP_CHOICES_DELAYED);
  883. # else
  884.     set_global_g_val(GMDPOPUP_CHOICES,TRUE);
  885. # endif
  886. #endif
  887. #if    OPT_FILEBACK
  888. # if    OPT_MSDOS_PATH
  889.     set_global_g_val_ptr(GVAL_BACKUPSTYLE, strmalloc(".bak"));
  890. # else
  891.     set_global_g_val_ptr(GVAL_BACKUPSTYLE, strmalloc("off"));
  892. # endif
  893. #endif
  894. #if    OPT_POPUP_MSGS
  895.     set_global_g_val(GMDPOPUP_MSGS,-TRUE);    /* popup-msgs */
  896. #endif
  897. #ifdef GMDRAMSIZE
  898.     set_global_g_val(GMDRAMSIZE,    TRUE);    /* show ram-usage */
  899. #endif
  900.     set_global_g_val(GVAL_REPORT,    5);    /* report changes */
  901. #if    OPT_XTERM
  902.     set_global_g_val(GMDXTERM_MOUSE,FALSE);    /* mouse-clicking */
  903. #endif
  904.     set_global_g_val(GMDWARNUNREAD,TRUE);    /* warn if quitting without
  905.                         looking at all buffers */
  906.     set_global_g_val(GMDWARNREREAD,TRUE);    /* warn before rereading
  907.                         a buffer */
  908.     set_global_g_val(GMDWARNRENAME,TRUE);    /* warn before renaming
  909.                         a buffer */
  910.     set_global_g_val(GMDSMOOTH_SCROLL, FALSE);
  911.     set_global_g_val(GMDSPACESENT,  TRUE); /* add two spaces after each
  912.                         sentence */
  913. #if OPT_COLOR
  914.     set_global_g_val(GVAL_FCOLOR,    C_WHITE); /* foreground color */
  915.     set_global_g_val(GVAL_BCOLOR,    C_BLACK); /* background color */
  916. #endif
  917.  
  918.     /*
  919.      * Buffer-mode defaults
  920.      */
  921.     set_global_b_val(MDAIND,    FALSE); /* auto-indent */
  922.     set_global_b_val(MDASAVE,    FALSE);    /* auto-save */
  923.     set_global_b_val(MDBACKLIMIT,    TRUE);     /* limit backspacing to
  924.                             insert point */
  925. #ifdef    MDCHK_MODTIME
  926.     set_global_b_val(MDCHK_MODTIME,    FALSE); /* modtime-check */
  927. #endif
  928. #if    !OPT_MAJORMODE
  929.     set_global_b_val(MDCMOD,    FALSE); /* C mode */
  930. #endif
  931. #ifdef MDCRYPT
  932.     set_global_b_val(MDCRYPT,    FALSE);    /* crypt */
  933. #endif
  934.     set_global_b_val(MDIGNCASE,    FALSE); /* exact matches */
  935.     set_global_b_val(MDDOS, CRLF_LINES); /* on by default on DOS, off others */
  936.     set_global_b_val(MDMAGIC,    TRUE);     /* magic searches */
  937.     set_global_b_val( MDMETAINSBIND, TRUE); /* honor meta-bindings when
  938.                             in insert mode */
  939.     set_global_b_val(MDNEWLINE,    TRUE);     /* trailing-newline */
  940.     set_global_b_val(MDREADONLY,    FALSE); /* readonly */
  941.     set_global_b_val(MDSHOWMAT,    FALSE);    /* show-match */
  942.     set_global_b_val(MDSHOWMODE,    TRUE);    /* show-mode */
  943.     set_global_b_val(MDSWRAP,    TRUE);     /* scan wrap */
  944.     set_global_b_val(MDTABINSERT,    TRUE);    /* allow tab insertion */
  945.     set_global_b_val(MDTAGSRELTIV,    FALSE);    /* path relative tag lookups */
  946.     set_global_b_val(MDTERSE,    FALSE);    /* terse messaging */
  947. #if    OPT_HILITEMATCH
  948.     set_global_b_val(VAL_HILITEMATCH, 0);    /* no hilite */
  949. #endif
  950.     set_global_g_val(GVAL_MINI_HILITE, VAREV); /* reverse hilite */
  951. #if    OPT_UPBUFF
  952.     set_global_b_val(MDUPBUFF,    TRUE);    /* animated */
  953. #endif
  954.     set_global_b_val(MDVIEW,    FALSE); /* view-only */
  955.     set_global_b_val(MDWRAP,    FALSE); /* wrap */
  956. #if OPT_LCKFILES
  957.     /* locking defaults */
  958.     set_global_g_val(GMDUSEFILELOCK,FALSE);    /* Use filelocks */
  959.     set_global_b_val(MDLOCKED,    FALSE);    /* LOCKED */
  960.     set_global_b_val_ptr(VAL_LOCKER, strmalloc("")); /* Name locker */
  961. #endif
  962.     set_global_g_val(GMDRONLYVIEW,    FALSE);    /* Set view-on-readonly */
  963.     set_global_g_val(GMDRONLYRONLY,    FALSE);    /* Set readonly-on-readonly */
  964.  
  965.     set_global_b_val(VAL_ASAVECNT,    256);    /* autosave count */
  966. #if OPT_MAJORMODE
  967.     set_submode_val("c", VAL_SWIDTH, 8);     /* C file shiftwidth */
  968.     set_submode_val("c", VAL_TAB,    8);     /* C file tab stop */
  969. #else
  970.     set_global_b_val(VAL_C_SWIDTH,    8);     /* C file shiftwidth */
  971.     set_global_b_val(VAL_C_TAB,    8);     /* C file tab stop */
  972. #endif
  973.     set_global_b_val(VAL_SWIDTH,    8);     /* shiftwidth */
  974.     set_global_b_val(VAL_TAB,    8);    /* tab stop */
  975.     set_global_b_val(VAL_TAGLEN,    0);    /* significant tag length */
  976.     set_global_b_val(VAL_UNDOLIM,    10);    /* undo limit */
  977.  
  978.     set_global_b_val_ptr(VAL_TAGS, strmalloc("tags")); /* tags filename */
  979.     set_global_b_val_ptr(VAL_FENCES, strmalloc("{}()[]")); /* fences */
  980.  
  981. #if SYS_VMS
  982. #define    DEFAULT_CSUFFIX    "\\.\\(\\([CHIS]\\)\\|CC\\|CXX\\|HXX\\)\\(;[0-9]*\\)\\?$"
  983. #endif
  984. #if SYS_MSDOS || SYS_WIN31
  985. #define    DEFAULT_CSUFFIX    "\\.\\(\\([chis]\\)\\|cc\\|cpp\\|cxx\\|hxx\\)$"
  986. #endif
  987. #ifndef DEFAULT_CSUFFIX    /* UNIX or OS2/HPFS (mixed-case names) */
  988. #define    DEFAULT_CSUFFIX    "\\.\\(\\([Cchis]\\)\\|CC\\|cc\\|cpp\\|cxx\\|hxx\\|scm\\)$"
  989. #endif
  990.  
  991. #if OPT_MAJORMODE
  992.     set_majormode_rexp("c", MVAL_SUFFIXES, DEFAULT_CSUFFIX);
  993. #else
  994.     /* suffixes for C mode */
  995.     set_global_g_val_rexp(GVAL_CSUFFIXES,
  996.         new_regexval(
  997.             DEFAULT_CSUFFIX,
  998.             TRUE));
  999. #endif
  1000.  
  1001. #define B_REGEXP(mode,value) \
  1002.         set_global_b_val_rexp(mode, new_regexval(value, TRUE));
  1003.  
  1004.     B_REGEXP( VAL_FENCE_BEGIN, "/\\*" );
  1005.     B_REGEXP( VAL_FENCE_END,   "\\*/" );
  1006.  
  1007.     B_REGEXP( VAL_FENCE_IF,    "^\\s*#\\s*if" );
  1008.     B_REGEXP( VAL_FENCE_ELIF,  "^\\s*#\\s*elif\\>" );
  1009.     B_REGEXP( VAL_FENCE_ELSE,  "^\\s*#\\s*else\\>" );
  1010.     B_REGEXP( VAL_FENCE_FI,    "^\\s*#\\s*endif\\>" );
  1011.  
  1012.         /* where do paragraphs start? */
  1013.     B_REGEXP( VAL_PARAGRAPHS, "^\\.[ILPQ]P\\>\\|^\\.P\\>\\|\
  1014. ^\\.LI\\>\\|^\\.[plinb]p\\>\\|^\\.\\?\\s*$" );
  1015.  
  1016.         /* where do comments start and end, for formatting them */
  1017.     B_REGEXP( VAL_COMMENTS, "^\\s*/\\?\\(\\s*[#*>/]\\)\\+/\\?\\s*$" );
  1018.  
  1019.     B_REGEXP( VAL_CMT_PREFIX, "^\\s*\\(\\(\\s*[#*>]\\)\\|\\(///*\\)\\)\\+" );
  1020.  
  1021.         /* where do sections start? */
  1022.     B_REGEXP( VAL_SECTIONS, "^[{\014]\\|^\\.[NS]H\\>\\|^\\.HU\\?\\>\\|\
  1023. ^\\.[us]h\\>\\|^+c\\>" );    /* }vi */
  1024.  
  1025.         /* where do sentences start? */
  1026.     B_REGEXP( VAL_SENTENCES, "[.!?][])\"']* \\?$\\|[.!?][])\"']*  \\|\
  1027. ^\\.[ILPQ]P\\>\\|^\\.P\\>\\|^\\.LI\\>\\|^\\.[plinb]p\\>\\|^\\.\\?\\s*$" );
  1028.  
  1029.     /*
  1030.      * Window-mode defaults
  1031.      */
  1032. #ifdef WMDLINEWRAP
  1033.     set_global_w_val(WMDLINEWRAP,    FALSE); /* line-wrap */
  1034. #endif
  1035.     set_global_w_val(WMDLIST,    FALSE); /* list-mode */
  1036.     set_global_w_val(WMDNUMBER,    FALSE);    /* number */
  1037.     set_global_w_val(WMDHORSCROLL,    TRUE);    /* horizontal scrolling */
  1038. #ifdef WMDTERSELECT
  1039.     set_global_w_val(WMDTERSELECT,    TRUE);    /* terse selections */
  1040. #endif
  1041.  
  1042.     set_global_w_val(WVAL_SIDEWAYS,    0);    /* list-mode */
  1043.  
  1044.     if ((s = getenv("VILE_HELP_FILE")) == 0)
  1045.         s = "vile.hlp";
  1046.     helpfile = strmalloc(s);
  1047.  
  1048.     if ((s = getenv("VILE_STARTUP_FILE")) == 0) {
  1049. #if    SYS_MSDOS || SYS_WIN31 || SYS_OS2 || SYS_WINNT || SYS_VMS
  1050.         s = "vile.rc";
  1051. #else    /* SYS_UNIX */
  1052.         s = ".vilerc";
  1053. #endif
  1054.     }
  1055.     startup_file = strmalloc(s);
  1056.  
  1057.     if ((s = getenv("VILE_STARTUP_PATH")) == 0) {
  1058. #if    SYS_MSDOS || SYS_WIN31 || SYS_OS2 || SYS_WINNT
  1059.         s = "\\sys\\public\\;\\usr\\bin\\;\\bin\\;\\";
  1060. #else
  1061. #if    SYS_VMS
  1062.         s = "sys$login;sys$sysdevice:[vmstools];sys$library";
  1063. #else    /* SYS_UNIX */
  1064. #if    defined(VILE_STARTUP_PATH)
  1065.         s = VILE_STARTUP_PATH;
  1066. #else
  1067.         s = "/usr/local/lib/:/usr/local/:/usr/lib/";
  1068. #endif
  1069. #endif
  1070. #endif
  1071.     }
  1072.     startup_path = strmalloc(s);
  1073.  
  1074. #ifdef    HELP_LOC
  1075.     /*
  1076.      * *NIX install will define this
  1077.      */
  1078.     {
  1079.         char temp[NFILEN];
  1080.         int found = FALSE;
  1081.         const char *t = startup_path;
  1082.  
  1083.         while ((t = parse_pathlist(t, temp)) != 0) {
  1084.             if (!strcmp(temp, HELP_LOC)) {
  1085.                 found = TRUE;
  1086.                 break;
  1087.             }
  1088.         }
  1089.         if (!found) {
  1090.             s = typeallocn(char, strlen(HELP_LOC) + 2 + strlen(startup_path));
  1091.             lsprintf(s, "%s%c%s", HELP_LOC, PATHCHR, startup_path);
  1092.             if (startup_path != NULL)    /* memory leak! */
  1093.                 free(startup_path);
  1094.             startup_path = s;
  1095.         }
  1096.     }
  1097. #endif
  1098. }
  1099.  
  1100. #if SYS_UNIX || SYS_MSDOS || SYS_WIN31 || SYS_OS2 || SYS_WINNT || SYS_VMS
  1101.  
  1102. /* ARGSUSED */
  1103. SIGT
  1104. catchintr (int ACTUAL_SIG_ARGS)
  1105. {
  1106.     am_interrupted = TRUE;
  1107. #if SYS_MSDOS || SYS_OS2 || SYS_WINNT
  1108.     sgarbf = TRUE;    /* there's probably a ^C on the screen. */
  1109. #endif
  1110.     setup_handler(SIGINT,catchintr);
  1111.     if (im_waiting(-1))
  1112.         longjmp(read_jmp_buf, signo);
  1113.     SIGRET;
  1114. }
  1115. #endif
  1116.  
  1117. #ifndef interrupted  /* i.e. unless it's a macro */
  1118. int
  1119. interrupted(void)
  1120. {
  1121. #if SYS_MSDOS && CC_DJGPP
  1122.  
  1123.     if (_go32_was_ctrl_break_hit() != 0) {
  1124.         while(keystroke_avail())
  1125.             (void)keystroke();
  1126.         return TRUE;
  1127.     }
  1128.     if (was_ctrl_c_hit() != 0) {
  1129.         while(keystroke_avail())
  1130.             (void)keystroke();
  1131.         return TRUE;
  1132.     }
  1133.  
  1134.     if (am_interrupted)
  1135.         return TRUE;
  1136.     return FALSE;
  1137. #endif
  1138. }
  1139. #endif
  1140.  
  1141. void
  1142. not_interrupted(void)
  1143. {
  1144.     am_interrupted = FALSE;
  1145. #if SYS_MSDOS
  1146. # if CC_DJGPP
  1147.     (void)_go32_was_ctrl_break_hit();  /* flush any pending kbd ctrl-breaks */
  1148.     (void)was_ctrl_c_hit();  /* flush any pending kbd ctrl-breaks */
  1149. # endif
  1150. #endif
  1151. }
  1152.  
  1153. #if SYS_MSDOS
  1154. # if CC_WATCOM
  1155.     int  dos_crit_handler(unsigned deverror, unsigned errcode, unsigned *devhdr)
  1156. # else
  1157.     void dos_crit_handler(void)
  1158. # endif
  1159. {
  1160. # if CC_WATCOM
  1161.     _hardresume((int)_HARDERR_FAIL);
  1162.     return (int)_HARDERR_FAIL;
  1163. # else
  1164. #  if ! CC_DJGPP
  1165.     _hardresume(_HARDERR_FAIL);
  1166. #  endif
  1167. # endif
  1168. }
  1169. #endif
  1170.  
  1171.  
  1172. static void
  1173. siginit(void)
  1174. {
  1175. #if SYS_UNIX
  1176.     setup_handler(SIGINT,catchintr);
  1177.     setup_handler(SIGHUP,imdying);
  1178. #ifdef SIGBUS
  1179.     setup_handler(SIGBUS,imdying);
  1180. #endif
  1181. #ifdef SIGSYS
  1182.     setup_handler(SIGSYS,imdying);
  1183. #endif
  1184.     setup_handler(SIGSEGV,imdying);
  1185.     setup_handler(SIGTERM,imdying);
  1186. /* #define DEBUG 1 */
  1187. #if DEBUG
  1188.     setup_handler(SIGQUIT,imdying);
  1189. #else
  1190.     setup_handler(SIGQUIT,SIG_IGN);
  1191. #endif
  1192.     setup_handler(SIGPIPE,SIG_IGN);
  1193. #if defined(SIGWINCH) && ! DISP_X11
  1194.     setup_handler(SIGWINCH,sizesignal);
  1195. #endif
  1196. #else
  1197. # if SYS_MSDOS
  1198.     setup_handler(SIGINT,catchintr);
  1199. #  if CC_DJGPP
  1200.     _go32_want_ctrl_break(TRUE);
  1201.     setcbrk(FALSE);
  1202.     want_ctrl_c(TRUE);
  1203.     hard_error_catch_setup();
  1204. #  else
  1205. #   if CC_WATCOM
  1206.     {
  1207.     /* clean up Warning from Watcom C */
  1208.     void *ptrfunc = dos_crit_handler;
  1209.     _harderr(ptrfunc);
  1210.     }
  1211. #   else    /* CC_TURBO */
  1212.     _harderr(dos_crit_handler);
  1213. #   endif
  1214. #  endif
  1215. # endif
  1216. # if SYS_OS2 || SYS_WINNT
  1217.     setup_handler(SIGINT,catchintr);
  1218. #endif
  1219. #endif
  1220.  
  1221. }
  1222.  
  1223. static void
  1224. siguninit(void)
  1225. {
  1226. #if SYS_MSDOS
  1227. # if CC_DJGPP
  1228.     _go32_want_ctrl_break(FALSE);
  1229.     want_ctrl_c(FALSE);
  1230.     hard_error_teardown();
  1231.     setcbrk(TRUE);
  1232. # endif
  1233. #endif
  1234. }
  1235.  
  1236. /* do number processing if needed */
  1237. static void
  1238. do_num_proc(int *cp, int *fp, int *np)
  1239. {
  1240.     register int c, f, n;
  1241.     register int    mflag;
  1242.     register int oldn;
  1243.  
  1244.     c = *cp;
  1245.  
  1246.     if (isCntrl(c) || isspecial(c))
  1247.         return;
  1248.  
  1249.     f = *fp;
  1250.     n = *np;
  1251.     if (f)
  1252.         oldn = n;
  1253.     else
  1254.         oldn = 1;
  1255.     n = 1;
  1256.  
  1257.     if ( isDigit(c) && c != '0' ) {
  1258.         n = 0;        /* start with a zero default */
  1259.         f = TRUE;    /* there is a # arg */
  1260.         mflag = 1;        /* current minus flag */
  1261.         while ((isDigit(c) && !isspecial(c)) || (c == '-')) {
  1262.             if (c == '-') {
  1263.                 /* already hit a minus or digit? */
  1264.                 if ((mflag == -1) || (n != 0))
  1265.                     break;
  1266.                 mflag = -1;
  1267.             } else {
  1268.                 n = n * 10 + (c - '0');
  1269.             }
  1270.             if ((n == 0) && (mflag == -1))    /* lonely - */
  1271.                 mlwrite("arg:");
  1272.             else
  1273.                 mlwrite("arg: %d",n * mflag);
  1274.  
  1275.             c = kbd_seq();    /* get the next key */
  1276.         }
  1277.         n = n * mflag;    /* figure in the sign */
  1278.     }
  1279.     *cp = c;
  1280.     *fp = f;
  1281.     *np = n * oldn;
  1282. }
  1283.  
  1284. /* do ^U-style repeat argument processing -- vile binds this to 'K' */
  1285. static void
  1286. do_rept_arg_proc(int *cp, int *fp, int *np)
  1287. {
  1288.     register int c, f, n;
  1289.     register int    mflag;
  1290.     register int    oldn;
  1291.     c = *cp;
  1292.  
  1293.     if (c != reptc)
  1294.         return;
  1295.  
  1296.     f = *fp;
  1297.     n = *np;
  1298.  
  1299.     if (f)
  1300.         oldn = n;
  1301.     else
  1302.         oldn = 1;
  1303.  
  1304.     n = 4;        /* start with a 4 */
  1305.     f = TRUE;    /* there is a # arg */
  1306.     mflag = 0;            /* that can be discarded. */
  1307.     mlwrite("arg: %d",n);
  1308.     while ( (isDigit( c=kbd_seq() ) && !isspecial(c))
  1309.             || c==reptc || c=='-'){
  1310.         if (c == reptc) {
  1311.             /* wow.  what does this do?  -pgf */
  1312.             /* (i've been told it controls overflow...) */
  1313.             if ((n > 0) == ((n*4) > 0))
  1314.                 n = n*4;
  1315.             else
  1316.                 n = 1;
  1317.         }
  1318.         /*
  1319.          * If dash, and start of argument string, set arg.
  1320.          * to -1.  Otherwise, insert it.
  1321.          */
  1322.         else if (c == '-') {
  1323.             if (mflag)
  1324.                 break;
  1325.             n = 0;
  1326.             mflag = -1;
  1327.         }
  1328.         /*
  1329.          * If first digit entered, replace previous argument
  1330.          * with digit and set sign.  Otherwise, append to arg.
  1331.          */
  1332.         else {
  1333.             if (!mflag) {
  1334.                 n = 0;
  1335.                 mflag = 1;
  1336.             }
  1337.             n = 10*n + c - '0';
  1338.         }
  1339.         mlwrite("arg: %d", (mflag >=0) ? n : (n ? -n : -1));
  1340.     }
  1341.     /*
  1342.      * Make arguments preceded by a minus sign negative and change
  1343.      * the special argument "^U -" to an effective "^U -1".
  1344.      */
  1345.     if (mflag == -1) {
  1346.         if (n == 0)
  1347.             n++;
  1348.         n = -n;
  1349.     }
  1350.  
  1351.     *cp = c;
  1352.     *fp = f;
  1353.     *np = n * oldn;
  1354. }
  1355.  
  1356. /* handle all repeat counts */
  1357. void
  1358. do_repeats(int *cp, int *fp, int *np)
  1359. {
  1360.     do_num_proc(cp,fp,np);
  1361.     do_rept_arg_proc(cp,fp,np);
  1362.     if (dotcmdmode == PLAY) {
  1363.         if (dotcmdarg)    /* then repeats are done by dotcmdcnt */
  1364.             *np = 1;
  1365.     } else {
  1366.         /* then we want to cancel any dotcmdcnt repeats */
  1367.         if (*fp) dotcmdarg = FALSE;
  1368.     }
  1369. }
  1370.  
  1371. /* the vi ZZ command -- write all, then quit */
  1372. int
  1373. zzquit(int f, int n)
  1374. {
  1375.     int thiscmd;
  1376.     int cnt;
  1377.     BUFFER *bp;
  1378.  
  1379.     thiscmd = lastcmd;
  1380.     cnt = any_changed_buf(&bp);
  1381.     if (cnt) {
  1382.             if (cnt > 1) {
  1383.             mlprompt("Will write %d buffers.  %s ", cnt,
  1384.                 clexec ? s_NULL : "Repeat command to continue.");
  1385.         } else {
  1386.             mlprompt("Will write buffer \"%s\".  %s ",
  1387.                 bp->b_bname,
  1388.                 clexec ? s_NULL : "Repeat command to continue.");
  1389.         }
  1390.         if (!clexec && !isnamedcmd) {
  1391.             if (thiscmd != kbd_seq())
  1392.                 return FALSE;
  1393.         }
  1394.  
  1395.         if (writeall(f,n,FALSE,TRUE,FALSE) != TRUE) {
  1396.             return FALSE;
  1397.         }
  1398.  
  1399.     } else if (!clexec && !isnamedcmd) {
  1400.         /* consume the next char. anyway */
  1401.         if (thiscmd != kbd_seq())
  1402.             return FALSE;
  1403.     }
  1404.     return quit(f, n);
  1405. }
  1406.  
  1407. /*
  1408.  * Fancy quit command, as implemented by Norm. If the any buffer has
  1409.  * changed do a write on that buffer and exit, otherwise simply exit.
  1410.  */
  1411. int
  1412. quickexit(int f, int n)
  1413. {
  1414.     register int status;
  1415.     if ((status = writeall(f,n,FALSE,TRUE,FALSE)) == TRUE)
  1416.         status = quithard(f, n);  /* conditionally quit    */
  1417.     return status;
  1418. }
  1419.  
  1420. /* Force quit by giving argument */
  1421. /* ARGSUSED */
  1422. int
  1423. quithard(int f GCC_UNUSED, int n GCC_UNUSED)
  1424. {
  1425.     return quit(TRUE,1);
  1426. }
  1427.  
  1428. /*
  1429.  * Quit command. If an argument, always quit. Otherwise confirm if a buffer
  1430.  * has been changed and not written out.
  1431.  */
  1432. /* ARGSUSED */
  1433. int
  1434. quit(int f, int n GCC_UNUSED)
  1435. {
  1436.     int cnt;
  1437.     BUFFER *bp;
  1438.     const char *sadj, *sverb;
  1439.  
  1440. #if OPT_PROCEDURES
  1441.     {
  1442.         static int exithooking;
  1443.         if (!exithooking && *exithook) {
  1444.             exithooking = TRUE;
  1445.             run_procedure(exithook);
  1446.             exithooking = FALSE;
  1447.         }
  1448.     }
  1449. #endif
  1450.  
  1451.     if (f == FALSE) {
  1452.         cnt = any_changed_buf(&bp);
  1453.         sadj = "modified";
  1454.         sverb = "Write";
  1455.         if (cnt == 0 && global_g_val(GMDWARNUNREAD)) {
  1456.             cnt = any_unread_buf(&bp);
  1457.             sadj = "unread";
  1458.             sverb = "Look at";
  1459.         }
  1460.         if (cnt != 0) {
  1461.             if (cnt == 1)
  1462.                 mlforce(
  1463.                 "Buffer \"%s\" is %s.  %s it, or use :q!",
  1464.                     bp->b_bname,sadj,sverb);
  1465.             else
  1466.                 mlforce(
  1467.               "There are %d %s buffers.  %s them, or use :q!",
  1468.                     cnt,sadj,sverb);
  1469.             return FALSE;
  1470.         }
  1471.     }
  1472. #if OPT_LCKFILES
  1473.     /* Release all placed locks */
  1474.     if ( global_g_val(GMDUSEFILELOCK) ) {
  1475.         for_each_buffer(bp) {
  1476.             if ( bp->b_active ) {
  1477.                 if (!b_val(curbp,MDLOCKED) &&
  1478.                         !b_val(curbp,MDVIEW))
  1479.                     release_lock(bp->b_fname);
  1480.             }
  1481.         }
  1482.     }
  1483. #endif
  1484.     siguninit();
  1485. #if OPT_WORKING
  1486.     setup_handler(SIGALRM, SIG_IGN);
  1487. #endif
  1488. #if NO_LEAKS
  1489.     {
  1490.         beginDisplay();        /* ...this may take a while... */
  1491.  
  1492.         /* free all of the global data structures */
  1493.         onel_leaks();
  1494.         path_leaks();
  1495.         kbs_leaks();
  1496.         bind_leaks();
  1497.         map_leaks();
  1498.         tags_leaks();
  1499.         itb_leaks();
  1500.         tb_leaks();
  1501.         wp_leaks();
  1502.         bp_leaks();
  1503.         vt_leaks();
  1504.         ev_leaks();
  1505.         mode_leaks();
  1506. #if DISP_X11
  1507.         x11_leaks();
  1508. #endif
  1509.  
  1510.         free_local_vals(g_valnames, global_g_values.gv, global_g_values.gv);
  1511.         free_local_vals(b_valnames, global_b_values.bv, global_b_values.bv);
  1512.         free_local_vals(w_valnames, global_w_values.wv, global_w_values.wv);
  1513.  
  1514.         FreeAndNull(gregexp);
  1515.         FreeAndNull(patmatch);
  1516. #if    OPT_MLFORMAT
  1517.             FreeAndNull(modeline_format);
  1518. #endif
  1519.  
  1520. #if SYS_UNIX
  1521.         if (strcmp(exec_pathname, "."))
  1522.             FreeAndNull(exec_pathname);
  1523. #endif
  1524.         /* whatever is left over must be a leak */
  1525.         show_alloc();
  1526.     }
  1527. #endif
  1528.     tidy_exit(GOODEXIT);
  1529.     /* NOTREACHED */
  1530.     return FALSE;
  1531. }
  1532.  
  1533. /* ARGSUSED */
  1534. int
  1535. writequit(int f GCC_UNUSED, int n)
  1536. {
  1537.     int s;
  1538.     s = filesave(FALSE,n);
  1539.     if (s != TRUE)
  1540.         return s;
  1541.     return quit(FALSE,n);
  1542. }
  1543.  
  1544. /*
  1545.  * Abort.
  1546.  * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
  1547.  * Sometimes called as a routine, to do general aborting of stuff.
  1548.  */
  1549. /* ARGSUSED */
  1550. int
  1551. esc_func(int f GCC_UNUSED, int n GCC_UNUSED)
  1552. {
  1553.     dotcmdmode = STOP;
  1554.     regionshape = EXACT;
  1555.     doingopcmd = FALSE;
  1556.     doingsweep = FALSE;
  1557.     sweephack = FALSE;
  1558.     opcmd = 0;
  1559.     mlwarn("[Aborted]");
  1560.     return ABORT;
  1561. }
  1562.  
  1563. /* tell the user that this command is illegal while we are in
  1564.    VIEW (read-only) mode                */
  1565.  
  1566. int
  1567. rdonly(void)
  1568. {
  1569.     mlwarn("[No changes are allowed while in \"view\" mode]");
  1570.     return FALSE;
  1571. }
  1572.  
  1573. /* ARGSUSED */
  1574. int
  1575. unimpl(int f GCC_UNUSED, int n GCC_UNUSED)
  1576. {
  1577.     mlwarn("[Sorry, that vi command is unimplemented in vile ]");
  1578.     return FALSE;
  1579. }
  1580.  
  1581. int
  1582. opercopy(int f, int n)
  1583. {
  1584.     return unimpl(f,n);
  1585. }
  1586.  
  1587. int
  1588. opermove(int f, int n)
  1589. {
  1590.     return unimpl(f,n);
  1591. }
  1592.  
  1593. int
  1594. opertransf(int f, int n)
  1595. {
  1596.     return unimpl(f,n);
  1597. }
  1598.  
  1599. int
  1600. operglobals(int f, int n)
  1601. {
  1602.     return unimpl(f,n);
  1603. }
  1604.  
  1605. int
  1606. opervglobals(int f, int n)
  1607. {
  1608.     return unimpl(f,n);
  1609. }
  1610.  
  1611. int
  1612. source(int f, int n)
  1613. {
  1614.     return unimpl(f,n);
  1615. }
  1616.  
  1617. int
  1618. visual(int f, int n)
  1619. {
  1620.     return unimpl(f,n);
  1621. }
  1622.  
  1623. int
  1624. ex(int f, int n)
  1625. {
  1626.     return unimpl(f,n);
  1627. }
  1628.  
  1629. /* ARGSUSED */
  1630. int
  1631. nullproc(int f GCC_UNUSED, int n GCC_UNUSED)    /* user function that does (almost) NOTHING */
  1632. {
  1633.     return TRUE;
  1634. }
  1635.  
  1636. /* ARGSUSED */
  1637. int
  1638. cntl_a_func(int f GCC_UNUSED, int n GCC_UNUSED)    /* dummy function for binding to control-a prefix */
  1639. {
  1640.     return TRUE;
  1641. }
  1642.  
  1643. /* ARGSUSED */
  1644. int
  1645. cntl_x_func(int f GCC_UNUSED, int n GCC_UNUSED)    /* dummy function for binding to control-x prefix */
  1646. {
  1647.     return TRUE;
  1648. }
  1649.  
  1650. /* ARGSUSED */
  1651. int
  1652. poundc_func(int f GCC_UNUSED, int n GCC_UNUSED)    /* dummy function for binding to poundsign prefix */
  1653. {
  1654.     return TRUE;
  1655. }
  1656.  
  1657. /* ARGSUSED */
  1658. int
  1659. unarg_func(int f GCC_UNUSED, int n GCC_UNUSED) /* dummy function for binding to universal-argument */
  1660. {
  1661.     return TRUE;
  1662. }
  1663.  
  1664. /*----------------------------------------------------------------------------*/
  1665.  
  1666. #if OPT_SHOW_CTYPE
  1667.  
  1668. /* list the current chrs into the current buffer */
  1669. /* ARGSUSED */
  1670. static void
  1671. makectypelist(int dum1 GCC_UNUSED, void *ptr GCC_UNUSED)
  1672. {
  1673.     static const struct {
  1674.         ULONG    mask;
  1675.         const char *name;
  1676.     } table[] = {
  1677.         { vl_upper,    "Upr" },
  1678.         { vl_lower,    "Lwr" },
  1679.         { vl_digit,    "Num" },
  1680.         { vl_space,    "Spc" },
  1681.         { vl_bspace,    "DEL" },
  1682.         { vl_cntrl,    "CTL" },
  1683.         { vl_print,    "Prn" },
  1684.         { vl_punct,    "Pun" },
  1685.         { vl_ident,    "id" },
  1686.         { vl_pathn,    "path" },
  1687.         { vl_wild,    "*" },
  1688.         { vl_linespec,    "arg" },
  1689.         { vl_fence,    "()" },
  1690.         { vl_nonspace,    "!S" },
  1691.         { vl_qident,    "qid" },
  1692. #if OPT_WIDE_CTYPES
  1693.         { vl_scrtch,    "tmp" },
  1694.         { vl_shpipe,    "sh" },
  1695. #endif
  1696.         { 0,        0 }
  1697.     };
  1698.     register UINT i, j;
  1699.  
  1700.     bprintf("--- Printable Characters %*P\n", term.t_ncol-1, '-');
  1701.     for (i = 0; i < N_chars; i++) {
  1702.         bprintf("\n%d\t", i);
  1703.         if ((i == '\n') || (i == '\t')) /* vtlistc() may not do these */
  1704.             bprintf("^%c", '@' | i);
  1705. #if OPT_LOCALE
  1706.         else if (!isprint(i) && i > 127 && i < 160) /* C1 controls? */
  1707.             bprintf(
  1708.                 global_w_val(WMDNONPRINTOCTAL)
  1709.                 ? "\\%3o"
  1710.                 : "\\x%2x",
  1711.                 i);
  1712. #endif
  1713.         else
  1714.             bprintf("%c", i);
  1715.         bputc('\t');
  1716.         for (j = 0; table[j].name != 0; j++) {
  1717.             if (j != 0)
  1718.                 bputc(' ');
  1719.             bprintf("%*s",
  1720.                 strlen(table[j].name),
  1721.                 (vl_chartypes_[i] & table[j].mask)
  1722.                     ? table[j].name
  1723.                     : "-");
  1724.         }
  1725.     }
  1726. }
  1727.  
  1728. int
  1729. desprint(int f GCC_UNUSED, int n GCC_UNUSED)
  1730. {
  1731.     return liststuff(PRINTABLECHARS_BufName, FALSE, makectypelist, 0, (void *)0);
  1732. }
  1733.  
  1734. #endif /* OPT_SHOW_CTYPE */
  1735.  
  1736. /*----------------------------------------------------------------------------*/
  1737.  
  1738. /* initialize our version of the "chartypes" stuff normally in ctypes.h */
  1739. /* also called later, if charset-affecting modes change, for instance */
  1740. void
  1741. charinit(void)
  1742. {
  1743.     register int c;
  1744.  
  1745.     TRACE(("charinit lo=%d, hi=%d\n",
  1746.         global_g_val(GVAL_PRINT_LOW),
  1747.         global_g_val(GVAL_PRINT_HIGH)))
  1748.  
  1749.     /* If we're using the locale functions, set our flags based on its
  1750.      * tables.  Note that just because you have 'setlocale()' doesn't mean
  1751.      * that the tables are present or correct.  But this is a start.
  1752.      */
  1753. #if OPT_LOCALE
  1754.     for (c = 0; c < N_chars; c++) {
  1755.         vl_chartypes_[c] = 0;
  1756.         if (iscntrl(c))  vl_chartypes_[c] |= vl_cntrl;
  1757.         if (isdigit(c))  vl_chartypes_[c] |= vl_digit;
  1758.         if (islower(c))  vl_chartypes_[c] |= vl_lower;
  1759.         if (isprint(c))  vl_chartypes_[c] |= vl_print;
  1760.         if (ispunct(c))  vl_chartypes_[c] |= vl_punct;
  1761.         if (isspace(c))  vl_chartypes_[c] |= vl_space;
  1762.         if (isupper(c))  vl_chartypes_[c] |= vl_upper;
  1763.     }
  1764. #else /* ! OPT_LOCALE */
  1765.     (void)memset((char *)vl_chartypes_, 0, sizeof(vl_chartypes_));
  1766.  
  1767.     /* control characters */
  1768.     for (c = 0; c < ' '; c++)
  1769.         vl_chartypes_[c] |= vl_cntrl;
  1770.     vl_chartypes_[127] |= vl_cntrl;
  1771.  
  1772.     /* lowercase */
  1773.     for (c = 'a'; c <= 'z'; c++)
  1774.         vl_chartypes_[c] |= vl_lower;
  1775. #if OPT_ISO_8859
  1776.     for (c = 0xc0; c <= 0xd6; c++)
  1777.         vl_chartypes_[c] |= vl_lower;
  1778.     for (c = 0xd8; c <= 0xde; c++)
  1779.         vl_chartypes_[c] |= vl_lower;
  1780. #endif
  1781.     /* uppercase */
  1782.     for (c = 'A'; c <= 'Z'; c++)
  1783.         vl_chartypes_[c] |= vl_upper;
  1784. #if OPT_ISO_8859
  1785.     for (c = 0xdf; c <= 0xf6; c++)
  1786.         vl_chartypes_[c] |= vl_upper;
  1787.     for (c = 0xf8; c <= 0xff; c++)
  1788.         vl_chartypes_[c] |= vl_upper;
  1789. #endif
  1790.  
  1791.     /* digits */
  1792.     for (c = '0'; c <= '9'; c++)
  1793.         vl_chartypes_[c] |= vl_digit;
  1794.  
  1795.     /* punctuation */
  1796.     for (c = '!'; c <= '/'; c++)
  1797.         vl_chartypes_[c] |= vl_punct;
  1798.     for (c = ':'; c <= '@'; c++)
  1799.         vl_chartypes_[c] |= vl_punct;
  1800.     for (c = '['; c <= '`'; c++)
  1801.         vl_chartypes_[c] |= vl_punct;
  1802.     for (c = LBRACE; c <= '~'; c++)
  1803.         vl_chartypes_[c] |= vl_punct;
  1804. #if OPT_ISO_8859
  1805.     for (c = 0xa1; c <= 0xbf; c++)
  1806.         vl_chartypes_[c] |= vl_punct;
  1807. #endif
  1808.  
  1809.     /* printable */
  1810.     for (c = ' '; c <= '~'; c++)
  1811.         vl_chartypes_[c] |= vl_print;
  1812.  
  1813.     /* whitespace */
  1814.     vl_chartypes_[' ']  |= vl_space;
  1815. #if OPT_ISO_8859
  1816.     vl_chartypes_[0xa0] |= vl_space;
  1817. #endif
  1818.     vl_chartypes_['\t'] |= vl_space;
  1819.     vl_chartypes_['\r'] |= vl_space;
  1820.     vl_chartypes_['\n'] |= vl_space;
  1821.     vl_chartypes_['\f'] |= vl_space;
  1822.  
  1823. #endif /* OPT_LOCALE */
  1824.  
  1825.     /* legal in pathnames */
  1826.     vl_chartypes_['.'] |= vl_pathn;
  1827.     vl_chartypes_['_'] |= vl_pathn;
  1828.     vl_chartypes_['~'] |= vl_pathn;
  1829.     vl_chartypes_['-'] |= vl_pathn;
  1830.     vl_chartypes_['*'] |= vl_pathn;
  1831.     vl_chartypes_['/'] |= vl_pathn;
  1832.  
  1833.     /* legal in "identifiers" */
  1834.     vl_chartypes_['_'] |= vl_ident|vl_qident;
  1835.     vl_chartypes_[':'] |= vl_qident;
  1836. #if SYS_VMS
  1837.     vl_chartypes_['$'] |= vl_ident|vl_qident;
  1838. #endif
  1839.  
  1840.     c = global_g_val(GVAL_PRINT_LOW);
  1841.     if (c < HIGHBIT) c = HIGHBIT;
  1842.     while ( c <= global_g_val(GVAL_PRINT_HIGH) && c < N_chars)
  1843.         vl_chartypes_[c++] |= vl_print;
  1844.  
  1845. #if DISP_X11
  1846.     for (c = 0; c < N_chars; c++) {
  1847.         if (isPrint(c) && !gui_isprint(c)) {
  1848.             vl_chartypes_[c] &= ~vl_print;
  1849.         }
  1850.     }
  1851. #endif
  1852.     /* backspacers: ^H, rubout */
  1853.     vl_chartypes_['\b'] |= vl_bspace;
  1854.     vl_chartypes_[127] |= vl_bspace;
  1855.  
  1856.     /* wildcard chars for most shells */
  1857.     vl_chartypes_['*'] |= vl_wild;
  1858.     vl_chartypes_['?'] |= vl_wild;
  1859. #if !OPT_VMS_PATH
  1860. #if SYS_UNIX
  1861.     vl_chartypes_['~'] |= vl_wild;
  1862. #endif
  1863.     vl_chartypes_[LBRACK] |= vl_wild;
  1864.     vl_chartypes_[RBRACK] |= vl_wild;
  1865.     vl_chartypes_[LBRACE] |= vl_wild;
  1866.     vl_chartypes_[RBRACE] |= vl_wild;
  1867.     vl_chartypes_['$'] |= vl_wild;
  1868.     vl_chartypes_['`'] |= vl_wild;
  1869. #endif
  1870.  
  1871.     /* ex mode line specifiers */
  1872.     vl_chartypes_[','] |= vl_linespec;
  1873.     vl_chartypes_['%'] |= vl_linespec;
  1874.     vl_chartypes_['-'] |= vl_linespec;
  1875.     vl_chartypes_['+'] |= vl_linespec;
  1876.     vl_chartypes_[';'] |= vl_linespec;
  1877.     vl_chartypes_['.'] |= vl_linespec;
  1878.     vl_chartypes_['$'] |= vl_linespec;
  1879.     vl_chartypes_['\''] |= vl_linespec;
  1880.  
  1881.     /* fences */
  1882.     vl_chartypes_[LBRACE] |= vl_fence;
  1883.     vl_chartypes_[RBRACE] |= vl_fence;
  1884.     vl_chartypes_[LPAREN] |= vl_fence;
  1885.     vl_chartypes_[RPAREN] |= vl_fence;
  1886.     vl_chartypes_[LBRACK] |= vl_fence;
  1887.     vl_chartypes_[RBRACK] |= vl_fence;
  1888.  
  1889. #if OPT_VMS_PATH
  1890.     vl_chartypes_[LBRACK] |= vl_pathn;    /* actually, "<", ">" too */
  1891.     vl_chartypes_[RBRACK] |= vl_pathn;
  1892.     vl_chartypes_['$'] |= vl_pathn;
  1893.     vl_chartypes_[':'] |= vl_pathn;
  1894.     vl_chartypes_[';'] |= vl_pathn;
  1895. #endif
  1896.  
  1897. #if OPT_MSDOS_PATH
  1898.     vl_chartypes_['\\'] |= vl_pathn;
  1899.     vl_chartypes_[':'] |= vl_pathn;
  1900. #endif
  1901.  
  1902. #if OPT_WIDE_CTYPES
  1903.     /* scratch-buffer-names (usually superset of vl_pathn) */
  1904.     vl_chartypes_[(unsigned)SCRTCH_LEFT[0]]  |= vl_scrtch;
  1905.     vl_chartypes_[(unsigned)SCRTCH_RIGHT[0]] |= vl_scrtch;
  1906.     vl_chartypes_[' '] |= vl_scrtch;    /* ...to handle "[Buffer List]" */
  1907. #endif
  1908.  
  1909.     for (c = 0; c < N_chars; c++) {
  1910.         if (!(isSpace(c)))
  1911.             vl_chartypes_[c] |= vl_nonspace;
  1912.         if (isDigit(c))
  1913.             vl_chartypes_[c] |= vl_linespec;
  1914.         if (isAlpha(c) || isDigit(c))
  1915.             vl_chartypes_[c] |= vl_ident|vl_pathn|vl_qident;
  1916. #if OPT_WIDE_CTYPES
  1917.         if (isSpace(c) || isPrint(c))
  1918.             vl_chartypes_[c] |= vl_shpipe;
  1919.         if (ispath(c))
  1920.             vl_chartypes_[c] |= vl_scrtch;
  1921. #endif
  1922.     }
  1923.  
  1924. }
  1925.  
  1926. /*****        Compiler specific Library functions    ****/
  1927.  
  1928.  
  1929. #if    OPT_RAMSIZE
  1930. /*    These routines will allow me to track memory usage by placing
  1931.     a layer on top of the standard system malloc() and free() calls.
  1932.     with this code defined, the environment variable, $RAM, will
  1933.     report on the number of bytes allocated via malloc.
  1934.  
  1935.     with SHOWRAM defined, the number is also posted on the
  1936.     end of the bottom mode line and is updated whenever it is changed.
  1937. */
  1938.  
  1939. #undef    realloc
  1940. #undef    malloc
  1941. #undef    free
  1942.  
  1943. typedef    struct {
  1944.     size_t    length;
  1945.     unsigned magic;
  1946. } RAMSIZE;
  1947.  
  1948. #define MAGIC_RAM 0x12345678
  1949.  
  1950.     /* display the amount of RAM currently malloc'ed */
  1951. static void
  1952. display_ram_usage (void)
  1953. {
  1954.     beginDisplay();
  1955.     if (global_g_val(GMDRAMSIZE)) {
  1956.         char mbuf[20];
  1957.         int    saverow = ttrow;
  1958.         int    savecol = ttcol;
  1959.  
  1960.         if (saverow >= 0 && saverow < term.t_nrow
  1961.          && savecol >= 0 && savecol < term.t_ncol) {
  1962.             (void)lsprintf(mbuf, "[%ld]", envram);
  1963.             kbd_overlay(mbuf);
  1964.             kbd_flush();
  1965.             movecursor(saverow, savecol);
  1966.         }
  1967.     }
  1968.     endofDisplay();
  1969. }
  1970.  
  1971. static char *old_ramsize(char *mp)
  1972. {
  1973.     RAMSIZE *p = (RAMSIZE *)(mp - sizeof(RAMSIZE));
  1974.  
  1975.     if (p->magic == MAGIC_RAM) {
  1976.         mp = (char *)p;
  1977.         envram -= p->length;
  1978.     }
  1979.     return mp;
  1980. }
  1981.  
  1982. static char *new_ramsize(char *mp, unsigned nbytes)
  1983. {
  1984.     RAMSIZE *p = (RAMSIZE *)mp;
  1985.     if (p != 0) {
  1986.         p->length = nbytes;
  1987.         p->magic  = MAGIC_RAM;
  1988.         envram += nbytes;
  1989.         mp = (char *)((long)p + sizeof(RAMSIZE));
  1990.     }
  1991.     return mp;
  1992. }
  1993.  
  1994.     /* reallocate mp with nbytes and track */
  1995. char *reallocate(char *mp, unsigned nbytes)
  1996. {
  1997.     if (mp != 0) {
  1998.         nbytes += sizeof(RAMSIZE);
  1999.         mp = new_ramsize(realloc(old_ramsize(mp), nbytes), nbytes);
  2000.         display_ram_usage();
  2001.     } else
  2002.         mp = allocate(nbytes);
  2003.     return mp;
  2004. }
  2005.  
  2006.     /* allocate nbytes and track */
  2007. char *allocate(
  2008. unsigned nbytes)    /* # of bytes to allocate */
  2009. {
  2010.     char *mp;    /* ptr returned from malloc */
  2011.  
  2012.     nbytes += sizeof(RAMSIZE);
  2013.     if ((mp = malloc(nbytes)) != 0) {
  2014.         (void)memset(mp, 0, nbytes);    /* so we can use for calloc */
  2015.         mp = new_ramsize(mp, nbytes);
  2016.         display_ram_usage();
  2017.     }
  2018.  
  2019.     return mp;
  2020. }
  2021.  
  2022.     /* release malloced memory and track */
  2023. void
  2024. release(char *mp)    /* chunk of RAM to release */
  2025. {
  2026.     if (mp) {
  2027.         free(old_ramsize(mp));
  2028.         display_ram_usage();
  2029.     }
  2030. }
  2031. #endif    /* OPT_RAMSIZE */
  2032.  
  2033. #if MALLOCDEBUG
  2034. mallocdbg(int f, int n)
  2035. {
  2036.     int lvl;
  2037.     lvl = malloc_debug(n);
  2038.     mlwrite("malloc debug level was %d",lvl);
  2039.     if (!f) {
  2040.         malloc_debug(lvl);
  2041.     } else if (n > 2) {
  2042.         malloc_verify();
  2043.     }
  2044.     return TRUE;
  2045. }
  2046. #endif
  2047.  
  2048.  
  2049. /*
  2050.  *    the log file is left open, unbuffered.  thus any code can do
  2051.  *
  2052.  *     extern FILE *FF;
  2053.  *    fprintf(FF, "...", ...);
  2054.  *
  2055.  *    to log events without disturbing the screen
  2056.  */
  2057.  
  2058. #ifdef DEBUGLOG
  2059. /* suppress the declaration so that the link will fail if someone uses it */
  2060. FILE *FF;
  2061. #endif
  2062.  
  2063. /*ARGSUSED*/
  2064. static void
  2065. start_debug_log(int ac GCC_UNUSED, char **av GCC_UNUSED)
  2066. {
  2067. #ifdef DEBUGLOG
  2068.     int i;
  2069.     FF = fopen("vilelog", "w");
  2070.     setbuf(FF,NULL);
  2071.     for (i = 0; i < ac; i++)
  2072.         (void)fprintf(FF,"arg %d: %s\n",i,av[i]);
  2073. #endif
  2074. }
  2075.  
  2076. #if SYS_MSDOS
  2077.  
  2078. #if CC_TURBO
  2079. int
  2080. showmemory(int f, int n)
  2081. {
  2082.     extern    long    coreleft(void);
  2083.     mlforce("Memory left: %D bytes", coreleft());
  2084.     return TRUE;
  2085. }
  2086. #endif
  2087.  
  2088. #if CC_WATCOM
  2089. int
  2090. showmemory(int f, int n)
  2091. {
  2092.     mlforce("Watcom C doesn't provide a very useful 'memory-left' call.");
  2093.     return TRUE;
  2094. }
  2095. #endif
  2096.  
  2097. #if CC_DJGPP
  2098. int
  2099. showmemory(int f, int n)
  2100. {
  2101.     mlforce("Memory left: %D Kb virtual, %D Kb physical",
  2102.             _go32_dpmi_remaining_virtual_memory()/1024,
  2103.             _go32_dpmi_remaining_physical_memory()/1024);
  2104.     return TRUE;
  2105. }
  2106. #endif
  2107. #endif /* SYS_MSDOS */
  2108.  
  2109. char *
  2110. strncpy0(char *t, const char *f, SIZE_T l)
  2111. {
  2112.     (void)strncpy(t, f, l);
  2113.     if (l)
  2114.     t[l-1] = EOS;
  2115.     return t;
  2116. }
  2117.  
  2118. #if defined(SA_RESTART)
  2119. /* several systems (SCO, SunOS) have sigaction without SA_RESTART */
  2120. /*
  2121.  * Redefine signal in terms of sigaction for systems which have the
  2122.  * SA_RESTART flag defined through <signal.h>
  2123.  *
  2124.  * This definition of signal will cause system calls to get restarted for a
  2125.  * more BSD-ish behavior.  This will allow us to use the OPT_WORKING feature
  2126.  * for such systems.
  2127.  */
  2128.  
  2129. void
  2130. setup_handler(int sig, void (*disp) (int ACTUAL_SIG_ARGS))
  2131. {
  2132.     struct sigaction act, oact;
  2133.  
  2134.     act.sa_handler = disp;
  2135.     sigemptyset(&act.sa_mask);
  2136. #ifdef SA_NODEFER    /* don't rely on it.  if it's not there, signals
  2137.                     probably aren't deferred anyway. */
  2138.     act.sa_flags = SA_RESTART|SA_NODEFER ;
  2139. #else
  2140.     act.sa_flags = SA_RESTART;
  2141. #endif
  2142.  
  2143.     (void)sigaction(sig, &act, &oact);
  2144.  
  2145. }
  2146. #else
  2147. void
  2148. setup_handler(int sig, void (*disp) (int ACTUAL_SIG_ARGS))
  2149. {
  2150.     (void)signal(sig, disp);
  2151. }
  2152. #endif
  2153.  
  2154.  
  2155. /* put us in a new process group, on command.  we don't do this all the
  2156. * time since it interferes with suspending xvile on some systems with some
  2157. * shells.  but we _want_ it other times, to better isolate us from signals,
  2158. * and isolate those around us (like buggy window/display managers) from
  2159. * _our_ signals.  so we punt, and leave it up to the user.
  2160. */
  2161. /* ARGSUSED */
  2162. int
  2163. newprocessgroup(int f GCC_UNUSED, int n GCC_UNUSED)
  2164. {
  2165. #if DISP_X11
  2166.  
  2167.     int pid;
  2168.  
  2169.     if (f) {
  2170. #ifndef SYS_VMS
  2171.         pid = fork();
  2172. #else
  2173.         pid = vfork();    /* VAX C and DEC C have a 'vfork()' */
  2174. #endif
  2175.  
  2176.         if (pid > 0)
  2177.         tidy_exit(GOODEXIT);
  2178.         else if (pid < 0) {
  2179.         fputs("cannot fork\n", stderr);
  2180.         tidy_exit(BADEXIT);
  2181.         }
  2182.     }
  2183. # ifndef SYS_VMS
  2184. #  ifdef HAVE_SETSID
  2185.      (void)setsid();
  2186. #  else
  2187. #   ifdef HAVE_BSD_SETPGRP
  2188.      (void) setpgrp(0, 0);
  2189. #   else
  2190.      (void)setpgrp();
  2191. #   endif /* HAVE_BSD_SETPGRP */
  2192. #  endif /* HAVE_SETSID */
  2193. # endif /* SYS_VMS */
  2194. #endif /* DISP_X11 */
  2195.     return TRUE;
  2196. }
  2197.  
  2198.  
  2199. static int
  2200. cmd_mouse_motion(const CMDFUNC *cfp)
  2201. {
  2202. #if (OPT_XTERM || DISP_X11)
  2203.     return cfp && CMD_U_FUNC(cfp) == mouse_motion;
  2204. #else
  2205.     return FALSE;
  2206. #endif
  2207. }
  2208.