home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / VILE327.ZIP / VILE327.TAR / vile3.27 / main.c < prev    next >
Text File  |  1992-12-14  |  41KB  |  1,742 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
  14.  *
  15.  *
  16.  * $Log: main.c,v $
  17.  * Revision 1.88  1992/12/04  09:24:12  foxharp
  18.  * deleted unused assigns
  19.  *
  20.  * Revision 1.87  1992/12/02  09:13:16  foxharp
  21.  * changes for "c-shiftwidth"
  22.  *
  23.  * Revision 1.86  1992/11/19  09:11:45  foxharp
  24.  * eric krohn's changes for xvile "foreground", "background", and "name"
  25.  * arguments, and
  26.  * the "_qident" class of characters, useful for C++ "qualified" identifiers
  27.  *
  28.  * Revision 1.85  1992/11/19  08:48:48  foxharp
  29.  * comment fixup
  30.  *
  31.  * Revision 1.84  1992/08/20  23:40:48  foxharp
  32.  * typo fixes -- thanks, eric
  33.  *
  34.  * Revision 1.83  1992/08/19  22:59:05  foxharp
  35.  * catch SIGINT and critical errors under DOS, glob command line args,
  36.  * and clean up debug log ifdefs
  37.  *
  38.  * Revision 1.82  1992/08/18  22:39:59  foxharp
  39.  * prevent double zotting of VILEINIT buffer by delaying setting the
  40.  * BFSCRTCH flag (which probably isn't necessary anyway)
  41.  *
  42.  * Revision 1.81  1992/08/11  23:29:53  foxharp
  43.  * fixed core from vileinit buf getting killed too early -- no longer
  44.  * a scratch buffer
  45.  *
  46.  * Revision 1.80  1992/08/07  21:41:09  foxharp
  47.  * cosmetic ifdef cleanup
  48.  *
  49.  * Revision 1.79  1992/07/15  08:56:28  foxharp
  50.  * find our basename, so we can come up in view mode if named "view".
  51.  *
  52.  * Revision 1.78  1992/07/13  22:14:37  foxharp
  53.  * initialize TERSE and TAGSRELATIVE modes
  54.  *
  55.  * Revision 1.77  1992/07/13  09:26:56  foxharp
  56.  * use canonpath() on args before creating their buffers
  57.  *
  58.  * Revision 1.76  1992/07/04  14:37:49  foxharp
  59.  * allow the cursor to rest on the 'newline', in the case where we're in
  60.  * the middle of insert mode, and are only out here due to using arrow
  61.  * keys.  otherwise, there's no way to append to end of line with arrow
  62.  * keys -- you're blocked at the last character.:
  63.  *
  64.  * Revision 1.75  1992/07/01  17:01:42  foxharp
  65.  * make sure startstat is always set properly, and
  66.  * commented the usage of the FF logfile
  67.  *
  68.  * Revision 1.74  1992/06/26  22:22:23  foxharp
  69.  * moved reset of curbp (after makecurrent()) up higher -- vtinit may
  70.  * call update().
  71.  * some small fixes to the dos arg. expander.
  72.  * took out all the freshmem stuff -- it wasn't doing anything.
  73.  *
  74.  * Revision 1.73  1992/06/25  23:00:50  foxharp
  75.  * changes for dos/ibmpc
  76.  *
  77.  * Revision 1.72  1992/06/22  08:36:14  foxharp
  78.  * bug in section r.e.
  79.  *
  80.  * Revision 1.71  1992/06/12  22:23:42  foxharp
  81.  * changes for separate 'comments' r.e. for formatregion
  82.  *
  83.  * Revision 1.70  1992/06/08  08:56:05  foxharp
  84.  * added version no. to usage message
  85.  *
  86.  * Revision 1.69  1992/06/04  19:44:29  foxharp
  87.  * added -V for version info
  88.  *
  89.  * Revision 1.68  1992/06/01  20:38:12  foxharp
  90.  * writeall() no longer calls pressreturn() if successful, and
  91.  * added initialization for "tabinsert" mode
  92.  *
  93.  * Revision 1.67  1992/05/31  22:11:11  foxharp
  94.  * paragraph regexp augmented to support reformatting of comments
  95.  *
  96.  * Revision 1.66  1992/05/19  08:55:44  foxharp
  97.  * more prototype and shadowed decl fixups
  98.  *
  99.  * Revision 1.65  1992/05/16  12:00:31  pgf
  100.  * prototypes/ansi/void-int stuff/microsoftC
  101.  *
  102.  * Revision 1.64  1992/05/13  09:12:20  pgf
  103.  * force initial update in X11 -- not sure why -- seems to wait for event
  104.  * otherwise
  105.  *
  106.  * Revision 1.63  1992/04/30  17:53:37  pgf
  107.  * use new \s atom in paragraph and section regexps
  108.  *
  109.  * Revision 1.62  1992/04/14  08:42:42  pgf
  110.  * don't handle SIGWINCH in X11 case
  111.  *
  112.  * Revision 1.61  1992/04/10  18:49:23  pgf
  113.  * mark VILEINIT buf as scratch, so it goes away quickly
  114.  *
  115.  * Revision 1.60  1992/04/09  08:32:35  pgf
  116.  * new vilerc processing was happening too late, after the first buffer
  117.  * was already in.  this kept some modes from "sticking"
  118.  *
  119.  * Revision 1.59  1992/04/02  23:00:28  pgf
  120.  * fixed empty buffer bug, just introduced
  121.  *
  122.  * Revision 1.58  1992/03/24  07:44:05  pgf
  123.  * added support for VILEINIT variable for initialization
  124.  *
  125.  * Revision 1.57  1992/03/19  23:22:46  pgf
  126.  * SIGT for signals, linux port
  127.  *
  128.  * Revision 1.56  1992/03/19  23:09:22  pgf
  129.  * usage cleanup
  130.  *
  131.  * Revision 1.55  1992/03/07  10:36:29  pgf
  132.  * fix missing goto-line argument problem.  "vile + file.c" now goes to end of
  133.  * file, as it should
  134.  *
  135.  * Revision 1.54  1992/03/05  09:19:55  pgf
  136.  * changed some mlwrite() to mlforce(), due to new terse support
  137.  *
  138.  * Revision 1.53  1992/03/03  21:59:02  pgf
  139.  * added '`' to the _wild character set
  140.  *
  141.  * Revision 1.52  1992/03/03  09:35:52  pgf
  142.  * added support for getting "words" out of the buffer via variables --
  143.  * needed _nonspace character type
  144.  *
  145.  * Revision 1.51  1992/02/17  08:58:12  pgf
  146.  * added "showmode" support, and kill registers now hold unsigned chars
  147.  *
  148.  * Revision 1.50  1992/01/14  20:24:54  pgf
  149.  * don't ask for pressreturn() confirmation in quickexit() (ZZ command)
  150.  *
  151.  * Revision 1.49  1992/01/10  08:08:28  pgf
  152.  * added initialization of shiftwidth
  153.  *
  154.  * Revision 1.48  1992/01/05  00:06:13  pgf
  155.  * split mlwrite into mlwrite/mlprompt/mlforce to make errors visible more
  156.  * often.  also normalized message appearance somewhat.
  157.  *
  158.  * Revision 1.47  1992/01/03  23:31:49  pgf
  159.  * use new ch_fname() to manipulate filenames, since b_fname is now
  160.  * a malloc'ed sting, to avoid length limits
  161.  *
  162.  * Revision 1.46  1991/11/27  10:09:09  pgf
  163.  * slight rearrangement of init code, to prevent null filenames in makecurrent
  164.  *
  165.  * Revision 1.45  1991/11/16  18:38:58  pgf
  166.  * changes for better magic mode -- the regexps for sections, paras etc. had
  167.  * to change
  168.  *
  169.  * Revision 1.44  1991/11/13  20:09:27  pgf
  170.  * X11 changes, from dave lemke
  171.  *
  172.  * Revision 1.43  1991/11/07  02:00:32  pgf
  173.  * lint cleanup
  174.  *
  175.  * Revision 1.42  1991/11/06  23:26:27  pgf
  176.  * recomp the search pattern if set from command line, and
  177.  * added _fence to chartypes
  178.  *
  179.  * Revision 1.41  1991/11/01  14:38:00  pgf
  180.  * saber cleanup
  181.  *
  182.  * Revision 1.40  1991/10/29  14:35:29  pgf
  183.  * implemented the & commands: substagain
  184.  *
  185.  * Revision 1.39  1991/10/29  03:02:55  pgf
  186.  * rename ctlx? routines to be ...kbd_macro... names, and allowed
  187.  * for replaying of named registers
  188.  *
  189.  * Revision 1.38  1991/10/28  14:25:44  pgf
  190.  * VAL_ASAVE --> VAL_ASAVECNT
  191.  *
  192.  * Revision 1.37  1991/10/27  01:45:10  pgf
  193.  * set new regex values in global_val_init
  194.  *
  195.  * Revision 1.36  1991/10/24  13:05:52  pgf
  196.  * conversion to new regex package -- much faster
  197.  *
  198.  * Revision 1.35  1991/10/23  14:20:53  pgf
  199.  * changes to fix interactions between dotcmdmode and kbdmode and tungetc
  200.  *
  201.  * Revision 1.34  1991/10/22  03:08:45  pgf
  202.  * call cmdlinetag() for command-line tags
  203.  *
  204.  * Revision 1.33  1991/10/20  23:07:56  pgf
  205.  * pass taglength value to tags()
  206.  *
  207.  * Revision 1.32  1991/10/18  10:56:54  pgf
  208.  * modified VALUE structures and lists to make them more easily settable
  209.  *
  210.  * Revision 1.31  1991/10/15  03:10:49  pgf
  211.  * added backspacelimit and taglength
  212.  *
  213.  * Revision 1.30  1991/09/26  13:13:54  pgf
  214.  * initialize window values, and
  215.  * make sure file writing errors in writeall() are made visible
  216.  *
  217.  * Revision 1.29  1991/09/19  13:39:17  pgf
  218.  * MDEXACT is now MDIGNCASE, and initialize new VAL_TAGS value to "tags"
  219.  *
  220.  * Revision 1.28  1991/09/17  13:02:57  pgf
  221.  * added write-all and brethren
  222.  *
  223.  * Revision 1.27  1991/09/10  00:46:07    pgf
  224.  * cleanup of the dotcmd stuff
  225.  *
  226.  * Revision 1.26  1991/08/13  02:50:13    pgf
  227.  * initialize showmatch b_val
  228.  *
  229.  * Revision 1.25  1991/08/12  11:22:52    pgf
  230.  * added 'vi +/searchstring file.c' invocation
  231.  *
  232.  * Revision 1.24  1991/08/12  10:23:43    pgf
  233.  * esc() no longer kills keyboard recording
  234.  *
  235.  * Revision 1.23  1991/08/08  23:28:49    pgf
  236.  * moved init of VAL_FILL to after vtinit, since it depends on term.t_ncol
  237.  *
  238.  * Revision 1.22  1991/08/08  13:19:58    pgf
  239.  * removed ifdef BEFORE
  240.  *
  241.  * Revision 1.21  1991/08/07  12:35:07    pgf
  242.  * added RCS log messages
  243.  *
  244.  * revision 1.20
  245.  * date: 1991/08/06 15:55:24;
  246.  * fixed dos mode on empty buffer
  247.  * 
  248.  * revision 1.19
  249.  * date: 1991/08/06 15:23:42;
  250.  *  global/local values
  251.  * 
  252.  * revision 1.18
  253.  * date: 1991/07/23 11:12:19;
  254.  * don't reset lastdot if absolute motion is on behalf of an operator
  255.  * 
  256.  * revision 1.17
  257.  * date: 1991/07/19 17:16:03;
  258.  * ignore SIG_QUIT unless DEBUG
  259.  * 
  260.  * revision 1.16
  261.  * date: 1991/06/28 10:53:42;
  262.  * undo last change -- was breaking some ops
  263.  * 
  264.  * revision 1.15
  265.  * date: 1991/06/27 19:45:16;
  266.  * moved back from eol and eob to execute()
  267.  * 
  268.  * revision 1.14
  269.  * date: 1991/06/26 09:38:15;
  270.  * removed an ifdef BEFORE
  271.  * 
  272.  * revision 1.13
  273.  * date: 1991/06/25 19:52:59;
  274.  * massive data structure restructure
  275.  * 
  276.  * revision 1.12
  277.  * date: 1991/06/16 17:36:17;
  278.  * support for local vs. global fillcol value
  279.  * 
  280.  * revision 1.11
  281.  * date: 1991/06/07 22:00:18;
  282.  * changed header
  283.  * 
  284.  * revision 1.10
  285.  * date: 1991/06/07 13:22:23;
  286.  * don't move "last dot" mark if ABS command doesn't change dot
  287.  * 
  288.  * revision 1.9
  289.  * date: 1991/06/03 17:34:55;
  290.  * switch from "meta" etc. to "ctla" etc.
  291.  * 
  292.  * revision 1.8
  293.  * date: 1991/06/03 10:25:16;
  294.  * command loop is now a separate routine, and
  295.  * if (doingopcmd) stuff is now in operators()
  296.  * 
  297.  * revision 1.7
  298.  * date: 1991/05/31 12:54:25;
  299.  * put _wild chartypes back in -- dropped by mistake
  300.  * 
  301.  * revision 1.6
  302.  * date: 1991/05/31 11:12:19;
  303.  * changed args to execute(), and
  304.  * added linespec character class, and
  305.  * added unimplemented ex functions
  306.  * 
  307.  * revision 1.5
  308.  * date: 1991/04/22 09:00:12;
  309.  * added iswild type to chartypes
  310.  * 
  311.  * revision 1.4
  312.  * date: 1991/04/04 09:37:48;
  313.  * new arg. to unqname
  314.  * 
  315.  * revision 1.3
  316.  * date: 1991/02/19 17:27:03;
  317.  * set up the reverse pattern if -s is given
  318.  * 
  319.  * revision 1.2
  320.  * date: 1990/10/03 16:00:57;
  321.  * make backspace work for everyone
  322.  * 
  323.  * revision 1.1
  324.  * date: 1990/09/21 10:25:35;
  325.  * initial vile RCS revision
  326.  */
  327.  
  328. #include    <stdio.h>
  329.  
  330. #include    "estruct.h"    /* global structures and defines */
  331.  
  332. extern char *pathname[];    /* startup file path/name array */
  333.  
  334. /* for MSDOS, increase the default stack space */
  335.  
  336. #if    MSDOS & LATTICE
  337. unsigned _stack = 32767;
  338. #endif
  339.  
  340. #if    ATARI & LATTICE & 0
  341. int _mneed = 256000;        /* reset memory pool size */
  342. #endif
  343.  
  344. #if    MSDOS & AZTEC
  345. int _STKSIZ = 32767/16;     /* stack size in paragraphs */
  346. int _STKRED = 1024;        /* stack checking limit */
  347. int _HEAPSIZ = 4096/16;     /* (in paragraphs) */
  348. int _STKLOW = 0;        /* default is stack above heap (small only) */
  349. #endif
  350.  
  351. #if    MSDOS & TURBO
  352. unsigned _stklen = 32768;
  353. #endif
  354.  
  355. #if UNIX || MSDOS
  356. #include    <signal.h>
  357. #endif
  358.  
  359. /* Make global definitions not external */
  360. #define realdef
  361. #include    "edef.h"    /* global definitions */
  362.  
  363. #if    VMS
  364. #include    <ssdef.h>
  365. #define GOOD    (SS$_NORMAL)
  366. #endif
  367.  
  368. #ifndef GOOD
  369. #define GOOD    0
  370. #endif
  371.  
  372. int
  373. main(argc, argv)
  374. int    argc;
  375. char    *argv[];
  376. {
  377.     int    c;            /* command character */
  378.     register BUFFER *bp;        /* temp buffer pointer */
  379.     register int    gotafile = FALSE;/* filename arg present? */
  380.     register int    carg;        /* current arg to scan */
  381.     register int    ranstartup = FALSE;/* startup executed flag */
  382.     int startstat = TRUE;        /* result of running startup */
  383.     BUFFER *firstbp = NULL;     /* ptr to first buffer in cmd line */
  384.     int gotoflag = FALSE;        /* do we need to goto line at start? */
  385.     int gline = FALSE;        /* if so, what line? */
  386.     int helpflag = FALSE;        /* do we need help at start? */
  387.     int searchflag = FALSE;     /* Do we need to search at start? */
  388.     char bname[NBUFN];        /* buffer name of file to read */
  389.     char *msg;
  390. #if TAGS
  391.     int didtag = FALSE;        /* look up a tag to start? */
  392.     char *tname = NULL;
  393. #endif
  394. #if    CRYPT
  395.     char ekey[NPAT];        /* startup encryption key */
  396. #endif
  397.     char *us;
  398.  
  399. #if MSDOS
  400.     char *simplename( char * );
  401.     slash = '\\';  /* getswitchar() == '/' ? '\\' : '/'; */
  402.     expand_wild_args(&argc, &argv);
  403. #else
  404.     slash = '/';
  405. #endif
  406.  
  407.     us = strrchr(argv[0],slash);
  408.     if (!us)
  409.         us = argv[0];
  410.     else
  411.         us++;
  412.  
  413.     start_debug_log(argc,argv);
  414.  
  415.     charinit();        /* character types -- we need these pretty
  416.                     early  */
  417.     global_val_init();    /* global buffer values */
  418.  
  419.     if (strcmp(us, "view") == 0)
  420.         set_global_b_val(MDVIEW,TRUE);
  421.  
  422.  
  423. #if IBMPC    /* pjr */
  424.     ibmtype = CDSENSE;
  425. #endif    /* IBMPC */
  426.  
  427. #if X11
  428.     x_preparse_args(&argc, &argv);
  429. #endif
  430.     /* Parse the command line */
  431.     for (carg = 1; carg < argc; ++carg) {
  432. #if X11
  433.         if (argv[carg][0] == '=') {
  434.                     x_set_geometry(argv[carg]);
  435.                         continue;
  436.                 }
  437. #endif
  438.  
  439.  
  440.         /* Process Switches */
  441.         if (argv[carg][0] == '-') {
  442.             switch (argv[carg][1]) {
  443. #if    NeWS
  444.             case 'l':    /* -l for screen lines */
  445.             case 'L':
  446.                 term.t_nrow = atoi(&argv[carg][2]);
  447.                 break;
  448. #endif
  449. #if X11
  450.             case 'd':
  451.                 if (argv[carg + 1])
  452.                     x_set_dpy(argv[++carg]);
  453.                 else
  454.                     goto usage;
  455.                 break;
  456.             case 'r':
  457.             case 'R':
  458.                 x_set_rv();
  459.                 break;
  460.             case 'f':
  461.             case 'F':
  462.                 if (strcmp(&argv[carg][1], "foreground") == 0)
  463.                     x_setforeground(argv[++carg]);
  464.                 else if (strcmp(&argv[carg][1], "fg") == 0)
  465.                     x_setforeground(argv[++carg]);
  466.                 else if (argv[carg + 1])
  467.                     x_setfont(argv[++carg]);
  468.                 else
  469.                     goto usage;
  470.  
  471.                 break;
  472.             case 'b':
  473.                 if (strcmp(&argv[carg][1], "background") == 0)
  474.                     x_setbackground(argv[++carg]);
  475.                 else if (strcmp(&argv[carg][1], "bg") == 0)
  476.                     x_setbackground(argv[++carg]);
  477.                 else
  478.                     goto usage;
  479.  
  480.                 break;
  481.             case 'n':
  482.                 if (strcmp(&argv[carg][1], "name") == 0)
  483.                     x_setname(argv[++carg]);
  484.                 else
  485.                     goto usage;
  486.  
  487.                 break;
  488. #endif
  489.             case 'e':    /* -e for Edit file */
  490.             case 'E':
  491.                 set_global_b_val(MDVIEW,FALSE);
  492.                 break;
  493.             case 'g':    /* -g for initial goto */
  494.             case 'G':
  495.                 gotoflag = TRUE;
  496.                 if (argv[carg][2]) {
  497.                     gline = atoi(&argv[carg][2]);
  498.                 } else {
  499.                     if (++carg < argc)
  500.                         gline = atoi(&argv[carg][0]);
  501.                     else
  502.                         goto usage;
  503.                 }
  504.                 break;
  505.             case 'h':    /* -h for initial help */
  506.             case 'H':
  507.                 helpflag = TRUE;
  508.                 break;
  509. #if    CRYPT
  510.             case 'k':    /* -k<key> for code key */
  511.             case 'K':
  512.                 cryptflag = TRUE;
  513.                 if (argv[carg][2]) {
  514.                     strcpy(ekey, &argv[carg][2]);
  515.                 } else {
  516.                     if (++carg < argc)
  517.                         strcpy(ekey, &argv[carg][0]);
  518.                     else
  519.                         goto usage;
  520.                 }
  521.                 set_global_b_val(MDCRYPT,TRUE);
  522.                 crypt((char *)NULL, 0);
  523.                 crypt(ekey, strlen(ekey));
  524.                 break;
  525. #endif
  526.             case 's':  /* -s for initial search string */
  527.             case 'S':
  528.         dosearch:
  529.                 searchflag = TRUE;
  530.                 if (argv[carg][2]) {
  531.                     strncpy(pat,&argv[carg][2],NPAT);
  532.                 } else {
  533.                     if (++carg < argc)
  534.                         strncpy(pat,&argv[carg][0],NPAT);
  535.                     else
  536.                         goto usage;
  537.                 }
  538.                 gregexp = regcomp(pat, global_b_val(MDMAGIC));
  539.                 break;
  540. #if TAGS
  541.             case 't':  /* -t for initial tag lookup */
  542.             case 'T':
  543.                 if (argv[carg][2]) {
  544.                     tname = &argv[carg][2];
  545.                 } else {
  546.                     if (++carg < argc)
  547.                         tname = &argv[carg][0];
  548.                     else
  549.                         goto usage;
  550.                 }
  551.                 break;
  552. #endif
  553.             case 'V':
  554. #ifndef DOS
  555.                 printf("vile %s\n", version);
  556.                 exit(0);
  557. #endif
  558.             case 'v':    /* -v for View File */
  559.                 set_global_b_val(MDVIEW,TRUE);
  560.                 break;
  561. #if IBMPC
  562. #if __ZTC__
  563.             /*
  564.              * Note that ibmtype is now only used to detect
  565.              * whether a command line option was given, ie if
  566.              * it is not equal to CDSENSE then a command line
  567.              * option was given
  568.              */
  569.             case '2':    /* 25 line mode */
  570.                 ibmtype = CDMONO;
  571.                 set43 = FALSE;
  572.                   break;
  573.  
  574.             case '4':    /* 43 line mode */
  575.                 ibmtype = CDEGA;
  576.                 set43 = TRUE;
  577.                 break;
  578.  
  579.             case '5':    /* 50 line mode */
  580.                 ibmtype = CDVGA;
  581.                 set43 = TRUE;
  582.                 break;
  583. #else
  584.             case '2':    /* 25 line mode */
  585. #if COLOR
  586.                 ibmtype = CDCGA;
  587. #else
  588.                 ibmtype = CDMONO;
  589. #endif
  590.                 break;
  591.             case '4':    /* 43 line mode */
  592.                 ibmtype = CDEGA;
  593.                 break;
  594.             case '5':    /* 50 line mode */
  595.                 ibmtype = CDVGA;
  596.                 break;
  597.  
  598. #endif    /* __ZTC__ */
  599. #endif    /* IBMPC */
  600.  
  601.             case '?':
  602.             default:    /* unknown switch */
  603.             usage:
  604.     fprintf(stderr, "usage: %s [-flags] [@cmdfile] files...\n",argv[0]);
  605.     fprintf(stderr, "    -h to get help on startup\n");
  606.     fprintf(stderr, "    -gNNN or simply +NNN to go to line NNN\n");
  607.     fprintf(stderr, "    -sstring or +/string to search for \"string\"\n");
  608. #if TAGS
  609.     fprintf(stderr, "    -ttagname to look up a tag\n");
  610. #endif
  611.     fprintf(stderr, "    -v to view files as read-only\n");
  612.     /* fprintf(stderr, "    -e to edit (as opposed to view) files\n"); */
  613. #if CRYPT
  614.     fprintf(stderr, "    -kcryptkey for encrypted files\n");
  615. #endif
  616. #if X11
  617.     fprintf(stderr, "    -name name to change program name for X resources\n");
  618.     fprintf(stderr, "    -fg color to change foreground color\n");
  619.     fprintf(stderr, "    -bg color to change background color\n");
  620.     fprintf(stderr, "    -f fontname to change font\n");
  621.     fprintf(stderr, "    -d displayname to change the default display\n");
  622.     fprintf(stderr, "    -r for reverse video\n");
  623. #endif
  624. #if ! DOS
  625.     fprintf(stderr, "    -V for version info\n");
  626. #endif
  627.     fprintf(stderr, "    use @filename to run filename as commands\n");
  628.     fprintf(stderr, "     (this will suppress .vilerc)\n");
  629.     fprintf(stderr, "    This is vile %s\n",version);
  630.                 exit(1);
  631.             }
  632.  
  633.         } else if (argv[carg][0]== '+') { /* alternate form of -g */
  634.             if (argv[carg][1] == '/')
  635.                 goto dosearch;
  636.             gotoflag = TRUE;
  637.             gline = atoi(&argv[carg][1]);
  638.         } else if (argv[carg][0]== '@') {
  639.             /* Process Startup macroes */
  640.             if ((startstat = startup(&argv[carg][1])) == TRUE)
  641.                 ranstartup = TRUE; /* don't execute .vilerc */
  642.         } else {
  643.  
  644.             /* Process an input file */
  645.  
  646.             /* set up a buffer for this file */
  647. #if MSDOS
  648.             (void)glob(argv[carg]);
  649. #endif
  650.             makename(bname, argv[carg]);
  651.             unqname(bname,FALSE);
  652.  
  653.             bp = bfind(bname, OK_CREAT, 0);
  654.             ch_fname(bp, argv[carg]);
  655.             make_current(bp); /* pull it to the front */
  656.             if (!gotafile) {
  657.                 firstbp = bp;
  658.                 gotafile = TRUE;
  659.             }
  660.  
  661.         }
  662.     }
  663.  
  664.     /* we made some calls to makecurrent() above, to shuffle the
  665.         list order.  this set curbp, which isn't actually kosher */
  666.     curbp = NULL;
  667.  
  668.     /* initialize the editor */
  669. #if UNIX
  670.     signal(SIGINT,catchintr);
  671.     signal(SIGHUP,imdying);
  672. #ifdef SIGBUS
  673.     signal(SIGBUS,imdying);
  674. #endif
  675. #ifdef SIGSYS
  676.     signal(SIGSYS,imdying);
  677. #endif
  678.     signal(SIGSEGV,imdying);
  679.     signal(SIGTERM,imdying);
  680. #if DEBUG
  681.     signal(SIGQUIT,imdying);
  682. #else
  683.     signal(SIGQUIT,SIG_IGN);
  684. #endif
  685.     signal(SIGPIPE,SIG_IGN);
  686. #if defined(SIGWINCH) && ! X11
  687.     signal(SIGWINCH,sizesignal);
  688. #endif
  689. #else
  690. # if MSDOS
  691.     signal(SIGINT,catchintr);
  692.     _harderr(dos_crit_handler);
  693. # endif
  694. #endif
  695.     vtinit();        /* Display */
  696.     winit();        /* windows */
  697.     varinit();        /* user variables */
  698.         
  699.     /* this comes out to 70 on an 80 (or greater) column display */
  700.     {    register int fill;
  701.         fill = (7 * term.t_ncol) / 8;  /* must be done after vtinit() */
  702.         if (fill > 70) fill = 70;
  703.         set_global_b_val(VAL_FILL, fill);
  704.     }
  705.  
  706.     /* pull in an unnamed buffer, if we were given none to work with */
  707.     if (!gotafile) {
  708.         bp = bfind("[unnamed]", OK_CREAT, 0);
  709.         bp->b_active = TRUE;
  710. #if DOSFILES
  711.         make_local_b_val(bp,MDDOS);
  712.         set_b_val(bp, MDDOS, FALSE );
  713. #endif
  714.         swbuffer(bp);
  715.     }
  716.  
  717.     /* if invoked with no other startup files,
  718.        run the system startup file here */
  719.     if (!ranstartup) {
  720.         char *getenv();
  721.         char *vileinit;
  722.         vileinit = getenv("VILEINIT");
  723.         if (vileinit != NULL) {
  724.             int odiscmd;
  725.             BUFFER *vbp, *obp;
  726.             int oflags = 0;
  727.  
  728.             /* mark as modified, to prevent undispbuff() from
  729.                  clobbering */
  730.             obp = curbp;
  731.             if (obp) {
  732.                 oflags = obp->b_flag;
  733.                 obp->b_flag |= BFCHG;
  734.             }
  735.  
  736.             if ((vbp=bfind("[vileinit]", OK_CREAT, 0))==NULL)
  737.                 exit(1);
  738.             /* mark the buffer as read only */
  739.             make_local_b_val(vbp,MDVIEW);
  740.             set_b_val(vbp,MDVIEW,TRUE);
  741.  
  742.             vbp->b_active = TRUE;
  743.  
  744.             swbuffer(vbp);
  745.             bprintf("%s", vileinit);
  746.             vbp->b_flag &= ~BFCHG;
  747.  
  748.             /* go execute it! */
  749.             odiscmd = discmd;
  750.             discmd = FALSE;
  751.             startstat = dobuf(vbp);
  752.             discmd = odiscmd;
  753.             if (obp) {
  754.                 swbuffer(obp);
  755.                 obp->b_flag = oflags;
  756.             }
  757.             /* remove the now unneeded buffer */
  758.             vbp->b_flag |= BFSCRTCH;  /* make sure it will go */
  759.             zotbuf(vbp);
  760.         } else {
  761.             char *fname;
  762.             /* if .vilerc is one of the input files....
  763.                     don't clobber it */
  764. #if MSDOS
  765.             /* search PATH for vilerc under dos */
  766.              fname = flook(pathname[0], FL_ANYWHERE); /* pjr - find it! */
  767. #else
  768.             fname = pathname[0];
  769. #endif
  770.             if (gotafile && 
  771.                 strcmp(pathname[0], firstbp->b_bname) == 0) {
  772.                 c = firstbp->b_bname[0];
  773.                 firstbp->b_bname[0] = '[';
  774.                 startstat = startup(fname);
  775.                 firstbp->b_bname[0] = c;
  776.             } else {
  777.                 if (fname)
  778.                     startstat = startup(fname);
  779.                 else
  780.                     startstat = TRUE;
  781.             }
  782.         }
  783.         /* ranstartup = TRUE; (unneeded) */
  784.     }
  785.  
  786.  
  787.     /* if there are any files to read, read the first one! */
  788.     if (gotafile) {
  789.         nextbuffer(FALSE,0);
  790.     }
  791. #if TAGS
  792.     else if (tname) {
  793.         cmdlinetag(tname);
  794.         didtag = TRUE;
  795.     }
  796. #endif
  797.     msg = "";
  798.     if (helpflag) {
  799.         if (help(TRUE,1) != TRUE) {
  800.             msg = 
  801.     "[Problem with help information. Type \":quit\" to exit if you wish]";
  802.         }
  803.     } else {
  804.         msg = "[Use ^A-h, ^X-h, or :help to get help]";
  805.     }
  806.  
  807.     /* Deal with startup gotos and searches */
  808.     if (gotoflag + searchflag
  809. #if TAGS
  810.          + (tname?1:0) 
  811. #endif
  812.         > 1) {
  813. #if TAGS
  814.         msg = "[Search, goto and tag are used one at a time]";
  815. #else
  816.         msg = "[Cannot search and goto at the same time]";
  817. #endif
  818.     } else if (gotoflag) {
  819.         if (gotoline(gline != 0, gline) == FALSE)
  820.             msg = "[Invalid goto argument]";
  821.     } else if (searchflag) {
  822.         forwhunt(FALSE, 0);
  823. #if TAGS
  824.     } else if (tname && !didtag) {
  825.         cmdlinetag(tname);
  826. #endif
  827.     }
  828.  
  829. #if X11
  830.     update(TRUE);
  831. #else
  832.     update(FALSE);
  833. #endif
  834.     if (startstat == TRUE)  /* else there's probably an error message */
  835.         mlforce(msg);
  836.  
  837.  
  838.     /* process commands */
  839.     loop();
  840.  
  841.     /* NOTREACHED */
  842.  
  843.     return 1;
  844.  
  845. }
  846.  
  847. #if MSDOS
  848. /*
  849.  * This is a replacement for the usual main routine.  It takes argc and
  850.  * argv, and does wild card expansion on any arguments containing a '*' or
  851.  * '?', and then calls main() with a new argc and argv.  Any errors result
  852.  * in calling main() with the original arguments intact.  Arguments
  853.  * containing wild cards that expand to 0 filenames are deleted.  Arguments
  854.  * without wild cards are passed straight through.
  855.  *
  856.  * Arguments which are preceded by a " or ', are passed straight through. 
  857.  * (cck)
  858.  *
  859.  * (taken from the winc app example of the zortech compiler - pjr)
  860.  */
  861.  
  862. void
  863. expand_wild_args(argcp, argvp)
  864. int *argcp;
  865. char ***argvp;
  866. {
  867. #ifdef FRESHMEM
  868.     char          **freshmem = NULL;
  869.     unsigned int    freshmemcount = 0;
  870.     unsigned int    freshmemmax = 0;
  871. #endif
  872.     int oargc;
  873.     char **oargv;
  874.  
  875. #ifdef __ZTC__
  876.     struct FIND    *p;
  877. #else
  878.     struct find_t   p;
  879.     int             j = 0;
  880. #endif
  881.  
  882.     int             i, nargc, path_size, nargvmax;
  883.     char          **nargv, path[FILENAME_MAX + 1], *cp, *end_path;
  884.  
  885.     oargc = *argcp;
  886.     oargv = *argvp;
  887.  
  888.     nargc = 0;
  889.     nargvmax = 2;        /* dimension of nargv[]         */
  890.     if ((nargv = (char **)malloc(nargvmax * sizeof(char *))) == NULL) {
  891.         mlforce("[OUT OF MEMORY]");
  892.         return;
  893.     }
  894.  
  895.     for (i = 0; i < oargc; ++i) {
  896.         if (nargc + 2 >= nargvmax) {
  897.             nargvmax = nargc + 2;
  898.             if ((nargv = (char **) realloc(nargv, nargvmax * sizeof(char *))) == NULL) {
  899.                 mlforce("[OUT OF MEMORY]");
  900.                 return;
  901.             }
  902.         }
  903.         cp = oargv[i];    /* cck */
  904.  
  905.         /* if have expandable names */
  906.         if (!(cp[0] == '"' || cp[0] == '\'') && 
  907.             (strchr(cp, '*') || strchr(cp, '?'))) {
  908.             end_path = cp + strlen(cp);
  909.  
  910.             while (end_path >= cp && *end_path != '\\'
  911.                    && *end_path != '/' && *end_path != ':')
  912.                 --end_path;
  913.  
  914.             path_size = 0;
  915.  
  916.             if (end_path >= cp) {    /* if got a path */
  917.                 path_size = end_path - cp + 1;
  918.                 memcpy(path, cp, path_size);
  919.             }
  920.             path[path_size] = 0;
  921. #ifdef __ZTC__
  922.             p = findfirst(cp, 0);
  923.             while (p) {
  924.                 if ((cp = malloc(path_size+strlen(p->name)+1))
  925.                             == NULL)
  926. #else
  927.             j = _dos_findfirst(cp, 0, &p);
  928.             while (!j) {
  929.                 if ((cp = malloc(path_size+strlen(p.name)+1))
  930.                             == NULL)
  931. #endif
  932.                 {
  933.                     mlforce("[OUT OF MEMORY]");
  934.                     return;
  935.                 }
  936.                 strcpy(cp, path);
  937.  
  938. #ifdef __ZTC__
  939.                 strcat(cp, p->name);
  940. #else
  941.                 strcat(cp, p.name);
  942. #endif
  943.  
  944.                 if (nargc + 2 >= nargvmax) {
  945.                     nargvmax = nargc + 2;
  946.                     if ((nargv = (char **) realloc(
  947.                         nargv, 
  948.                         nargvmax * sizeof(char *))
  949.                         ) == NULL) {
  950.                         mlforce("[OUT OF MEMORY]");
  951.                         return;
  952.                     }
  953.                 }
  954.                 nargv[nargc++] = cp;
  955.  
  956. #ifdef FRESHMEM
  957.                 if (freshmemcount >= freshmemmax) {
  958.                     freshmemmax += 4;
  959.  
  960.                     if ((freshmem = (char **) realloc(
  961.                         freshmem, 
  962.                         freshmemmax * sizeof(char *))
  963.                             ) == NULL) {
  964.                         mlforce("[OUT OF MEMORY]");
  965.                         return;
  966.                     }
  967.                 }
  968.                 freshmem[freshmemcount++] = cp;
  969. #endif
  970. #ifdef __ZTC__
  971.                 p = findnext();
  972.             }
  973. #else
  974.                 j = _dos_findnext(&p);
  975.             }
  976. #endif
  977.         } else {
  978.             nargv[nargc++] = oargv[i];
  979.         }
  980.     }
  981.  
  982.     nargv[nargc] = NULL;
  983.     *argcp = nargc;
  984.     *argvp = nargv;
  985. }
  986. #endif
  987.  
  988. void do_num_proc();
  989. void do_rept_arg_proc();
  990.  
  991. /* this is nothing but the main command loop */
  992. void
  993. loop()
  994. {
  995.     int s,c,f,n;
  996.     while(1) {
  997.         extern int insert_mode_was;
  998.  
  999.         /* vi doesn't let the cursor rest on the newline itself.  This
  1000.             takes care of that. */
  1001.         /* if we're inserting, or will be inserting again, then
  1002.             suppress.  this happens if we're using arrow keys
  1003.             during insert */
  1004.         if (is_at_end_of_line(DOT) && !is_empty_line(DOT) &&
  1005.                 !insertmode && !insert_mode_was)
  1006.             backchar(TRUE,1);
  1007.  
  1008.         /* same goes for end-of-file -- I'm actually not sure if
  1009.             this can ever happen, but I _am_ sure that it's
  1010.             a lot safer not to let it... */
  1011.         if (is_header_line(DOT,curbp) && !is_empty_buf(curbp))
  1012.             backline(TRUE,1);
  1013.  
  1014.         /* start recording for '.' command */
  1015.         dotcmdbegin();
  1016.  
  1017.         /* Fix up the screen    */
  1018.         s = update(FALSE);
  1019.  
  1020.         /* get the next command from the keyboard */
  1021.         c = kbd_seq();
  1022.  
  1023.         /* if there is something on the command line, clear it */
  1024.         if (mpresf != FALSE) {
  1025.             mlerase();
  1026.             if (s != SORTOFTRUE) /* did nothing due to typeahead */
  1027.                 update(FALSE);
  1028.         }
  1029.  
  1030.         f = FALSE;
  1031.         n = 1;
  1032.  
  1033.         do_num_proc(&c,&f,&n);
  1034.         do_rept_arg_proc(&c,&f,&n);
  1035.  
  1036.         kregflag = 0;
  1037.             
  1038.         /* flag the first time through for some commands -- e.g. subst
  1039.             must know to not prompt for strings again, and pregion
  1040.             must only restart the p-lines buffer once for each
  1041.             command. */
  1042.         calledbefore = FALSE;
  1043.  
  1044.         /* and execute the command */
  1045.         execute(kcod2fnc(c), f, n);
  1046.             
  1047.         if (bheadp != curbp)
  1048.             mlforce("BUG: main: bheadp != curbp, bhead name is %s",
  1049.                      bheadp->b_bname);
  1050.  
  1051.         /* stop recording for '.' command */
  1052.         dotcmdfinish();
  1053.     }
  1054. }
  1055.  
  1056. char *
  1057. strmalloc(s)
  1058. char *s;
  1059. {
  1060.     char *ns = malloc(strlen(s)+1);
  1061.     if (ns)
  1062.         return strcpy(ns,s);
  1063.     else
  1064.         return NULL;
  1065.  
  1066. }
  1067.  
  1068.  
  1069. void
  1070. global_val_init()
  1071. {
  1072.     register int i;
  1073.     struct regexval *rp;
  1074.     /* set up so the global value pointers point at the global
  1075.         values.  we never actually use the global pointers
  1076.         directly, but but when buffers get a copy of the
  1077.         global_b_values structure, the pointers will still point
  1078.         back at the global values, which is what we want */
  1079.     for (i = 0; i <= MAX_B_VALUES; i++)
  1080.         global_b_values.bv[i].vp = &(global_b_values.bv[i].v);
  1081.  
  1082.     for (i = 0; i <= MAX_W_VALUES; i++)
  1083.         global_w_values.wv[i].vp = &(global_w_values.wv[i].v);
  1084.  
  1085.  
  1086.     set_global_b_val(MDWRAP,FALSE);     /* wrap */
  1087.     set_global_b_val(MDCMOD,FALSE);     /* C mode */
  1088.     set_global_b_val(MDBACKLIMIT,TRUE);     /* limit backspacing to insert point */
  1089.     set_global_b_val(MDSWRAP,TRUE);     /* scan wrap */
  1090.     set_global_b_val(MDIGNCASE,FALSE);     /* exact matches */
  1091.     set_global_b_val(MDVIEW,FALSE);     /* view-only */
  1092.     set_global_b_val(MDMAGIC,TRUE);     /* magic searches */
  1093.     set_global_b_val(MDCRYPT,FALSE);    /* crypt */
  1094.     set_global_b_val(MDASAVE,FALSE);    /* auto-save */
  1095.     set_global_b_val(MDDOS,FALSE);        /* dos mode */
  1096.     set_global_b_val(MDAIND,FALSE);     /* auto-indent */
  1097.     set_global_b_val(MDSHOWMAT,FALSE);    /* show-match */
  1098.     set_global_b_val(MDSHOWMODE,TRUE);    /* show-mode */
  1099.     set_global_b_val(MDTABINSERT,TRUE);    /* allow tab insertion */
  1100.     set_global_b_val(MDTAGSRELTIV,FALSE);    /* path relative tag lookups */
  1101.     set_global_b_val(MDTERSE,FALSE);    /* terse messaging */
  1102.     set_global_b_val(VAL_TAB, 8);        /* tab stop */
  1103.     set_global_b_val(VAL_SWIDTH, 8);     /* shiftwidth */
  1104.     set_global_b_val(VAL_TAGLEN, 0);    /* significant tag length */
  1105.     set_global_b_val(VAL_C_TAB, 8);     /* C file tab stop */
  1106.     set_global_b_val(VAL_C_SWIDTH, 8);     /* C file shiftwidth */
  1107.     set_global_b_val(VAL_ASAVECNT, 256);    /* autosave count */
  1108.     set_global_b_val_ptr(VAL_CWD, NULL);    /* current directory */
  1109.     set_global_b_val_ptr(VAL_TAGS, strmalloc("tags")); /* tags filename */
  1110.  
  1111.     /* suffixes for C mode */
  1112.     rp = (struct regexval *)malloc(sizeof (struct regexval));
  1113.     set_global_b_val_rexp(VAL_CSUFFIXES, rp);
  1114.     rp->pat = strmalloc("\\.[chs]$");
  1115.     rp->reg = regcomp(rp->pat, TRUE);
  1116.  
  1117.     /* where do paragraphs start? */
  1118.     rp = (struct regexval *)malloc(sizeof (struct regexval));
  1119.     set_global_b_val_rexp(VAL_PARAGRAPHS, rp);
  1120.     rp->pat = 
  1121.         strmalloc("^\\.[ILPQ]P\\s\\|^\\.P\\s\\|^\\.LI\\s\\|\
  1122. ^\\.[plinb]p\\s\\|^\\.\\?\\s$");
  1123.     rp->reg = regcomp(rp->pat, TRUE);
  1124.  
  1125.     /* where do comments start and end, for formatting them */
  1126.     rp = (struct regexval *)malloc(sizeof (struct regexval));
  1127.     set_global_b_val_rexp(VAL_COMMENTS, rp);
  1128.     rp->pat = 
  1129.         strmalloc("^\\s/\\?[#*>]\\+/\\?\\s$");
  1130.     rp->reg = regcomp(rp->pat, TRUE);
  1131.  
  1132.     /* where do sections start? */
  1133.     rp = (struct regexval *)malloc(sizeof (struct regexval));
  1134.     set_global_b_val_rexp(VAL_SECTIONS, rp);
  1135.     rp->pat = strmalloc("^[{\014]\\|^\\.[NS]H\\s\\|^\\.HU\\?\\s\\|\
  1136. ^\\.[us]h\\s\\|^+c\\s");
  1137.     rp->reg = regcomp(rp->pat, TRUE);
  1138.  
  1139.     /* where do sentences start? */
  1140.     rp = (struct regexval *)malloc(sizeof (struct regexval));
  1141.     set_global_b_val_rexp(VAL_SENTENCES, rp);
  1142.     rp->pat = strmalloc(
  1143.     "[.!?][])\"']* \\?$\\|[.!?][])\"']*  \\|^\\.[ILPQ]P\\s\\|\
  1144. ^\\.P\\s\\|^\\.LI\\s\\|^\\.[plinb]p\\s\\|^\\.\\?\\s$");
  1145.     rp->reg = regcomp(rp->pat, TRUE);
  1146.  
  1147.     set_global_w_val(WMDLIST,FALSE); /* list-mode */
  1148.     set_global_w_val(WVAL_SIDEWAYS,0); /* list-mode */
  1149.     set_global_w_val(WVAL_FCOLOR,7); /* foreground color */
  1150.     set_global_w_val(WVAL_BCOLOR,0); /* background color */
  1151.  
  1152. }
  1153.  
  1154. #if UNIX || MSDOS
  1155. SIGT
  1156. catchintr(signo)
  1157. int signo;
  1158. {
  1159.     interrupted = TRUE;
  1160. #if USG || MSDOS
  1161.     signal(SIGINT,catchintr);
  1162. #endif
  1163.     SIGRET;
  1164. }
  1165. #endif
  1166.  
  1167. #if MSDOS
  1168. void
  1169. dos_crit_handler()
  1170. {
  1171.     _hardresume(_HARDERR_FAIL);
  1172. }
  1173. #endif
  1174.  
  1175. /* do number processing if needed */
  1176. void
  1177. do_num_proc(cp,fp,np)
  1178. int *cp, *fp, *np;
  1179. {
  1180.     register int c, f, n;
  1181.     register int    mflag;
  1182.  
  1183.     c = *cp;
  1184.     f = *fp;
  1185.     n = *np;
  1186.  
  1187.     if (iscntrl(c) || (c & (CTLA|CTLX|SPEC)))
  1188.         return;
  1189.     if ( isdigit(c) && c != '0' ) {
  1190.         f = TRUE;        /* there is a # arg */
  1191.         n = 0;            /* start with a zero default */
  1192.         mflag = 1;        /* current minus flag */
  1193.         while (isdigit(c) || (c == '-')) {
  1194.             if (c == '-') {
  1195.                 /* already hit a minus or digit? */
  1196.                 if ((mflag == -1) || (n != 0))
  1197.                     break;
  1198.                 mflag = -1;
  1199.             } else {
  1200.                 n = n * 10 + (c - '0');
  1201.             }
  1202.             if ((n == 0) && (mflag == -1))    /* lonely - */
  1203.                 mlwrite("arg:");
  1204.             else
  1205.                 mlwrite("arg: %d",n * mflag);
  1206.  
  1207.             c = kbd_seq();    /* get the next key */
  1208.         }
  1209.         n = n * mflag;    /* figure in the sign */
  1210.     }
  1211.     *cp = c;
  1212.     *fp = f;
  1213.     *np = n;
  1214. }
  1215.  
  1216. /* do ^U-style repeat argument processing -- vile binds this to 'K' */
  1217. void
  1218. do_rept_arg_proc(cp,fp,np)
  1219. int *cp, *fp, *np;
  1220. {
  1221.     register int c, f, n;
  1222.     register int    mflag;
  1223.     c = *cp;
  1224.  
  1225.     if (c != reptc) 
  1226.         return;
  1227.  
  1228.     f = TRUE;
  1229.     n = 4;                /* with argument of 4 */
  1230.     mflag = 0;            /* that can be discarded. */
  1231.     mlwrite("arg: 4");
  1232.     while (isdigit(c=kbd_seq()) || c==reptc || c=='-'){
  1233.         if (c == reptc)
  1234.             if ((n > 0) == ((n*4) > 0))
  1235.                 n = n*4;
  1236.             else
  1237.                 n = 1;
  1238.         /*
  1239.          * If dash, and start of argument string, set arg.
  1240.          * to -1.  Otherwise, insert it.
  1241.          */
  1242.         else if (c == '-') {
  1243.             if (mflag)
  1244.                 break;
  1245.             n = 0;
  1246.             mflag = -1;
  1247.         }
  1248.         /*
  1249.          * If first digit entered, replace previous argument
  1250.          * with digit and set sign.  Otherwise, append to arg.
  1251.          */
  1252.         else {
  1253.             if (!mflag) {
  1254.                 n = 0;
  1255.                 mflag = 1;
  1256.             }
  1257.             n = 10*n + c - '0';
  1258.         }
  1259.         mlwrite("arg: %d", (mflag >=0) ? n : (n ? -n : -1));
  1260.     }
  1261.     /*
  1262.      * Make arguments preceded by a minus sign negative and change
  1263.      * the special argument "^U -" to an effective "^U -1".
  1264.      */
  1265.     if (mflag == -1) {
  1266.         if (n == 0)
  1267.             n++;
  1268.         n = -n;
  1269.     }
  1270.  
  1271.     *cp = c;
  1272.     *fp = f;
  1273.     *np = n;
  1274. }
  1275.  
  1276.  
  1277. /* write all _changed_ buffers */
  1278. int
  1279. writeall(f,n)
  1280. int f,n;
  1281. {
  1282.     register BUFFER *bp;    /* scanning pointer to buffers */
  1283.     register BUFFER *oldbp; /* original current buffer */
  1284.     register int status = TRUE;
  1285.     int count = 0;
  1286.  
  1287.     oldbp = curbp;                /* save in case we fail */
  1288.  
  1289.     bp = bheadp;
  1290.     while (bp != NULL) {
  1291.         if ((bp->b_flag&BFCHG) != 0 && (bp->b_flag&BFINVS) == 0) {
  1292.             make_current(bp);
  1293.             mlforce("[Saving %s]",bp->b_fname);
  1294.             mlforce("\n");
  1295.             if ((status = filesave(f, n)) != TRUE)
  1296.                 break;
  1297.             count++;
  1298.             mlforce("\n");
  1299.         }
  1300.         bp = bp->b_bufp;    /* on to the next buffer */
  1301.     }
  1302.     make_current(oldbp);
  1303.     mlforce("\n");
  1304.     if (status != TRUE) {
  1305.         pressreturn();
  1306.         sgarbf = TRUE;
  1307.     } else {
  1308.         sgarbf = TRUE;
  1309.         mlwrite("[Wrote %d buffer%c]",count,(count==1)?' ':'s');
  1310.     }
  1311.     return status;
  1312. }
  1313.  
  1314. /* the vi ZZ command -- write all, then quit */
  1315. int
  1316. zzquit(f,n)
  1317. int f,n;
  1318. {
  1319.     int thiscmd;
  1320.     int cnt;
  1321.  
  1322.     thiscmd = lastcmd;
  1323.     cnt = anycb();
  1324.     if (cnt) {
  1325.         mlprompt("Will write %d buffer%c  %s ",
  1326.             cnt, cnt > 1 ? 's':'.',
  1327.             clexec ? "" : "Repeat command to continue.");
  1328.         if (!clexec && !isnamedcmd) {
  1329.             if (thiscmd != kbd_seq())
  1330.                 return FALSE;
  1331.         }
  1332.  
  1333.         if (writeall(TRUE,1) != TRUE)
  1334.             return FALSE;
  1335.  
  1336.     } else if (!clexec && !isnamedcmd) {
  1337.         /* consume the next char. anyway */
  1338.         if (thiscmd != kbd_seq())
  1339.             return FALSE;
  1340.     }
  1341.     quithard(f, n);
  1342.     return TRUE;
  1343. }
  1344.  
  1345. /*
  1346.  * Fancy quit command, as implemented by Norm. If the any buffer has
  1347.  * changed do a write on that buffer and exit, otherwise simply exit.
  1348.  */
  1349. int
  1350. quickexit(f, n)
  1351. int f,n;
  1352. {
  1353.     if (writeall(TRUE,1) == TRUE)
  1354.         quithard(f, n);     /* conditionally quit    */
  1355.     return TRUE;
  1356. }
  1357.  
  1358. /* Force quit by giving argument */
  1359. /* ARGSUSED */
  1360. int
  1361. quithard(f,n)
  1362. int f,n;
  1363. {
  1364.     return quit(TRUE,1);
  1365. }
  1366.  
  1367. /*
  1368.  * Quit command. If an argument, always quit. Otherwise confirm if a buffer
  1369.  * has been changed and not written out.
  1370.  */
  1371. /* ARGSUSED */
  1372. int
  1373. quit(f, n)
  1374. int f,n;
  1375. {
  1376.     int cnt;
  1377.         
  1378.     if (f == FALSE && (cnt = anycb()) != 0) {
  1379.         if (cnt == 1)
  1380.             mlforce(
  1381.             "There is an unwritten modified buffer.  Write it, or use :q!");
  1382.         else
  1383.             mlforce(
  1384.             "There are %d unwritten modified buffers.  Write them, or use :q!",
  1385.                 cnt);
  1386.         return FALSE;
  1387.     }
  1388.     vttidy(TRUE);
  1389. #if    FILOCK
  1390.     if (lockrel() != TRUE) {
  1391.         exit(1);
  1392.         /* NOTREACHED */
  1393.     }
  1394. #endif
  1395.     exit(GOOD);
  1396.     /* NOTREACHED */
  1397.     return FALSE;
  1398. }
  1399.  
  1400. /* ARGSUSED */
  1401. int
  1402. writequit(f,n)
  1403. int f,n;
  1404. {
  1405.     int s;
  1406.     s = filesave(FALSE,n);
  1407.     if (s != TRUE)
  1408.         return s;
  1409.     return quit(FALSE,n);
  1410. }
  1411.  
  1412. /*
  1413.  * Abort.
  1414.  * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
  1415.  * Sometimes called as a routine, to do general aborting of stuff.
  1416.  */
  1417. /* ARGSUSED */
  1418. int
  1419. esc(f, n)
  1420. int f,n;
  1421. {
  1422.     TTbeep();
  1423.     dotcmdmode = STOP;
  1424.     fulllineregions = FALSE;
  1425.     doingopcmd = FALSE;
  1426.     opcmd = 0;
  1427.     mlforce("[Aborted]");
  1428.     return ABORT;
  1429. }
  1430.  
  1431. /* tell the user that this command is illegal while we are in
  1432.    VIEW (read-only) mode                */
  1433.  
  1434. int
  1435. rdonly()
  1436. {
  1437.     TTbeep();
  1438.     mlforce("[No changes are allowed while in \"view\" mode]");
  1439.     return FALSE;
  1440. }
  1441.  
  1442. /* ARGSUSED */
  1443. int
  1444. showversion(f,n)
  1445. int f,n;
  1446. {
  1447.     mlforce(version);
  1448.     return TRUE;
  1449. }
  1450.  
  1451. /* ARGSUSED */
  1452. int
  1453. unimpl(f,n)
  1454. int f,n;
  1455. {
  1456.     TTbeep();
  1457.     mlforce("[Sorry, that vi command is unimplemented in vile ]");
  1458.     return FALSE;
  1459. }
  1460.  
  1461. int opercopy(f,n) int f,n; { return unimpl(f,n); }
  1462. int opermove(f,n) int f,n; { return unimpl(f,n); }
  1463. int opertransf(f,n) int f,n; { return unimpl(f,n); }
  1464.  
  1465. int operglobals(f,n) int f,n; { return unimpl(f,n); }
  1466. int opervglobals(f,n) int f,n; { return unimpl(f,n); }
  1467.  
  1468. int map(f,n) int f,n; { return unimpl(f,n); }
  1469. int unmap(f,n) int f,n; { return unimpl(f,n); }
  1470.  
  1471. int source(f,n) int f,n; { return unimpl(f,n); }
  1472.  
  1473. int visual(f,n) int f,n; { return unimpl(f,n); }
  1474. int ex(f,n) int f,n; { return unimpl(f,n); }
  1475.  
  1476. /* ARGSUSED */
  1477. int
  1478. nullproc(f,n)    /* user function that does (almost) NOTHING */
  1479. int f,n;
  1480. {
  1481.     return TRUE;
  1482. }
  1483.  
  1484. void
  1485. cntl_af()    /* dummy function for binding to control-a prefix */
  1486. {
  1487. }
  1488.  
  1489. void
  1490. cntl_xf()    /* dummy function for binding to control-x prefix */
  1491. {
  1492. }
  1493.  
  1494. void
  1495. unarg() /* dummy function for binding to universal-argument */
  1496. {
  1497. }
  1498.  
  1499. /* initialize our version of the "chartypes" stuff normally in ctypes.h */
  1500. void
  1501. charinit()
  1502. {
  1503.     register int c;
  1504.  
  1505.     /* legal in pathnames */
  1506.     _chartypes_['.'] = 
  1507.         _chartypes_['_'] = 
  1508.         _chartypes_['-'] =
  1509.         _chartypes_['*'] = 
  1510.         _chartypes_['/'] = _pathn;
  1511.  
  1512.     /* legal in "identifiers" */
  1513.     _chartypes_['_'] |= _ident|_qident;
  1514.     _chartypes_[':'] |= _qident;
  1515.  
  1516.     /* whitespace */
  1517.     _chartypes_[' '] =
  1518.         _chartypes_['\t'] = 
  1519.         _chartypes_['\r'] =
  1520.         _chartypes_['\n'] = 
  1521.         _chartypes_['\f'] = _space;
  1522.  
  1523.     /* control characters */
  1524.     for (c = 0; c < ' '; c++)
  1525.         _chartypes_[c] |= _cntrl;
  1526.     _chartypes_[127] |= _cntrl;
  1527.  
  1528.     /* lowercase */
  1529.     for (c = 'a'; c <= 'z'; c++)
  1530.         _chartypes_[c] |= _lower|_pathn|_ident|_qident;
  1531.  
  1532.     /* uppercase */
  1533.     for (c = 'A'; c <= 'Z'; c++)
  1534.         _chartypes_[c] |= _upper|_pathn|_ident|_qident;
  1535.  
  1536.     /* digits */
  1537.     for (c = '0'; c <= '9'; c++)
  1538.         _chartypes_[c] |= _digit|_pathn|_ident|_qident|_linespec;
  1539.  
  1540.     /* punctuation */
  1541.     for (c = '!'; c <= '/'; c++)
  1542.         _chartypes_[c] |= _punct;
  1543.     for (c = ':'; c <= '@'; c++)
  1544.         _chartypes_[c] |= _punct;
  1545.     for (c = '['; c <= '`'; c++)
  1546.         _chartypes_[c] |= _punct;
  1547.     for (c = '{'; c <= '~'; c++)
  1548.         _chartypes_[c] |= _punct;
  1549.  
  1550.     /* printable */
  1551.     for (c = ' '; c <= '~'; c++)
  1552.         _chartypes_[c] |= _print;
  1553.  
  1554.     /* backspacers: ^H, rubout, and the user's backspace char */
  1555.     /* we'll add the user's char later */
  1556.     _chartypes_['\b'] |= _bspace;
  1557.     _chartypes_[127] |= _bspace;
  1558.  
  1559.     /* wildcard chars for most shells */
  1560.     _chartypes_['*'] |= _wild;
  1561.     _chartypes_['?'] |= _wild;
  1562.     _chartypes_['~'] |= _wild;
  1563.     _chartypes_['['] |= _wild;
  1564.     _chartypes_[']'] |= _wild;
  1565.     _chartypes_['$'] |= _wild;
  1566.     _chartypes_['{'] |= _wild;
  1567.     _chartypes_['}'] |= _wild;
  1568.     _chartypes_['`'] |= _wild;
  1569.  
  1570.     /* ex mode line specifiers */
  1571.     _chartypes_[','] |= _linespec;
  1572.     _chartypes_['%'] |= _linespec;
  1573.     _chartypes_['-'] |= _linespec;
  1574.     _chartypes_['+'] |= _linespec;
  1575.     _chartypes_['.'] |= _linespec;
  1576.     _chartypes_['$'] |= _linespec;
  1577.     _chartypes_['\''] |= _linespec;
  1578.  
  1579.     /* fences */
  1580.     _chartypes_['('] |= _fence;
  1581.     _chartypes_[')'] |= _fence;
  1582.     _chartypes_['['] |= _fence;
  1583.     _chartypes_[']'] |= _fence;
  1584.     _chartypes_['{'] |= _fence;
  1585.     _chartypes_['}'] |= _fence;
  1586.  
  1587.     for (c = 0; c < N_chars; c++)
  1588.             if ((_chartypes_[c] & _space) == 0)
  1589.                     _chartypes_[c] |= _nonspace;
  1590.  
  1591. }
  1592.  
  1593.  
  1594. /*****        Compiler specific Library functions    ****/
  1595.  
  1596. #if    MWC86 & MSDOS
  1597. movmem(source, dest, size)
  1598. char *source;    /* mem location to move memory from */
  1599. char *dest;    /* memory location to move text to */
  1600. int size;    /* number of bytes to move */
  1601. {
  1602.     register int i;
  1603.  
  1604.     for (i=0; i < size; i++)
  1605.         *dest++ = *source++;
  1606. }
  1607. #endif
  1608.  
  1609. #if    (AZTEC || TURBO || LATTICE || ZTC) && MSDOS
  1610. /*    strncpy:    copy a string...with length restrictions
  1611.             ALWAYS null terminate
  1612. Hmmmm...
  1613. I don't know much about DOS, but I do know that strncpy shouldn't ALWAYS
  1614.     null terminate.  -pgf
  1615. */
  1616.  
  1617. char *strncpy(dst, src, maxlen)
  1618. char *dst;    /* destination of copied string */
  1619. char *src;    /* source */
  1620. int maxlen;    /* maximum length */
  1621. {
  1622.     char *dptr;    /* ptr into dst */
  1623.  
  1624.     dptr = dst;
  1625.     while (*src && (maxlen-- > 0))
  1626.         *dptr++ = *src++;
  1627.     *dptr = 0;
  1628.     return dst;
  1629. }
  1630. #endif
  1631.  
  1632. #if    RAMSIZE & LATTICE & MSDOS
  1633. /*    These routines will allow me to track memory usage by placing
  1634.     a layer on top of the standard system malloc() and free() calls.
  1635.     with this code defined, the environment variable, $RAM, will
  1636.     report on the number of bytes allocated via malloc.
  1637.  
  1638.     with SHOWRAM defined, the number is also posted on the
  1639.     end of the bottom mode line and is updated whenever it is changed.
  1640. */
  1641.  
  1642. #undef    malloc
  1643. #undef    free
  1644.  
  1645. char *allocate(nbytes)    /* allocate nbytes and track */
  1646. unsigned nbytes;    /* # of bytes to allocate */
  1647. {
  1648.     char *mp;    /* ptr returned from malloc */
  1649.  
  1650.     mp = malloc(nbytes);
  1651.     if (mp) {
  1652.         envram += nbytes;
  1653. #if    RAMSHOW
  1654.         dspram();
  1655. #endif
  1656.     }
  1657.  
  1658.     return mp;
  1659. }
  1660.  
  1661. release(mp)    /* release malloced memory and track */
  1662. char *mp;    /* chunk of RAM to release */
  1663. {
  1664.     unsigned *lp;    /* ptr to the long containing the block size */
  1665.  
  1666.     if (mp) {
  1667.         lp = ((unsigned *)mp) - 1;
  1668.  
  1669.         /* update amount of ram currently malloced */
  1670.         envram -= (long)*lp - 2;
  1671.         free(mp);
  1672. #if    RAMSHOW
  1673.         dspram();
  1674. #endif
  1675.     }
  1676. }
  1677.  
  1678. #if    RAMSHOW
  1679. dspram()    /* display the amount of RAM currently malloced */
  1680. {
  1681.     char mbuf[20];
  1682.     char *sp;
  1683.  
  1684.     TTmove(term.t_nrow - 1, 70);
  1685. #if    COLOR
  1686.     TTforg(7);
  1687.     TTbacg(0);
  1688. #endif
  1689.     lsprintf(mbuf, "[%ld]", envram);
  1690.     sp = &mbuf[0];
  1691.     while (*sp)
  1692.         TTputc(*sp++);
  1693.     TTmove(term.t_nrow, 0);
  1694.     movecursor(term.t_nrow, 0);
  1695. }
  1696. #endif
  1697. #endif
  1698.  
  1699. #if MALLOCDEBUG
  1700. mallocdbg(f,n)
  1701. {
  1702.     int lvl;
  1703.     lvl = malloc_debug(n);
  1704.     mlwrite("malloc debug level was %d",lvl);
  1705.     if (!f) {
  1706.         malloc_debug(lvl);
  1707.     } else if (n > 2) {
  1708.         malloc_verify();
  1709.     }
  1710.     return TRUE;
  1711. }
  1712. #endif
  1713.  
  1714.  
  1715. /*
  1716.  *    the log file is left open, unbuffered.  thus any code can do 
  1717.  
  1718.      extern FILE *FF;
  1719.     fprintf(FF, "...", ...);
  1720.     
  1721.  *    to log events without disturbing the screen
  1722.  */
  1723.  
  1724. #ifdef DEBUGLOG
  1725. /* suppress the declaration so that the link will fail if someone uses it */
  1726. FILE *FF;
  1727. #endif
  1728.  
  1729. void
  1730. start_debug_log(ac,av)
  1731. int ac;
  1732. char **av;
  1733. {
  1734. #ifdef DEBUGLOG
  1735.     int i;
  1736.     FF = fopen("vilelog", "w");
  1737.     setbuf(FF,NULL);
  1738.     for (i = 0; i < ac; i++)
  1739.         fprintf(FF,"arg %d: %s\n",i,av[i]);
  1740. #endif
  1741. }
  1742.