home *** CD-ROM | disk | FTP | other *** search
/ Carousel Volume 2 #1 / carousel.iso / mactosh / code / microema.sit / src / main.c < prev    next >
Encoding:
Text File  |  1989-06-09  |  54.7 KB  |  1,640 lines  |  [TEXT/Earl]

  1. /*
  2.  *    MicroEMACS 3.9
  3.  *            written by Dave G. Conroy.
  4.  *            substatially modified by Daniel M. Lawrence
  5.  *
  6.  *    (C)opyright 1987 by Daniel M. Lawrence
  7.  *    MicroEMACS 3.9 can be copied and distributed freely for any
  8.  *    non-commercial purposes. MicroEMACS 3.9 can only be incorporated
  9.  *    into commercial software with the permission of the current author.
  10.  *
  11.  * This file contains the main driving routine, and some keyboard processing
  12.  * code, for the MicroEMACS screen editor.
  13.  *
  14.  * REVISION HISTORY:
  15.  *
  16.  * 1.0    Steve Wilhite, 30-Nov-85
  17.  *    - Removed the old LK201 and VT100 logic. Added code to support the
  18.  *      DEC Rainbow keyboard (which is a LK201 layout) using the the Level
  19.  *      1 Console In ROM INT. See "rainbow.h" for the function key defs
  20.  *    Steve Wilhite, 1-Dec-85
  21.  *    - massive cleanup on code in display.c and search.c
  22.  *
  23.  * 2.0    George Jones, 12-Dec-85
  24.  *    - Ported to Amiga.
  25.  *
  26.  * 3.0    Daniel Lawrence, 29-Dec-85
  27.  *    - rebound keys/added new fast buffered I/O for AMIGA
  28.  *    - added META- repeat commands
  29.  *    - added reposition default to center screen (yeah!)
  30.  *    - changed exit with modified buffers message
  31.  *    - made filesave tell us what it is doing
  32.  *    - changed search string entry to terminate with <ESC>
  33.  *      so we can use <NL> in search/replace strings
  34.  *    - updated version number in mode line to 3.0
  35.  *    12-Jan-86
  36.  *    - Added code to reconize the search/replace functions
  37.  *    - Added code to perform search/replace & query functions
  38.  *    14-Jan-86
  39.  *    - moved search logic to separate function in search.c
  40.  *    - added replace and query replace functions
  41.  *    - separated out control key expansions to be used by others in search.c
  42.  *    15-Jan-86
  43.  *    - changed "visiting" to finding
  44.  *    - changed yes/no responses to not need return
  45.  *    - cleaned up various messages
  46.  *    16-jan-86
  47.  *    - fixed spurious spawn message in MSDOS
  48.  *    - added ^X-S synonym to save command
  49.  *    - moved escape to shell to ^X-C
  50.  *    21-jan-86
  51.  *    - added code to suspend shell under BSD
  52.  *    22-jan-86
  53.  *    - added function key support (SPEC) under MSDOS
  54.  *    - Abort now prints [Aborted] on message line
  55.  *    23-jan-86
  56.  *    - Added modes and commands to set/unset them
  57.  *    24-jan-86
  58.  *    - Added Goto Line command
  59.  *    - added Rename Buffer command
  60.  *    28-jan-86
  61.  *    - added goto beginning and end of paragraph commands (META-P/META-N)
  62.  *    - re-wrote kdelete to use realloc. Gained MUCH speed here when
  63.  *      doing large wipes on both UNIX and MSDOS. Changed kill buffer
  64.  *      allocation block size from 256 bytes to 1 k
  65.  *    29-jan-86
  66.  *    - moved extern function declarations to efunc.h
  67.  *    - made name[] name binding table
  68.  *    30-jan-86
  69.  *    - fixed Previous/Next paragraph command not to wrap around EOF
  70.  *    - added Fill Paragraph command (META-Q)
  71.  *    4-feb-86
  72.  *    - added code to properly display long lines, scrolling them right
  73.  *      to left
  74.  *    5-feb-85
  75.  *    - rewrote code to right/left scroll...much better
  76.  *    - added shifted arrow keys on IBMPC
  77.  *    6-feb-85
  78.  *    - add option to allow forward-word to jump to beginning of
  79.  *      next word instead of end of current one. This is different from
  80.  *      other emacs' but can be configured off in estruct.h
  81.  *    - added VIEW mode to allow a buffer to be read only
  82.  *       (-v switch on command line will activate this)
  83.  *    - changed quick exit to write out ALL changed buffers!!!
  84.  *      MAKE SURE YOU KNOW THIS WHEN META-Zing
  85.  *    10-feb-86
  86.  *    - added handling of lines longer than allowed on file read in
  87.  *      (they wrap on additional lines)
  88.  *    - made having space clear the message line and NOT insert itself
  89.  *      a configuration option in ed.h
  90.  *    11-feb-86
  91.  *    - added Describe-command and Help commands.
  92.  *    13-feb-86
  93.  *    - added View file command (^X ^V) and finished HELP command
  94.  *    14-feb-86
  95.  *    - added option to let main loop skip update if type ahead commands
  96.  *       are queued up
  97.  *    16-feb-86
  98.  *    - added Insert File command
  99.  *    17-feb-86
  100.  *    - added scroll next window up/down commands
  101.  *    18-feb-86
  102.  *    - added CMODE indentation
  103.  *    - re-arranged header files to standardize extern and global
  104.  *      definitions
  105.  *    - changed version number to 3.2
  106.  *    - added numeric arguments to search, reverse search and
  107.  *      search and replace
  108.  *    24-feb-86
  109.  *    - added Bind To Key function (^C for now) to allow the user
  110.  *      to change his command keys
  111.  *    - added Unbind key function (M-^C for now)
  112.  *    - added execute named command to execute unbound commands (M-X)
  113.  *    - added describe bindings command (not bound)
  114.  *    - changed version number to 3.3
  115.  *    25-feb-86
  116.  *    - scrapped CERROR mode (too many compilers)
  117.  *    - added EXACT mode for case sensitive searchers
  118.  *    26-feb-86
  119.  *    - added command completion on execute named command and
  120.  *      all routined grabbing a command name
  121.  *    - adding execute-command-line command and its support functions
  122.  *      (in preparation for sourcing files)
  123.  *    - added Execute Buffer command
  124.  *    27-feb-86
  125.  *    - added execute(source) file command and added code to automatically
  126.  *      execute emacs.rc (or .emacsrc on UNIX) before initial read in
  127.  *    - changed version number to 3.4
  128.  *    4-mar-86
  129.  *    - changed word delete to be consistant with word move (it gets
  130.  *      rid of the inter word space now) This is configurable with the
  131.  *      NFWORD symbol in estruct.h
  132.  *    - added B_ACTIVE entry to the buffer table. Let emacs read multiple
  133.  *      file names from the command line and only read them in as needed
  134.  *    5-mar-85
  135.  *    - rewrote command line parser to get rid of my patchy code
  136.  *    - changed version number to 3.5
  137.  *    1-apr-86
  138.  *    - added support for Aztec C 3.20e under MSDOS
  139.  *    - fixed bug in mlwrite on ADM3's and their ilk under V7
  140.  *    - added insertion of pounds in column one under CMODE
  141.  *    - changed version number to 3.6
  142.  *    3-apr-86
  143.  *    - added next-buffer command (^X-X)
  144.  *    5-apr-86
  145.  *    - added kill paragraph command (M-^W)
  146.  *    - changed fill-paragraph to leave 2 spaces after a period at the
  147.  *      end of a word.
  148.  *    - added OVERWRITE mode
  149.  *    7-apr-86
  150.  *    - fixed overwrite mode to handle tabs
  151.  *    8-apr-86
  152.  *    - added add/delete global mode (<ESC>M & <ESC> ^M) commands
  153.  *    9-apr-86
  154.  *    - added insert space command
  155.  *    - moved bindings around     ^C    insert space
  156.  *                    M-K    bind-to-key
  157.  *                    INSERT    insert space
  158.  *                    DELETE    forwdel
  159.  *    - added hunt forward and hunt reverse commands
  160.  *    10-apr-86
  161.  *    - fixed bug in DOBUF with non-terminated command string
  162.  *    15-apr-86
  163.  *    - fixed tab expansion bug in DISPLAY which hung the AMIGA
  164.  *      (sent in by Dawn Banks)
  165.  *    - fixed curcol problen if forwline/backline during keyboard
  166.  *      macro execution (sent in by Ernst Christen)
  167.  *    - added AMIGA function/cursor key support
  168.  *    - fixed nonterminating <NL> replacement bug
  169.  *    - fixed word wrapping problems
  170.  *    16-apr-86
  171.  *    - updated documentation and froze development for 3.6 net release
  172.  *    23-apr-86    version 3.6a
  173.  *    - added foreground and background colors. Setable with the
  174.  *      add mode commands for the moment
  175.  *    24-apr-86
  176.  *    - added command to pipe CLI output to a buffer
  177.  *    25-apr-86
  178.  *    - added Dana Hoggatt's code to replace Lattice's sick system()
  179.  *      function. Now we no longer care what the switchar is.
  180.  *    - cleaned up the positioning on several of the spawing commands
  181.  *    26-apr-86
  182.  *    - added an output flush in vttidy(). Unix really appreciates this.
  183.  *    - added filter-buffer (^X#) command to send a buffer through
  184.  *      a DOS filter
  185.  *    - made automatic CMODE on .c and .h file compilation dependant
  186.  *      in estruct.h
  187.  *    1-may-86
  188.  *    - optimized some code in update(). It certainly need a lot more.
  189.  *    - added Aztec profiling capabilities. These are conditional on
  190.  *      the APROF symbol in estruct.h
  191.  *    2-may-86
  192.  *    - added (u)ndo command in query-replace. undoes last repalce.
  193.  *    6-may-86
  194.  *    - re-organized and wrote the update() function in display.c
  195.  *      Now my color hacks are in the right places and the code can be
  196.  *      understood.
  197.  *    [Released version 3.6f for BETA test sites]
  198.  *    8-may-86
  199.  *    - fixed bug in new display routine to wrap cursor on extended
  200.  *      lines at the right time
  201.  *    - modified the buffer-position command to give reasonable info
  202.  *    9-may-86
  203.  *    - improved the word wrap algorithm as not to discard non-space
  204.  *      delimiters. The backscan now looks for white space rather than
  205.  *      !inword().
  206.  *    [Released version 3.6g to Krannert]
  207.  *    10-may-86
  208.  *    - Added IBMPC.C an IBM-PC specific display driver. This makes paging
  209.  *      4-6 times faster. Also made some conditional changes to DISPLAY.C
  210.  *      to eliminate the pscreen[] if using the PC driver.
  211.  *    [changed version number to 3.6i]
  212.  *    12-may-86
  213.  *    - added delete-window (^X 0) command to dispose of a single window
  214.  *    - fixed problem with multiple prefixes from a command line which
  215.  *      was reported by John Gamble
  216.  *    14-may-86
  217.  *    - Added Aztec support for the IBMPC display driver. Had to
  218.  *      readjust some includes and defines for this.
  219.  *    - fixed bug in delete-window.
  220.  *    - fixed some bizarre behavior with the cursor after coming back
  221.  *      from spawn calls.
  222.  *    [changed version number to 3.7 freezing development for net release]
  223.  *    15-may-86
  224.  *    - (that didn't last long...) Added execute-macro-(1 thru 20) commands
  225.  *      to execute macro buffers (named "[Macro nn]")
  226.  *    - changed BFTEMP to BFINVS and cleaned up treatment of invisible
  227.  *      buffers.
  228.  *    16-may-86
  229.  *    - added store-macro (unbound) to store any executed command lines to
  230.  *      macro buffer.
  231.  *    - added clear-message-line (unbound) command to do just that
  232.  *    - added resize-window command to change a window's size to the
  233.  *      specified argument
  234.  *    - improved help's logic not to re-read the file if it was already
  235.  *      in a buffer
  236.  *    - added MAGIC mode to all structures and command tables, but the
  237.  *      regular expression code that John Gamble is writing is not ready.
  238.  *    18-may-86
  239.  *    - added interactive prompt requests in command line execution (i.e.
  240.  *      while executing a macro, a parameter starting with an at sign (@)
  241.  *      causes emacs to prompt with the rest of the parameter and return
  242.  *      the resulting input as the value of the parameter).
  243.  *    - added arguments to split-current-window to force the cursor into
  244.  *      the upper or lower window.
  245.  *    20-may-86
  246.  *    - added support for the Microsoft C compiler as per the changes
  247.  *      sent in by Oliver Sharp
  248.  *    - made some upgrades and fixes for VMS sent in by Guy Streeter
  249.  *    21-may-86
  250.  *    - fixed an Aztec bug in ttgetc by clearing the upper byte
  251.  *    - fixed buf in CMODE with #preprocesser input (bug fix submitted by
  252.  *      Willis of unknown path)
  253.  *    - added support of alternative startup file ( @<filename> ) in
  254.  *      the command line
  255.  *    - added ^Q quoting in interactive input (mlreplyt()).
  256.  *    - added re-binding of meta-prefix and ctlx-prefix
  257.  *    22-may-86
  258.  *    - reorganized getkey routines to make more sense and let prefix
  259.  *      binding work properly.
  260.  *    23-may-86
  261.  *    - checked new code on BSD4.2 and made a few fixes
  262.  *    - added optional fence matching while in CMODE
  263.  *    - added goto and search command line arguments by Mike Spitzer
  264.  *    26-may-86
  265.  *    - added parameter fetching from buffers
  266.  *    27-may-86
  267.  *    - fixed some HP150 bugs......
  268.  *    31-may-86
  269.  *    - Added Wang PC keyboard support from modifications by
  270.  *      Sid Shapiro @ Wang Institute
  271.  *    - Fixed some reverse video bugs with code submitted by Peter Chubb
  272.  *    - Fixed bug in nextbuffer reported by Dave Forslund
  273.  *    - added system V support (USG) from Linwood Varney
  274.  *    2-jun-86
  275.  *    - changed defines to just define one Unix define (for example,
  276.  *      just define BSD for Unix BSD 4.2)
  277.  *    - Added Incremental search functions written by D. R. Banks
  278.  *      in file ISEARCH.C
  279.  *    - added insert-string (unbound) command to help the macro
  280.  *      language out.
  281.  *    - added unmark-buffer (M-~) command to turn off the current buffers
  282.  *      change flag
  283.  *    - fixed nxtarg to truncate strings longer than asked for max length
  284.  *    4-jun-86
  285.  *    - added special characters in command line tokens. Tilde (~) is
  286.  *      the special lead-in character for "nrtb".
  287.  *    - Fixed bad ifdef in Aztec code so it could look at HOME dir
  288.  *      for startup, help, and emacs.rc files
  289.  *    6-jun-86
  290.  *    - make delete word commands clear the kill buffer if not after another
  291.  *      kill command
  292.  *    11-jun-86
  293.  *    - made ~@ in string arguments pass as char(192) to nxtarg() so one can
  294.  *      quote @ at the beginning of string arguments
  295.  *    - changed buffer size vars in listbuffers() to long (for big files)
  296.  *    - re-wrote buffer-position command to be much faster
  297.  *    12-jun-86
  298.  *    - added count-words (M-^C) command to count the words/chars and
  299.  *      lines in a region
  300.  *    - changed regions so they could be larger than 65535 (short ->
  301.  *      long in the REGION structure)
  302.  *    - changed ldelete() and all callers to use a long size. The kill
  303.  *      buffer will still have a problem >65535 that can not be solved
  304.  *      until I restructure it.
  305.  *    - grouped paragraph commands and word count together under symbol
  306.  *      WORDPRO to allow them to be conditionally made (or not)
  307.  *    13-jun-86
  308.  *    - re-wrote kill buffer routines again. Now they support an unlimited
  309.  *      size kill buffer, and are (in theory) faster.
  310.  *    - changed delete-next-word (M-D) to not eat the newline after a word,
  311.  *      instead it checks and eats a newline at the cursor.
  312.  *    17-jun-86
  313.  *    - added numeric argument to next/previous-window to access the nth
  314.  *      window from the top/bottom
  315.  *    - added support for the Data General 10 MSDOS machine
  316.  *    - added save-window (unbound) and restore-window (unbound) commands
  317.  *      for the use of the menu script. Save-window remembers which window
  318.  *      is current, and restore-window returns the cursor to that window.
  319.  *    20-jun-86
  320.  *    - fixed a bug with the fence matching locking up near the beginning
  321.  *      of a buffer
  322.  *    - added argument to update to selectively force a complete update
  323.  *    - added update-screen (unbound) command so macros can force a
  324.  *      screen update
  325.  *    21-jun-86
  326.  *    - rearranged token() and nxtarg() calls so that command names and
  327.  *      repeat counts could also be prompted and fetched from buffers
  328.  *      [this broke later with the exec re-write....]
  329.  *    - added write-message (unbound) command to write out a message
  330.  *      on the message line (for macros)
  331.  *    - changed ifdef's so that color modes are recognized as legal in
  332.  *      b/w version, and simply do nothing (allowing us to use the same
  333.  *      script files)
  334.  *    [Released version 3.7 on July 1 to the net and elswhere]
  335.  *    2-jul-86
  336.  *    - Changed search string terminator to always be the meta character
  337.  *      even if it is rebound.
  338.  *    3-jul-86
  339.  *    - removed extra calls to set color in startup code. This caused the
  340.  *      original current window to always be the global colors.
  341.  *    7-jul-86
  342.  *    - Fixed bugs in mlreplyt() to work properly with all terminators
  343.  *      including control and spec characters
  344.  *    22-jul-86
  345.  *    - fixed replaces() so that it will return FALSE properly on the
  346.  *      input of the replacement string.
  347.  *    - added a definition for FAILED as a return type.....
  348.  *    - changed version number to 3.7b
  349.  *    23-jul-86
  350.  *    - fixed o -> 0 problem in TERMIO.C
  351.  *    - made ^U universal-argument re-bindable
  352.  *    - wrote atoi() for systems (like Aztec) where it acts strangely
  353.  *    - changed version number to 3.7c
  354.  *    25-jul-86
  355.  *    - make ^G abort-command rebindable
  356.  *    29-jul-86
  357.  *    - added HP110 Portable Computer support
  358.  *    - changed version number to 3.7d
  359.  *    30-jul-86
  360.  *    - Fixed a couple of errors in the new VMS code as pointer
  361.  *      out by Ken Shacklford
  362.  *    - split terminal open/close routines into screen and keyboard
  363.  *      open/close routines
  364.  *    - closed the keyboard during all disk I/O so that OS errors
  365.  *      can be respoded to correctly (especially on the HP150)
  366.  *    - changed version number to 3.7e
  367.  *    31-jul-86
  368.  *    - added label-function-key (unbound) command under symbol FLABEL
  369.  *      (primarily for the HP150)
  370.  *    4-aug-86
  371.  *    - added fixes for Microsoft C as suggested by ihnp4!ihuxm!gmd1
  372.  *        <<remember to fix [list] deletion bug as reported
  373.  *          by craig@hp-pcd>>
  374.  *    8-aug-86
  375.  *    - fixed beginning misspelling error everywhere
  376.  *    - fixed some more MSC errors
  377.  *    - changed version number to 3.7g
  378.  *    20-aug-86
  379.  *    - fixed CMODE .h scanning bug
  380.  *    - changed version number to 3.7h
  381.  *    30-aug-86
  382.  *    - fixed killing renamed [list] buffer (it can't) as submitted
  383.  *      by James Aldridge
  384.  *    - Added code to allow multiple lines to display during
  385.  *      vertical retrace
  386.  *      [total disaster....yanked it back out]
  387.  *    9-sep-86
  388.  *    - added M-A (apropos) command to list commands containing a substring.
  389.  *    - fixed an inefficiency in the display update code submitted
  390.  *      by William W. Carlson (wwc@pur-ee)
  391.  *    10-sep-86
  392.  *    - added Dana Hoggatt's code for encryption and spliced it into the
  393.  *      proper commands. CRYPT mode now triggers encryption.
  394.  *    - added -k flag to allow encryption key (no spaces) in command line
  395.  *    14-sep-86
  396.  *    - added missing lastflag/thisflag processing to docmd()
  397.  *    - changed version to 3.7i and froze for partial release via mail
  398.  *      and BBS
  399.  *    05-oct-86
  400.  *    - changed some strcpys in MAIN.C to strncpys as suggested by John
  401.  *      Gamble
  402.  *    - replaces SEARCH.C and ISEARCH.C with versions modified by
  403.  *      John Gamble
  404.  *    10-oct-86
  405.  *    - removed references to lflick....it just won't work that way.
  406.  *    - removed defines LAT2 and LAT3...the code no longer is Lattice
  407.  *      version dependant.
  408.  *    14-oct-86
  409.  *    - changed spawn so that it will not not pause if executed from
  410.  *      a command line
  411.  *    15-oct-86
  412.  *    - added argument concatination (+) to the macro parsing
  413.  *    - added [] as fence pairs
  414.  *    16-oct-86
  415.  *    - rewrote all macro line parsing routines and rearranged the
  416.  *      mlreply code. Saved 6K!!! Have blazed the path for expanding
  417.  *      the command language.
  418.  *    17-oct-86
  419.  *    - added new keyboard macro routines (plus a new level to the
  420.  *      input character function)
  421.  *    22-oct-86
  422.  *    - improved EGA cursor problems
  423.  *    - added -r (restricted) switch to command line for BBS use
  424.  *    06-nov-86
  425.  *    - fixed terminator declarations from char to int in getarg() and
  426.  *      nxtarg() in EXEC.C as pointed out by John Gamble
  427.  *    07-nov-86
  428.  *    - made wordrap() user callable as wrap-word (M-FNW) and changed
  429.  *      the getckey() routine so that illegal keystrokes (too many
  430.  *      prefixes set) could be used for internal bindings. When word
  431.  *      wrap conditions are met, the keystroke M-FNW is executed. Added
  432.  *      word wrap check/call to newline().
  433.  *    11-nov-86
  434.  *    - added and checked support for Mark Williams C 86
  435.  *    12-nov-86
  436.  *    - added goto-matching-fence (M-^F) command to jump to a matching
  437.  *      fence "({[]})" or beep if there is none. This can reframe the
  438.  *      screen.
  439.  *    - added code and structure elements to support change-screen-size
  440.  *      command (M-^S) to change the number of lines being used by
  441.  *      MicroEMACS.
  442.  *    15-nov-86
  443.  *    - finished debugging change-screen-size
  444.  *    17-nov-86
  445.  *    - Incorporated in James Turner's modifications for the Atari ST
  446.  *        23-sep-86
  447.  *        - added support for the Atari ST line of computers (jmt)
  448.  *          - added a '\r' to the end of each line on output and strip
  449.  *            it on input for the SHOW function from the desktop
  450.  *          - added 3 new mode functions (HIREZ, MEDREZ, and LOREZ);
  451.  *            chgrez routine in TERM structure; and MULTREZ define in
  452.  *            ESTRUCT.H to handle multiple screen resolutions
  453.  *    [note....ST still not running under Lattice yet...]
  454.  *    25-nov-86
  455.  *    - Made the filter-buffer (^X-#) command not work on VIEW mode
  456.  *      buffers
  457.  *    - Made the quick-exit (M-Z) command throw out a newline after
  458.  *      each message so they could be seen.
  459.  *    26-nov-86
  460.  *    - fixed a couple of bugs in change-screen-size (M-^S) command
  461.  *    - changed file read behavior on long lines and last lines
  462.  *      with no newline (it no longer throws the partial line out)
  463.  *    - [as suggested by Dave Tweten] Made adding a ^Z to the end
  464.  *      of an output file under MSDOS configurable under the
  465.  *      CTRL-Z symbol in ESTRUCT.H
  466.  *    - [Dave Tweten] Spawn will look up the "TMP" environment variable
  467.  *      for use during various pipeing commands.
  468.  *    - [Dave Tweten] changed pipe command under MSDOS to use '>>'
  469.  *      instead of '>'
  470.  *    04-dec-86
  471.  *    - moved processing of '@' and '#' so that they can be outside
  472.  *      the quotes in an argument, and added hooks to process '%' for
  473.  *      environment and user variables.
  474.  *    - modified IBMPC.C to sense the graphics adapter (CGA and MONO)
  475.  *      at runtime to cut down on the number of versions.
  476.  *    05-dec-86
  477.  *    - changed macro directive character to "!" instead of "$" (see
  478.  *      below) and fixed the standard .rc file to comply.
  479.  *    - added code to interpret environment variables ($vars). Added
  480.  *      hooks for built in functions (&func). So, to recap:
  481.  *
  482.  *        @<string>    prompt and return a string from the user
  483.  *        #<buffer name>    get the next line from a buffer and advance
  484.  *        %<var>        get user variable <var>
  485.  *        $<evar>     get environment variable <evar>
  486.  *        &<func>     evaluate function <func>
  487.  *
  488.  *    - allowed repeat counts to be any of the above
  489.  *    - added code to allow insert-string (unbound) to use its
  490.  *      repeat count properly
  491.  *    - added set (^X-A) command to set variables. Only works on
  492.  *      environmental vars yet.
  493.  *    9-dec-86
  494.  *    - added some code for user defined variables...more to come
  495.  *    - added options for malloc() memory pool tracking
  496.  *    - preliminary user variables (%) working
  497.  *    - changed terminal calls to macro's (to prepare for the new
  498.  *      terminal drivers)
  499.  *    15-dec-86
  500.  *    - changed previous-line (^P) and next-line (^N) to return a
  501.  *      FALSE at the end or beginning of the file so repeated
  502.  *      macros involving them terminate properly!
  503.  *    - added code for $CURCOL and $CURLINE
  504.  *    20-dec-86
  505.  *    - set (^X-A) now works with all vars
  506.  *    - added some new functions
  507.  *        &ADD &SUB &TIMES &DIV &MOD &NEG &CAT
  508.  *    - once again rearranged functions to control macro execution. Did
  509.  *      away with getarg()
  510.  *    23-dec-86
  511.  *    - added string functions
  512.  *        &LEFt &RIGht &MID
  513.  *    31-dec-86
  514.  *    - added many logical functions
  515.  *        &NOT &EQUal &LESs &GREater
  516.  *    - added string functions
  517.  *        &SEQual &SLEss &SGReater
  518.  *    - added variable indirection with &INDirect
  519.  *    - made fixes to allow recursive macro executions
  520.  *      (improved speed during macro execution as well)
  521.  *    3-jan-87
  522.  *    - added $FLICKER to control flicker supression
  523.  *    - made spawn commands restricted
  524.  *    - cleaned up lots of unintentional int<->char problems
  525.  *    4-jan-87
  526.  *    - Fixed broken pipe-command (^X-@) command under MSDOS
  527.  *    - added !IF  !ELSE  !ENDIF  directives and changed the
  528.  *      name of !END to !ENDM....real slick stuff
  529.  *    5-jan-87
  530.  *    - quick-exit (M-Z) aborts on any filewrite errors
  531.  *    8-jan-87
  532.  *    - debugged a lot of the new directive and evaluation code.
  533.  *      BEWARE of stack space overflows! (increasing stack to
  534.  *      16K under MSDOS)
  535.  *    - removed non-standard DEC Rainbow keyboard support...let someone
  536.  *      PLEASE implement this in the standard manner using key bindings
  537.  *      and send the results to me.
  538.  *    - added change-screen-width () command and $CURWIDTH variable
  539.  *    11-jan-87
  540.  *    - fixed an incredibly deeply buried bug in vtputc and combined
  541.  *      it with vtpute (saving about 200 bytes!)
  542.  *    16-jan-87
  543.  *    - added code to handle controlling multiple screen resolutions...
  544.  *      allowed the IBM-PC driver to force Mono or CGA modes.
  545.  *    - added current buffer name and filename variables
  546.  *      $cbufname and $cfname
  547.  *    18-jan-87
  548.  *    - added $sres variable to control screen resolution
  549.  *    - added $debug variable to control macro debugging code (no longer
  550.  *      is this activated by GLOBAL spell mode)
  551.  *    - fixed bug in -g command line option
  552.  *    - Released Version 3.8 to BBSNET
  553.  *    21-jan-87
  554.  *    - added $status variable to record return status of last command
  555.  *    2-feb-87
  556.  *    - added ATARI 1040 support...runs in all three modes right now
  557.  *    - added $palette var with palette value in it
  558.  *    - undefined "register" in BIND.C and INPUT.C for ST520 & LATTICE
  559.  *      to get around a nasty Lattice bug
  560.  *    4-feb-87
  561.  *    - added, debugged code for switching all 1040ST color modes, added
  562.  *      code for HIGH monochrome mode as well, DENSE still pending
  563.  *    5-feb-87
  564.  *    - with John Gamble, found and corrected the infamous bad matching
  565.  *      fence problems.
  566.  *    - added error return check in various add/delete mode commands
  567.  *    10-feb-87
  568.  *    - re-arrange code in docmd() so that labels are stored in
  569.  *      macro buffers
  570.  *    - fixed !RETURN to only return if (execlevel == 0) [If we are
  571.  *      currently executing]
  572.  *    14-feb-87
  573.  *    - added to outp() calls in the EGA driver to fix a bug in the BIOS
  574.  *    - adding code for 1040ST 40 line DENSE mode (not complete)
  575.  *    25-feb-87
  576.  *    - added auto-save "ASAVE" mode....variables $asave and $acount
  577.  *      control the frequency of saving and count until next save
  578.  *    - added &and and &or as functions for logical anding and oring
  579.  *    - added string length &LEN, upper and lower case string funtions
  580.  *      &LOWER and &UPPER
  581.  *    27-feb-87
  582.  *    - added $lastkey   last keystroke struck and
  583.  *        $curchar    character under cursor
  584.  *    28-feb-87
  585.  *    - added code for trim-line (^X^T) command and table entries
  586.  *      for the entab-line (^X^E) and detab-line (^X^D) commands.
  587.  *      These are conditional on AEDIT (Advanced editing) in estruct.h
  588.  *    18-mar-87
  589.  *    - finished above three commands
  590.  *    - added $version environment variable to return the current
  591.  *      MicroEMACS version number
  592.  *    - added $discmd emvironment variable. This is a logical flag that
  593.  *      indicates if emacs should be echoing commands on the command line.
  594.  *      real useful in order to stop flashing macros and .rc files
  595.  *    - added $progname environment variable. this always returns the
  596.  *      string "MicroEMACS". OEM's should change this so that macros can
  597.  *      tell if they are running on an unmodified emacs or not.
  598.  *    - fixed a minor bug in the CGA/MONO detection routine in IBMPC.C
  599.  *    20-mar-87
  600.  *    - integrated EGAPC.C into IBMPC.C and eliminated the file. Now an
  601.  *      EGA user can switch from EGA to CGA modes at will
  602.  *    - A LOT of little fixes and corrections sent in by John Ruply
  603.  *    25-mar-87
  604.  *    - Fixed buffer variables so they will work when referencing the
  605.  *      current buffer
  606.  *    26-mar-87
  607.  *    - Fixed atoi() to be more reasonable. trailing whitespace ignored,
  608.  *      only one leading sign, no non-digits allowed after the sign.
  609.  *    - fixed buffer variables to go from the point to the end of
  610.  *      line.
  611.  *    28-mar-87
  612.  *    - fixed bugs with 8 bit chars as submited by Jari Salminen
  613.  *    - replace AZTEC/MSDOS agetc() with a1getc() which won't strip
  614.  *      the high order bit
  615.  *    30-mar-87
  616.  *    - changed list-buffers (^X^B) so that with any argument, it will
  617.  *      also list the normally invisable buffers
  618.  *    - added store-procedure and execute-procedure/run (M-^E)
  619.  *      commands to store and execute named procedures.
  620.  *    31-mar-87
  621.  *    - Fixed infinite loop in ^X-X command (when [LIST] is the
  622.  *      only buffer left) as pointed out by John Maline
  623.  *    - made filenames in getfile() always lower case as pointed
  624.  *      out by John Maline
  625.  *    2-apr-87
  626.  *    - Fixed buffer variables so they would work on non-current displayed
  627.  *      buffers. They should now work with ALL buffers....
  628.  *    3-apr-87
  629.  *    - Yanked AZTEC profiling code....not very useful
  630.  *    - Modified IBMPC driver so it will not start in EGA mode
  631.  *    - allow the next-buffer (^X-X) command to have a preceding
  632.  *      non-negative argument.
  633.  *    14-apr-87
  634.  *    - added John Gamble's modified search.c. The code has cut apx
  635.  *      200-300 bytes off the executable.
  636.  *    - added the &RND function to generate a random integer between
  637.  *      1 and its arguments value. Also $SEED is availible as the
  638.  *      random number seed.
  639.  *    - changed the -k command line switch so if there is no argument,
  640.  *      it will prompt for one when the file is read
  641.  *    15-apr-87
  642.  *    - added 20 bytes of buffer in getval()'s local argument alloc so
  643.  *      when it returns a value, it has enough stack space to do at least
  644.  *      one strcpy() before stomping on the returned value. ALWAYS call
  645.  *      getval() ONLY from within a strcpy() call.
  646.  *    - made $curcol return a 1 based value instead of a zero based one.
  647.  *      [changed this back later for 3.8o   it was simply wrong.....]
  648.  *    16-apr-87
  649.  *    - re-wrote strncpy() for AZTEC & MSDOS so it null terminates the
  650.  *      string.
  651.  *    - changed pipe() to pipecmd() to avoid conflicts with various
  652.  *      UNIX systems
  653.  *    24-apr-87
  654.  *    - changed open parameters on AMIGA window open to 0/0/640/200
  655.  *    [Froze and released v3.8i via BBS net]
  656.  *    14-may-87
  657.  *    - added nop (M-FNC) that gets called on every command loop
  658.  *    - added $wline, returns and sets # lines in current window
  659.  *    - added $cwline, returns and set current line within window
  660.  *    - added $target, returns/sets target for line moves
  661.  *    - added $search, returns/sets default search string
  662.  *    - added $replace, returns/sets default replace string
  663.  *    - added $match, returns last matched string in magic search
  664.  *    29-may-87
  665.  *    - rewrote word deletes to not kill trailing non-whitespace after
  666.  *      the last word. Also a zero argument will cause it to just delete
  667.  *      the word and nothing else.
  668.  *    - more fixes for the search pattern environment variables
  669.  *    30-may-87
  670.  *    - forced all windows to redraw on a width change
  671.  *    2-jun-87
  672.  *    - forced clear-message-line to overide $discmd
  673.  *    - added mlforce() routine and call it in clear-message-line,
  674.  *      write-message and when $debug is TRUE
  675.  *    - recoded the startup sequence in main()....Much Better...
  676.  *    4-jun-87
  677.  *    - forced interactive arguments ( @"question" ) to ALWAYS be echoed
  678.  *      regardless of the setting of $discmd.
  679.  *    7-jun-87
  680.  *    - started adding support for Turbo C under MSDOS
  681.  *    11-jun-87
  682.  *    - words now include ONLY upper/lower case alphas and digits
  683.  *    - fixed some more bugs with the startup..(ORed in the global modes)
  684.  *    - took more limits off the self-insert list....
  685.  *    16-jun-87
  686.  *    - macro debugging now displays the name of the current macro.
  687.  *    - fixed a problem in expandp() in search.c that kept high-byte
  688.  *      characters from working in search strings
  689.  *    18-jun-87
  690.  *    - added &sindex <str1> <str2> function which searches for string 2
  691.  *      within string 1
  692.  *    [released verion 3.8o internally]
  693.  *    19-jun-87
  694.  *    - added $cmode and $gmode to return and set the mode of the
  695.  *      current buffer and the global mode
  696.  *    - separated findvar() out from setvar() so it could be used in
  697.  *      the !LOOP directive (which got canned....read on)
  698.  *    - %No such variable message now types the name of the offending
  699.  *      variable
  700.  *    22-jun-87
  701.  *    - fixed startup bug when editing the startup file
  702.  *    - added the !LOOP <var> <label> directive
  703.  *    26-jun-87
  704.  *    - dumped !LOOP......added !WHILE. This needed and caused a vaste
  705.  *      reorginization in exec.c which mainly involved moving all the
  706.  *      directive handling from docmd() to dobuf(), in the process
  707.  *      getting rid of a lot of junk and making the result smaller
  708.  *      than it started.....(yea!)
  709.  *    - added $tpause to control the fence flashing time in CMODE.
  710.  *      The value is machine dependant, but you can multiply the
  711.  *      original in macros to stay machine independant. (as
  712.  *      suggested by Baron O.A. Grey)
  713.  *    - added hook to execute M-FNR (null) during a file read, after
  714.  *      the name is set and right before the file is read. Took out
  715.  *      any auto-CMODE code, as this is now handled with a macro.
  716.  *      (also suggested by Baron O.A. Grey)
  717.  *    - Added Baron O.A. Grey's SYSTEM V typeahead() code...I hope
  718.  *      this works....if you check this out, drop me a line.
  719.  *    - Added new variable $pending, returns a logical telling if
  720.  *      a typed ahead character is pending.
  721.  *    29-jun-87
  722.  *    - Made adjustmode() use curbp-> instead of curwp->w_bufp-> which
  723.  *      fixed some bugs in the startup routines.
  724.  *    - added $lwidth to return the length of the current line
  725.  *    2-jul-87
  726.  *    - Added &env <str> which returns the value of the environment
  727.  *      variable <str> where possible
  728.  *    - Fixed a NASTY bug in execbuf()..the buffer for the name
  729.  *      of the buffer to execute was NBUFN long, and got overflowed
  730.  *      with a long interactive argument.
  731.  *    3-jul-87
  732.  *    - Moved the loop to match a key against its binding out of execute()
  733.  *      to getbind() so it could be used later elsewhere.
  734.  *    - Added &bind <keyname> which returns the function bound to the
  735.  *      named key
  736.  *    - changed execute-file to look in the executable path first...
  737.  *    6-jul-87
  738.  *    - changed $curchar to return a newline at the end of a line and
  739.  *      it no longer advances the cursor
  740.  *    - a lot of minor changes sent by various people....
  741.  *    7-jul-87
  742.  *    - some amiga specific fixes as suggested by Kenn Barry
  743.  *    - added $line [read/write] that contains the current line in the
  744.  *      current buffer
  745.  *    - changed $curcol so setting it beyond the end of the line will
  746.  *      move the cursor to the end of the line and then fail.
  747.  *    10-jul-87
  748.  *    - added a number of fixes and optimizations along with the rest
  749.  *      of the TURBO-C support as submited by John Maline
  750.  *    13-jun-87
  751.  *    - caused dobuf() to copy lastflag to thisflag so the first
  752.  *      command executed will inherit the lastflag from the command
  753.  *      before the execute-buffer command. (needed this for smooth
  754.  *      scrolling to work)
  755.  *    - made flook() look first in the $HOME directory, then in the
  756.  *      current directory, then down the $PATH, and then in the
  757.  *      list in epath.h
  758.  *    14-jul-87
  759.  *    - added some fixes for VMS along with support for the SMG
  760.  *      screen package as submited by Curtis Smith
  761.  *    15-jul-87
  762.  *    - fixed M-^H (delete-previous-word) so it can delete the first
  763.  *      word in a file....I think there may be more of this kind of thing
  764.  *      to fix.
  765.  *    16-jul-87
  766.  *    - added code to allow arbitrary sized lines to be read from files..
  767.  *      speed up file reading in the process.
  768.  *    - made out of memory conditions safer.. especial on file reads
  769.  *    - fixed a bug in bind having to do with uppercasing function
  770.  *      key names (submitted by Jari Salminen)
  771.  *    - made ST520 exit in the same resolution that EMACS was started in
  772.  *      (for the 1040ST)
  773.  *    [FROZE development and released version 3.9 to USENET]
  774.  *    {It never made it.....got killed by comp.unix.sources}
  775.  *    15-sep-87
  776.  *    - added support for Mark Williams C on the Atari ST
  777.  *    - made the MALLOC debugging package only conditional on RAMSIZE
  778.  *    - added code for flagging truncated buffers
  779.  *    23-sep-87
  780.  *    - fixed &RIGHT to return the <arg2> rightmost characters
  781.  *    - fixed a buffer in getval() to be static....things are stabler
  782.  *      now.
  783.  *    - moved all the stack size declarations to after include "estruct.h"
  784.  *      they work a lot better now....... (rather than not at all)
  785.  *    - made Atari ST spawns all work with MWshell
  786.  *    - fixed spawning on the 1040ST under MWC
  787.  *    27-sep-87
  788.  *    - added &exist function to check to see if a named file exist
  789.  *    - added &find function to find a file along the PATH
  790.  *    - added -A switch to run "error.cmd" from command line
  791.  *    - added $gflags to control startup behavior....
  792.  *    03-oct-87
  793.  *    - changed ":c\" to "c:" in epath.h for the AMIGA as suggested
  794.  *      by Tom Edds
  795.  *    - added binary and, or, and xor functions as submited by John Maline
  796.  *      (&band   &bor    and    &bxor)
  797.  *    - added binary not (&bnot) function
  798.  *    - added fixes for gotoline() and nextarg() as submited by David
  799.  *      Dermott
  800.  *    - fixed return value of $curwidth as submitted by David Dermott
  801.  *    - fixed several calls to ldelete() to have a long first argument
  802.  *      (pointed out by David Dermott)
  803.  *    - Fixed a bug in stock() which prevented uppercase FN bindings as
  804.  *      pointed out by many people
  805.  *    - changed dofile() to make sure all executed files don't conflict
  806.  *      with existing buffer names. Took out cludged code in main.c to
  807.  *      handle this problem... this solution is better (suggested by
  808.  *      Don Nash)
  809.  *    05-oct-87
  810.  *    - added in John Gamble's code to allow for a replacement regular
  811.  *      expresion character in MAGIC mode
  812.  *    [note: under MSDOS  we are still TOO BIG!!!!]
  813.  *    - added overwrite-string as a new user callable function, and
  814.  *      lowrite(c) as an internal function for overwriting characters
  815.  *    - added &xlate function to translate strings according to a
  816.  *      translation table
  817.  *    10-oct-87
  818.  *    - added code to allow emacs to clean its own buffers on exit.
  819.  *      useful if emacs is used as a subprogram. Conditional on
  820.  *      the CLEAN definition in estruct.h
  821.  *    14-oct-87
  822.  *    - swallowed very hard and switched to LARGE code/LARGE data model
  823.  *    - packaged and released version 3.9c internally
  824.  *      (MSDOS executables compiled with TURBO C Large model) 
  825.  *    16-oct-87
  826.  *    - temporary fix for FUNCTION keys now includes the Meta-O sequence
  827.  *      if VT100 is definined (submited by Jeff Lomicka)
  828.  *    - an VT100 also triggers input.c to force ESC to always
  829.  *      be interpeted as META as well as the currently bound key
  830.  *    - fixed a bug in the VMSVT driver as pointed out by Dave Dermott
  831.  *    - added a size parameter to token() to eliminate problems with
  832.  *      long variable names. (as sugested by Ray Wallace)
  833.  *    18-oct-87
  834.  *    - fixed a bug in the free ram code that did not clear the buffer
  835.  *      flag causing emacs to ask for more confirnmations on the way out.
  836.  *    19-oct-87
  837.  *    - added ^X-$ execute-program call to directly execute a program
  838.  *      without going through a shell... not all environments have this
  839.  *      code completed yet (uses shell-command where not)
  840.  *    [Froze for 3.9d release internally]
  841.  *    28-oct-87
  842.  *    - added code for Atari ST DENSE mode and new bell as submited
  843.  *      by J. C. Benoist
  844.  *    - made extra CR for ST files conditional on ADDCR. This is only
  845.  *      needed to make the desktop happy...and is painful for porting
  846.  *      files (with 2 CR's) elsewhere (Also from J. C. Benoist)
  847.  *    - added optional more intellegent (and larger) close brace
  848.  *      insertion code (also from J. C. Benoist)
  849.  *    4-nov-87
  850.  *    - fixed AZTEC spawning... all MSDOS spawns should work now
  851.  *    - a META key while debugging will turn $debug to false
  852.  *      and continue execution.
  853.  *    [Froze for version 3.9e USENET release]
  854.  *
  855.  *  Sometime in 1988--
  856.  *    [ERH] Macintosh stuff injected.
  857.  */
  858.  
  859.  
  860. #include    <stdio.h>
  861. #ifdef MPW
  862. #if MPW
  863. #include <types.h>
  864. #include <segload.h>
  865. #endif
  866. #if LSC
  867. #include <SegmentLdr.h>
  868. #define p2cstr PtoCstr
  869. #endif
  870.  
  871. /* make global definitions not external */
  872. #else
  873. #define maindef
  874. #endif
  875.  
  876. #include    "estruct.h"    /* global structures and defines */
  877. #if !FINDER
  878. #include    "efunc.h"    /* function declarations and name table */
  879. #endif
  880. #include    "edef.h"    /* global definitions */
  881. #if !FINDER
  882. #include    "ebind.h"    /* default key bindings */
  883. #endif
  884.  
  885. /* for MSDOS, increase the default stack space */
  886.  
  887. #if    MSDOS & LATTICE
  888. unsigned _stack = 32766;
  889. #endif
  890.  
  891. #if    ATARI & MWC
  892. long _stksize = 32766L;     /* reset stack size (must be even) */
  893. #endif
  894.  
  895. #if    MSDOS & AZTEC
  896. int _STKSIZ = 32766/16;     /* stack size in paragraphs */
  897. int _STKRED = 1024;        /* stack checking limit */
  898. int _HEAPSIZ = 4096/16;     /* (in paragraphs) */
  899. int _STKLOW = 0;        /* default is stack above heap (small only) */
  900. #endif
  901.  
  902. #if    MSDOS & TURBO
  903. extern unsigned _stklen = 32766;
  904. #endif
  905.  
  906. #if    VMS
  907. #include    <ssdef.h>
  908. #define GOOD    (SS$_NORMAL)
  909. #endif
  910.  
  911. #ifndef GOOD
  912. #define GOOD    0
  913. #endif
  914. #if FINDER
  915. extern short _iovrefnum;        /* defined in fileio.c */
  916. AppFile fParm;
  917. /*
  918.  *    InitEmacs                        05/19/86 DJB
  919.  *
  920.  *        Initialize microEmacs... hacked out from the main() subroutine of
  921.  *        Daniel Lawrence's ver 3.6
  922.  *
  923.  */
  924. #define __SEG__ INIT
  925. InitEmacs()
  926. {
  927.     int startf;            /* startup executed flag */
  928.     int ffile;            /* first file flag */
  929.     int basec;            /* c stripped of meta character */
  930.     int viewflag;            /* are we starting in view mode? */
  931.     int gotoflag;            /* do we need to goto a line at start? */
  932.     int gline;            /* if so, what line? */
  933.     int searchflag;         /* Do we need to search at start? */
  934.  
  935.     /* initialize the editor and process the command line arguments */
  936.     vtinit();        /* Displays.        */
  937.     edinit("main");        /* Buffers, windows.    */
  938.     varinit();            /* user variables */
  939.     viewflag = FALSE;    /* view mode defaults off in command line */
  940.     gotoflag = FALSE;    /* set to off to begin with */
  941.     searchflag = FALSE;    /* set to off to begin with */
  942.     ffile = TRUE;        /* no file to edit yet */
  943.     startf = FALSE;     /* startup file not executed yet */
  944.  
  945.     /* process relevant finder parameters */
  946.     if(Do_Emacs_FinderParms(&startf)==FALSE){ /* Invoked with no files. */
  947.         _iovrefnum = curbp->b_ioWDDirID = ourVRefNum;
  948.     }
  949.  
  950.     /* if invoked with nothing, run the startup file here */
  951.     if (startf == FALSE) {
  952.         startup("");
  953.         startf = TRUE;
  954.     }
  955.  
  956.     /* setup to process commands */
  957.     lastflag = 0;                /* Fake last flags.    */
  958.     curbp->b_mode = curbp->b_mode | gmode;    /* and set default modes*/
  959.     curwp->w_flag |= WFMODE;        /* and force an update    */
  960.     update(TRUE);                /* let the user know we are here */
  961. }
  962.  
  963.  
  964. /*
  965.  *    Do_Emacs_FinderParms                        11/11/86 DJB
  966.  *
  967.  *        Process finder parameters...open files.
  968.  *
  969.  */
  970. Do_Emacs_FinderParms(startf)
  971.    int    *startf;
  972. {
  973.     short    message, count, index;
  974.     int    fileFlag;
  975.     
  976.     register BUFFER *bp;
  977.     int ffile;            /* first file flag */
  978.     char bname[NBUFN];        /* buffer name of file to read */
  979. #if    CRYPT
  980.     int eflag;            /* encrypting on the way in? */
  981.     char ekey[NPAT];        /* startup encryption key */
  982. #endif
  983.     
  984.     /* Are there any Files launched from the Finder? */
  985.     CountAppFiles(&message, &count);
  986.     if(count == 0) return FALSE;
  987.     
  988.     /* We don't support printing from the Finder, sorry. */
  989. #ifdef NOTYET
  990.     if(message == appPrint) {
  991.     }
  992. #endif
  993.     
  994.     /* Process the files */
  995.     ffile = TRUE;        /* no file to edit yet */
  996.     *startf = FALSE;    /* startup file not executed yet */
  997. #if    CRYPT
  998.     eflag = FALSE;        /* no encryption by default */
  999. #endif
  1000.     for(index=1;index<=count;index++) {
  1001.         GetAppFiles(index, &fParm);
  1002.         ClrAppFiles(index);
  1003.         p2cstr(&fParm.fName);
  1004.  
  1005.         if (*startf == FALSE) {
  1006.             /* if we haven't run emacs.rc, do it now */
  1007.             startup("");
  1008.             *startf = TRUE;
  1009.         }
  1010.         
  1011. #if    CRYPT
  1012.         /* set up for de-cryption if needed */
  1013.         if (eflag) {
  1014.             curbp->b_mode |= MDCRYPT;
  1015.             strcpy(curbp->b_key, ekey);
  1016.             crypt((char *)NULL, 0);
  1017.             crypt(curbp->b_key, strlen(curbp->b_key));
  1018.         }
  1019. #endif
  1020.         /* set up a buffer for this file */
  1021.         makename(bname, &fParm.fName);
  1022.         /* if this is the first file, read it in */
  1023.         if (ffile) {
  1024.             bp = curbp;
  1025.             strcpy(bp->b_bname, bname);
  1026.             strcpy(bp->b_fname, &fParm.fName);
  1027.             _iovrefnum = bp->b_ioWDDirID = fParm.vRefNum;
  1028.             if (readin(&fParm.fName,TRUE) != TRUE) {
  1029.                 strcpy(bp->b_bname, "main");
  1030.                 strcpy(bp->b_fname, "");
  1031.             }
  1032.             bp->b_dotp = bp->b_linep;
  1033.             bp->b_doto = 0;
  1034.             ffile = FALSE;
  1035.         } else {
  1036.             /* set this to inactive */
  1037.             bp = bfind(bname, TRUE, 0);
  1038.             strcpy(bp->b_fname, &fParm.fName);
  1039.             bp->b_ioWDDirID = fParm.vRefNum;
  1040.             bp->b_active = FALSE;
  1041.         }
  1042.     }
  1043.     return TRUE;
  1044. }
  1045. #define __SEG__ main
  1046.  
  1047.  
  1048. /*
  1049.  *    Do_Emacs_Char                        05/19/86 DJB
  1050.  *
  1051.  *        Main microEmacs command loop - hacked from the main() routine of
  1052.  *        Daniel Lawrence's ver 3.6  by Dave Burnard, updated to 3.8 and 3.9e
  1053.  *        by Earle Horton
  1054.  *
  1055.  */
  1056. Do_Emacs_Char()
  1057. {
  1058.     register int    c;
  1059.     register int    f;
  1060.     register int    n;
  1061.     register int    mflag;
  1062.     int basec;            /* c stripped of meta character */
  1063. #else    
  1064.  
  1065. #if    CALLED
  1066. emacs(argc, argv)
  1067. #else
  1068. main(argc, argv)
  1069. #endif
  1070. int argc;    /* # of arguments */
  1071. char *argv[];    /* argument strings */
  1072.  
  1073. {
  1074.     register int    c;        /* command character */
  1075.     register int    f;        /* default flag */
  1076.     register int    n;        /* numeric repeat count */
  1077.     register int    mflag;        /* negative flag on repeat */
  1078.     register BUFFER *bp;        /* temp buffer pointer */
  1079.     register int    firstfile;    /* first file flag */
  1080.     register int    carg;        /* current arg to scan */
  1081.     register int    startflag;    /* startup executed flag */
  1082.     BUFFER *firstbp = NULL;     /* ptr to first buffer in cmd line */
  1083.     int basec;            /* c stripped of meta character */
  1084.     int viewflag;            /* are we starting in view mode? */
  1085.     int gotoflag;            /* do we need to goto a line at start? */
  1086.     int gline;            /* if so, what line? */
  1087.     int searchflag;         /* Do we need to search at start? */
  1088.     int saveflag;            /* temp store for lastflag */
  1089.     int errflag;            /* C error processing? */
  1090.     char bname[NBUFN];        /* buffer name of file to read */
  1091. #if    CRYPT
  1092.     int cryptflag;            /* encrypting on the way in? */
  1093.     char ekey[NPAT];        /* startup encryption key */
  1094. #endif
  1095.     char *strncpy();
  1096.     extern *pathname[];        /* startup file path/name array */
  1097.  
  1098.     /* initialize the editor */
  1099.     vtinit();        /* Display */
  1100.     edinit("main");     /* Buffers, windows */
  1101.     varinit();        /* user variables */
  1102.  
  1103.     viewflag = FALSE;    /* view mode defaults off in command line */
  1104.     gotoflag = FALSE;    /* set to off to begin with */
  1105.     searchflag = FALSE;    /* set to off to begin with */
  1106.     firstfile = TRUE;    /* no file to edit yet */
  1107.     startflag = FALSE;    /* startup file not executed yet */
  1108.     errflag = FALSE;    /* not doing C error parsing */
  1109. #if    CRYPT
  1110.     cryptflag = FALSE;    /* no encryption by default */
  1111. #endif
  1112. #if    CALLED
  1113.     eexitflag = FALSE;    /* not time to exit yet */
  1114. #endif
  1115.  
  1116.     /* Parse the command line */
  1117.     for (carg = 1; carg < argc; ++carg) {
  1118.  
  1119.         /* Process Switches */
  1120.         if (argv[carg][0] == '-') {
  1121.             switch (argv[carg][1]) {
  1122.                 /* Process Startup macroes */
  1123.                 case 'a':    /* process error file */
  1124.                 case 'A':
  1125.                     errflag = TRUE;
  1126.                     break;
  1127.                 case 'e':    /* -e for Edit file */
  1128.                 case 'E':
  1129.                     viewflag = FALSE;
  1130.                     break;
  1131.                 case 'g':    /* -g for initial goto */
  1132.                 case 'G':
  1133.                     gotoflag = TRUE;
  1134.                     gline = atoi(&argv[carg][2]);
  1135.                     break;
  1136. #if    CRYPT
  1137.                 case 'k':    /* -k<key> for code key */
  1138.                 case 'K':
  1139.                     cryptflag = TRUE;
  1140.                     strcpy(ekey, &argv[carg][2]);
  1141.                     break;
  1142. #endif
  1143.                 case 'r':    /* -r restrictive use */
  1144.                 case 'R':
  1145.                     restflag = TRUE;
  1146.                     break;
  1147.                 case 's':    /* -s for initial search string */
  1148.                 case 'S':
  1149.                     searchflag = TRUE;
  1150.                     strncpy(pat,&argv[carg][2],NPAT);
  1151.                     break;
  1152.                 case 'v':    /* -v for View File */
  1153.                 case 'V':
  1154.                     viewflag = TRUE;
  1155.                     break;
  1156.                 default:    /* unknown switch */
  1157.                     /* ignore this for now */
  1158.                     break;
  1159.             }
  1160.  
  1161.         } else if (argv[carg][0]== '@') {
  1162.  
  1163.             /* Process Startup macroes */
  1164.             if (startup(&argv[carg][1]) == TRUE)
  1165.                 /* don't execute emacs.rc */
  1166.                 startflag = TRUE;
  1167.  
  1168.         } else {
  1169.  
  1170.             /* Process an input file */
  1171.  
  1172.             /* set up a buffer for this file */
  1173.             makename(bname, argv[carg]);
  1174.             unqname(bname);
  1175.  
  1176.             /* set this to inactive */
  1177.             bp = bfind(bname, TRUE, 0);
  1178.             strcpy(bp->b_fname, argv[carg]);
  1179.             bp->b_active = FALSE;
  1180.             if (firstfile) {
  1181.                 firstbp = bp;
  1182.                 firstfile = FALSE;
  1183.             }
  1184.  
  1185.             /* set the modes appropriatly */
  1186.             if (viewflag)
  1187.                 bp->b_mode |= MDVIEW;
  1188. #if    CRYPT
  1189.             if (cryptflag) {
  1190.                 bp->b_mode |= MDCRYPT;
  1191.                 crypt((char *)NULL, 0);
  1192.                 crypt(ekey, strlen(ekey));
  1193.                 strncpy(bp->b_key, ekey, NPAT);
  1194.             }
  1195. #endif
  1196.         }
  1197.     }
  1198.  
  1199.     /* if we are C error parsing... run it! */
  1200.     if (errflag) {
  1201.         if (startup("error.cmd") == TRUE)
  1202.             startflag = TRUE;
  1203.     }
  1204.  
  1205.     /* if invoked with no other startup files,
  1206.        run the system startup file here */
  1207.     if (startflag == FALSE) {
  1208.         startup("");
  1209.         startflag = TRUE;
  1210.     }
  1211.  
  1212.     /* if there are any files to read, read the first one! */
  1213.     bp = bfind("main", FALSE, 0);
  1214.     if (firstfile == FALSE && (gflags & GFREAD)) {
  1215.         swbuffer(firstbp);
  1216.         curbp->b_mode |= gmode;
  1217.         zotbuf(bp);
  1218.     } else
  1219.         bp->b_mode |= gmode;
  1220.  
  1221.     /* Deal with startup gotos and searches */
  1222.     if (gotoflag && searchflag) {
  1223.         update(FALSE);
  1224.         mlwrite("[Can not search and goto at the same time!]");
  1225.     }
  1226.     else if (gotoflag) {
  1227.         if (gotoline(TRUE,gline) == FALSE) {
  1228.             update(FALSE);
  1229.             mlwrite("[Bogus goto argument]");
  1230.         }
  1231.     } else if (searchflag) {
  1232.         if (forwhunt(FALSE, 0) == FALSE)
  1233.             update(FALSE);
  1234.     }
  1235.  
  1236.     /* setup to process commands */
  1237.     lastflag = 0;                /* Fake last flags.    */
  1238. loop:
  1239.  
  1240. #if    CALLED
  1241.     /* if we were called as a subroutine and want to leave, do so */
  1242.     if (eexitflag)
  1243.         return(eexitval);
  1244. #endif
  1245.  
  1246.     /* execute the "command" macro...normally null */
  1247.     saveflag = lastflag;    /* preserve lastflag through this */
  1248.     execute(META|SPEC|'C', FALSE, 1);
  1249.     lastflag = saveflag;
  1250.  
  1251.     /* Fix up the screen    */
  1252.     update(FALSE);
  1253.  
  1254. #endif                /* FINDER */
  1255. #if    FINDER
  1256. loop:
  1257. #endif
  1258.     /* get the next command from the keyboard */
  1259.     c = getcmd();
  1260.  
  1261.     /* if there is something on the command line, clear it */
  1262.     if (mpresf != FALSE) {
  1263.         mlerase();
  1264.         update(FALSE);
  1265. #if    CLRMSG
  1266.         if (c == ' ')            /* ITS EMACS does this    */
  1267.             goto loop;
  1268. #endif
  1269.     }
  1270.     f = FALSE;
  1271.     n = 1;
  1272.  
  1273.     /* do META-# processing if needed */
  1274.  
  1275.     basec = c & ~META;        /* strip meta char off if there */
  1276.     if ((c & META) && ((basec >= '0' && basec <= '9') || basec == '-')) {
  1277.         f = TRUE;        /* there is a # arg */
  1278.         n = 0;            /* start with a zero default */
  1279.         mflag = 1;        /* current minus flag */
  1280.         c = basec;        /* strip the META */
  1281.         while ((c >= '0' && c <= '9') || (c == '-')) {
  1282.             if (c == '-') {
  1283.                 /* already hit a minus or digit? */
  1284.                 if ((mflag == -1) || (n != 0))
  1285.                     break;
  1286.                 mflag = -1;
  1287.             } else {
  1288.                 n = n * 10 + (c - '0');
  1289.             }
  1290.             if ((n == 0) && (mflag == -1))    /* lonely - */
  1291.                 mlwrite("Arg:");
  1292.             else
  1293.                 mlwrite("Arg: %d",n * mflag);
  1294.  
  1295.             c = getcmd();    /* get the next key */
  1296.         }
  1297.         n = n * mflag;    /* figure in the sign */
  1298.     }
  1299.  
  1300.     /* do ^U repeat argument processing */
  1301.  
  1302.     if (c == reptc) {           /* ^U, start argument   */
  1303.         f = TRUE;
  1304.         n = 4;                /* with argument of 4 */
  1305.         mflag = 0;            /* that can be discarded. */
  1306.         mlwrite("Arg: 4");
  1307.         while ((c=getcmd()) >='0' && c<='9' || c==reptc || c=='-'){
  1308.             if (c == reptc)
  1309.                 if ((n > 0) == ((n*4) > 0))
  1310.                     n = n*4;
  1311.                 else
  1312.                     n = 1;
  1313.             /*
  1314.              * If dash, and start of argument string, set arg.
  1315.              * to -1.  Otherwise, insert it.
  1316.              */
  1317.             else if (c == '-') {
  1318.                 if (mflag)
  1319.                     break;
  1320.                 n = 0;
  1321.                 mflag = -1;
  1322.             }
  1323.             /*
  1324.              * If first digit entered, replace previous argument
  1325.              * with digit and set sign.  Otherwise, append to arg.
  1326.              */
  1327.             else {
  1328.                 if (!mflag) {
  1329.                     n = 0;
  1330.                     mflag = 1;
  1331.                 }
  1332.                 n = 10*n + c - '0';
  1333.             }
  1334.             mlwrite("Arg: %d", (mflag >=0) ? n : (n ? -n : -1));
  1335.         }
  1336.         /*
  1337.          * Make arguments preceded by a minus sign negative and change
  1338.          * the special argument "^U -" to an effective "^U -1".
  1339.          */
  1340.         if (mflag == -1) {
  1341.             if (n == 0)
  1342.                 n++;
  1343.             n = -n;
  1344.         }
  1345.     }
  1346.  
  1347.     /* and execute the command */
  1348.     execute(c, f, n);
  1349. #if FINDER
  1350.     if (kbdmode != PLAY){
  1351.         return;
  1352.     }
  1353. #endif
  1354.     goto loop;
  1355. }
  1356.  
  1357. /*
  1358.  * Initialize all of the buffers and windows. The buffer name is passed down
  1359.  * as an argument, because the main routine may have been told to read in a
  1360.  * file by default, and we want the buffer name to be right.
  1361.  */
  1362. #define __SEG__ INIT
  1363. edinit(bname)
  1364. char    bname[];
  1365. {
  1366.     register BUFFER *bp;
  1367.     register WINDOW *wp;
  1368.     char *malloc();
  1369.  
  1370.     bp = bfind(bname, TRUE, 0);        /* First buffer     */
  1371.     blistp = bfind("[List]", TRUE, BFINVS); /* Buffer list buffer    */
  1372.     wp = (WINDOW *) malloc(sizeof(WINDOW)); /* First window     */
  1373.     if (bp==NULL || wp==NULL || blistp==NULL)
  1374.         exit(1);
  1375.     curbp  = bp;                /* Make this current    */
  1376.     wheadp = wp;
  1377.     curwp  = wp;
  1378.     wp->w_wndp  = NULL;            /* Initialize window    */
  1379.     wp->w_bufp  = bp;
  1380.     bp->b_nwnd  = 1;            /* Displayed.        */
  1381.     wp->w_linep = bp->b_linep;
  1382.     wp->w_dotp  = bp->b_linep;
  1383.     wp->w_doto  = 0;
  1384.     wp->w_markp = NULL;
  1385.     wp->w_marko = 0;
  1386.     wp->w_toprow = 0;
  1387. #if    COLOR
  1388.     /* initalize colors to global defaults */
  1389.     wp->w_fcolor = gfcolor;
  1390.     wp->w_bcolor = gbcolor;
  1391. #endif
  1392.     wp->w_ntrows = term.t_nrow-1;        /* "-1" for mode line.    */
  1393.     wp->w_force = 0;
  1394.     wp->w_flag  = WFMODE|WFHARD;        /* Full.        */
  1395. }
  1396. #define __SEG__ main
  1397. /*
  1398.  * This is the general command execution routine. It handles the fake binding
  1399.  * of all the keys to "self-insert". It also clears out the "thisflag" word,
  1400.  * and arranges to move it to the "lastflag", so that the next command can
  1401.  * look at it. Return the status of command.
  1402.  */
  1403. execute(c, f, n)
  1404. {
  1405.     register int status;
  1406.     int (*execfunc)();        /* ptr to function to execute */
  1407.     int (*getbind())();
  1408.  
  1409.     /* if the keystroke is a bound function...do it */
  1410.     execfunc = getbind(c);
  1411.     if (execfunc != NULL) {
  1412.         thisflag = 0;
  1413.         status     = (*execfunc)(f, n);
  1414.         lastflag = thisflag;
  1415.         return (status);
  1416.     }
  1417.  
  1418.     /*
  1419.      * If a space was typed, fill column is defined, the argument is non-
  1420.      * negative, wrap mode is enabled, and we are now past fill column,
  1421.      * and we are not read-only, perform word wrap.
  1422.      */
  1423.     if (c == ' ' && (curwp->w_bufp->b_mode & MDWRAP) && fillcol > 0 &&
  1424.         n >= 0 && getccol(FALSE) > fillcol &&
  1425.         (curwp->w_bufp->b_mode & MDVIEW) == FALSE)
  1426.         execute(META|SPEC|'W', FALSE, 1);
  1427.  
  1428.     if ((c>=0x20 && c<=0xFF)) {    /* Self inserting.    */
  1429.         if (n <= 0) {            /* Fenceposts.        */
  1430.             lastflag = 0;
  1431.             return (n<0 ? FALSE : TRUE);
  1432.         }
  1433.         thisflag = 0;            /* For the future.    */
  1434.  
  1435.         /* if we are in overwrite mode, not at eol,
  1436.            and next char is not a tab or we are at a tab stop,
  1437.            delete a char forword            */
  1438.         if (curwp->w_bufp->b_mode & MDOVER &&
  1439.             curwp->w_doto < curwp->w_dotp->l_used &&
  1440.             (lgetc(curwp->w_dotp, curwp->w_doto) != '\t' ||
  1441.              (curwp->w_doto) % 8 == 7))
  1442.                 ldelete(1L, FALSE);
  1443.  
  1444.         /* do the appropriate insertion */
  1445.         if (c == '}' && (curbp->b_mode & MDCMOD) != 0)
  1446.             status = insbrace(n, c);
  1447.         else if (c == '#' && (curbp->b_mode & MDCMOD) != 0)
  1448.             status = inspound();
  1449.         else
  1450.             status = linsert(n, c);
  1451.  
  1452. #if    CFENCE
  1453.         /* check for CMODE fence matching */
  1454.         if ((c == '}' || c == ')' || c == ']') &&
  1455.                 (curbp->b_mode & MDCMOD) != 0)
  1456.             fmatch(c);
  1457. #endif
  1458.  
  1459.         /* check auto-save mode */
  1460.         if (curbp->b_mode & MDASAVE)
  1461.             if (--gacount == 0) {
  1462.                 /* and save the file if needed */
  1463.                 upscreen(FALSE, 0);
  1464.                 filesave(FALSE, 0);
  1465.                 gacount = gasave;
  1466.             }
  1467.  
  1468.         lastflag = thisflag;
  1469.         return (status);
  1470.     }
  1471.     TTbeep();
  1472.     mlwrite("[Key not bound]");        /* complain        */
  1473.     lastflag = 0;                /* Fake last flags.    */
  1474.     return (FALSE);
  1475. }
  1476.  
  1477. /*
  1478.  * Fancy quit command, as implemented by Norm. If the any buffer has
  1479.  * changed do a write on that buffer and exit emacs, otherwise simply exit.
  1480.  */
  1481. quickexit(f, n)
  1482. {
  1483.     register BUFFER *bp;    /* scanning pointer to buffers */
  1484.     register BUFFER *oldcb; /* original current buffer */
  1485.     register int status;
  1486.  
  1487.     oldcb = curbp;                /* save in case we fail */
  1488.  
  1489.     bp = bheadp;
  1490.     while (bp != NULL) {
  1491.         if ((bp->b_flag&BFCHG) != 0    /* Changed.        */
  1492.         && (bp->b_flag&BFINVS) == 0) {    /* Real.        */
  1493.             curbp = bp;        /* make that buffer cur */
  1494.             mlwrite("[Saving %s]",bp->b_fname);
  1495.             mlwrite(EOLSTR);
  1496.             if ((status = filesave(f, n)) != TRUE) {
  1497.                 curbp = oldcb;    /* restore curbp */
  1498.                 return(status);
  1499.             }
  1500.         }
  1501.     bp = bp->b_bufp;            /* on to the next buffer */
  1502.     }
  1503.     quit(f, n);                /* conditionally quit    */
  1504.     return(TRUE);
  1505. }
  1506.  
  1507. /*
  1508.  * Quit command. If an argument, always quit. Otherwise confirm if a buffer
  1509.  * has been changed and not written out. Normally bound to "C-X C-C".
  1510.  */
  1511. quit(f, n)
  1512. {
  1513.     register int    s;
  1514.  
  1515.     if (f != FALSE                /* Argument forces it.    */
  1516.     || anycb() == FALSE            /* All buffers clean.    */
  1517.                         /* User says it's OK.   */
  1518.     || (s=mlyesno("Modified buffers exist. Leave anyway")) == TRUE) {
  1519. #if    FILOCK
  1520.         if (lockrel() != TRUE) {
  1521.             TTputc(LF);
  1522.             TTputc(CR);
  1523.             TTclose();
  1524.             TTkclose();
  1525.             exit(1);
  1526.         }
  1527. #endif
  1528.         vttidy();
  1529.         if (f)
  1530.             exit(n);
  1531.         else
  1532.             exit(GOOD);
  1533.     }
  1534.     mlwrite("");
  1535.     return(s);
  1536. }
  1537.  
  1538. /*
  1539.  * Begin a keyboard macro.
  1540.  * Error if not at the top level in keyboard processing. Set up variables and
  1541.  * return.
  1542.  */
  1543. ctlxlp(f, n)
  1544. {
  1545.     if (kbdmode != STOP) {
  1546.         mlwrite("%%Macro already active");
  1547.         return(FALSE);
  1548.     }
  1549.     mlwrite("[Start macro]");
  1550.     kbdptr = &kbdm[0];
  1551.     kbdend = kbdptr;
  1552.     kbdmode = RECORD;
  1553.     return (TRUE);
  1554. }
  1555.  
  1556. /*
  1557.  * End keyboard macro. Check for the same limit conditions as the above
  1558.  * routine. Set up the variables and return to the caller.
  1559.  */
  1560. ctlxrp(f, n)
  1561. {
  1562.     if (kbdmode == STOP) {
  1563.         mlwrite("%%Macro not active");
  1564.         return(FALSE);
  1565.     }
  1566.     if (kbdmode == RECORD) {
  1567.         mlwrite("[End macro]");
  1568.         kbdmode = STOP;
  1569.     }
  1570.     return(TRUE);
  1571. }
  1572.  
  1573. /*
  1574.  * Execute a macro.
  1575.  * The command argument is the number of times to loop. Quit as soon as a
  1576.  * command gets an error. Return TRUE if all ok, else FALSE.
  1577.  */
  1578. ctlxe(f, n)
  1579. {
  1580.     if (kbdmode != STOP) {
  1581.         mlwrite("%%Macro already active");
  1582.         return(FALSE);
  1583.     }
  1584.     if (n <= 0)
  1585.         return (TRUE);
  1586.     kbdrep = n;        /* remember how many times to execute */
  1587.     kbdmode = PLAY;     /* start us in play mode */
  1588.     kbdptr = &kbdm[0];    /*    at the beginning */
  1589.     return(TRUE);
  1590. }
  1591.  
  1592. /*
  1593.  * Abort.
  1594.  * Beep the beeper. Kill off any keyboard macro, etc., that is in progress.
  1595.  * Sometimes called as a routine, to do general aborting of stuff.
  1596.  */
  1597. ctrlg(f, n)
  1598. {
  1599.     TTbeep();
  1600.     kbdmode = STOP;
  1601.     mlwrite("[Aborted]");
  1602.     return(ABORT);
  1603. }
  1604.  
  1605. /* tell the user that this command is illegal while we are in
  1606.    VIEW (read-only) mode                */
  1607.  
  1608. rdonly()
  1609.  
  1610. {
  1611.     TTbeep();
  1612.     mlwrite("[Key illegal in VIEW mode]");
  1613.     return(FALSE);
  1614. }
  1615.  
  1616. resterr()
  1617.  
  1618. {
  1619.     TTbeep();
  1620.     mlwrite("[That command is RESTRICTED]");
  1621.     return(FALSE);
  1622. }
  1623.  
  1624. nullproc()    /* user function that does NOTHING */
  1625.  
  1626. {
  1627. }
  1628.  
  1629. meta()    /* dummy function for binding to meta prefix */
  1630. {
  1631. }
  1632.  
  1633. cex()    /* dummy function for binding to control-x prefix */
  1634. {
  1635. }
  1636.  
  1637. unarg() /* dummy function for binding to universal-argument */
  1638. {
  1639. }
  1640.