home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume8 / micrognu / part01 next >
Text File  |  1987-01-26  |  61KB  |  1,986 lines

  1. Subject:  v08i008:  A Micro-Emacs variant that resembles GNU Emacs
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: Bob Larson <seismo!usc-oberon!blarson>
  6. Mod.sources: Volume 8, Issue 8
  7. Archive-name: micrognu/Part01
  8.  
  9. [  It's editor week at mod.sources...  -r$ ]
  10.  
  11. #! /bin/sh
  12. #
  13. # distribution note: This distribution of mg 1a is 11 shar files:
  14. #    mg_1.shar through mg_5.shar    system indepentend, termcap,
  15. #                    bsd, sysv, and osk files.
  16. #    mg_amiga1.shar, mg_amiga2.shar    amiga specific files
  17. #    mg_vms1.shar through mg_vms4.shar
  18. #                    vms and eunice specific files.
  19. #
  20. # This is a shell archive, meaning:
  21. # 1. Remove everything above the #! /bin/sh line.
  22. # 2. Save the resulting text in a file.
  23. # 3. Execute the file with /bin/sh (not csh) to create the files:
  24. #    README
  25. #    systty.mods
  26. #    functions
  27. #    def.h
  28. #    display.c
  29. #    kbd.c
  30. export PATH; PATH=/bin:$PATH
  31. if test -f 'README'
  32. then
  33.     echo shar: will not over-write existing file "'README'"
  34. else
  35. cat << \SHAR_EOF > 'README'
  36. MG 1a README Nov 16, 1986
  37.  
  38. MicroGnuEmacs (mg) is a Public Domain EMACS style editor.  It is
  39. "broadly" compatible with GNU Emacs, the latest creation of Richard M.
  40. Stallman, Chief GNUisance and inventor of Emacs.  GNU Emacs (and other
  41. portions of GNU as they are released) are essentially free, (there are
  42. handling charges for obtaining it) and so is MicroGnuEmacs.  You may
  43. never have to learn another editor.  (But probably will, at least long
  44. enough to port MicroGnuEmacs...)
  45.  
  46. MicroGnuEmacs is not associated with the GNU project, and does not
  47. have the copyright restrictions present in GNU Emacs.  (However, a few
  48. of the system dependent modules do have copyright notices, specificly
  49. the VMS termcap routines and the amiga specific routines.  Look at the
  50. source code for exact copyright restrictions.)  The MicroGnuEmacs
  51. authors individually may or may not agree with the opinions expressed
  52. by Richard Stallman and the GNU project. 
  53.  
  54. This program is intended to be a small, fast, and portable editor for
  55. people who can't run real Emacs thing for one reason or another.  It
  56. is compatible with GNU because there shouldn't be any reason to learn
  57. more than one Emacs flavor.  We have excised most MicroEMACS features
  58. that were incompatible with the big brother, and added missing
  59. features that seemed essential. 
  60.  
  61. There are at least two other major versions of MicroEMACS in
  62. circulation.  One comes from Daniel Lawrence, (based on an old version
  63. from Dave Conroy) and is available from mod.sources.  It uses a 3.x
  64. version numbering scheme, and the latest I know about is 3.7i.  It has
  65. some features not found in MicroGnuEmacs, is bigger, and is
  66. incompatible with GNU Emacs.  It might be a better choice for you if
  67. you *must* have something not present here and can't run GNU. 
  68.  
  69. Another variety uses a different numbering scheme, and is up to v30.
  70. This also comes from mod.sources, and is the latest version from the
  71. original MicroEMACS author Dave Conroy.  MicroGnuEmacs is derived from
  72. this version, and we hope to replace it. 
  73.  
  74. Code will move fairly easily between MicroGnuEmacs and v30
  75. derivatives.  It will not move easily to the 3.x strain because of
  76. diverging ideas about how things should work internally.  Command
  77. functions and keymapping, for instance, are completely different
  78. between the two flavors. 
  79.  
  80. This is the first distribution release of MicroGnuEmacs.  (It went
  81. through four beta releases to iron out the changes made by the various
  82. autors.)  Beyond the work of Dave Conroy, author of the original
  83. public domain v30, this contains the efforts of:
  84.  
  85.     mwm@ucbopal.berkeley.edu    Mike Meyer
  86.     mic@ngp.utexas.edu        Mic Kaczmarczik
  87.     blarson@usc-oberon.arpa        Bob Larson
  88.     rtech!daveb@sun.com        Dave Brower
  89.  
  90. Special thanks are due the first three fellows, who did most of the
  91. work. 
  92.  
  93. These systems are known to work in the current version:
  94.  
  95.     4.2 & 4.3 BSD Unix
  96.     OS9/68k
  97.     VMS
  98.     Amiga
  99.     System V
  100.     Eunice
  101.  
  102. As far as MG is concerned, Ultrix-32 is equivalent to BSD unix.
  103.  
  104. It should support MSDOS, PCDOS, and the Rainbow if you swipe the sys
  105. and tty files from the v30 distribution and modify them as specified
  106. in the file systty.mods.  It obviously hasn't been tested. 
  107.  
  108. How to Make a MicroGnuEmacs
  109. ---------------------------
  110.  
  111. On UNIX at least, it's easy.  (Note that even on these systems you may
  112. want to change a compile time option.)  If you have BSD UNIX, do:
  113.  
  114.     ln sys/bsd/Makefile .
  115.     make
  116.  
  117. For System V, do:
  118.  
  119.     ln sys/sysv/Makefile .
  120.     make
  121.  
  122. There are several other directories under sys: osk, vms, and eunice
  123. and amiga.  You should follow the directions contained therein to make
  124. one of those versions. 
  125.  
  126. For most systems (everyting except the amiga currently), the termcap
  127. terminal definition is used.  There is a readme file in the termcap
  128. subdirectory of the tty directory explaining what entries are used and
  129. how.  (Termcap is a way to do display manipulation in a terminal
  130. independent manner.)
  131.  
  132. ----------------------------------------------------------------------
  133.  
  134. Known limitaions and minor bugs descovered immeditatly before release:
  135.  
  136.     A newline will be appended to the last line of a file if it does
  137.     not have one.
  138.  
  139.     There is a fixed maximum line length on files read.  (Defaults
  140.     to 256, but may be changed at compile time.)
  141.  
  142.     See functions for function by function differences from real
  143.     GNU Emacs.
  144.  
  145.     DPROMPT code has not been added to ttyio.c for all systems
  146.     where it could be supported.
  147.  
  148.     The Amiga code has not been extensivly tested with all options
  149.     on all compilers.  A problem have been discovered but not
  150.     duplicated, possibly a compiler problem.
  151.  
  152.     Multi-case buffer names can be created on case-insensitive systems
  153.     (i.e. OSK) for files specified on the command line.
  154.  
  155. ------------------------------------------------------------------------
  156.  
  157. If you have a change to make that you think should be incorporated
  158. into the next version of MicroGnuEmacs, send it to the contact for
  159. your system:
  160.  
  161. Amiga Lattice C:    Mike Meyer: 
  162.     mwm@berkeley.edu
  163.     ucbvax!mwm
  164.  
  165. Amiga Manx C & VMS:    Mic Kaczmarczik: 
  166.     ut-sally!ut-ngp!mic
  167.     mic@ngp.utexas.edu
  168.     CCEP001@UTADNX.BITNET
  169.  
  170. OSK & BSD:    Bob Larson: 
  171.     blarson@usc-oberon.arpa
  172.     sdcrdcf!usc-oberon!blarson
  173.  
  174. Support for additional systems and terminals should include being
  175. available for beta testing as other changes are made.  (Send a short
  176. note to all three contacts above.) If you can't reach one of us via a
  177. computer network, I suppose you could send a change to my snail mail
  178. address below on 5" os9 format disks or 9 track tape (ANSI variable
  179. label or Prime magsav format), but this efectivly rules you out as a
  180. potential beta tester.  (Don't expect the disk or tape back unless you
  181. inculude a SASE with sufficent postage.) I will not be sending out
  182. copies on magnetic media, so please don't ask.  If you somehow got an
  183. incomplete or non-standard copy, (i.e. missing one of the sys
  184. directories mentioned here as working) complain to who you got it from
  185. not to me. 
  186.  
  187.     Robert Larson
  188.     309 S. Alexandria Ave.
  189.     Apt. 117
  190.     Los Angeles, CA  90020
  191. SHAR_EOF
  192. fi # end of overwriting check
  193. if test -f 'systty.mods'
  194. then
  195.     echo shar: will not over-write existing file "'systty.mods'"
  196. else
  197. cat << \SHAR_EOF > 'systty.mods'
  198. 1) All the function names have changed, so fix function bindings.
  199. 2) version has changed from char *[] to char *, fix all references.
  200. 3) if STARTUP is defined, startupfile (which returns a pointer to the
  201.     name of the users startupfile) should be in fileio.c
  202. 4) The typedefs for KEY (the internal key type, an 11 bit value) and
  203.     RSIZE (how big a region can be) need to be in sysdef.h
  204. 5) Either a function or a define for bcopy() needs to come in for the
  205.     system. It looks like bcopy(b1, b2, length), and copies length
  206.     bytes from b1 to b2. IT MUST DO A NON-DESTRUCTIVE COPY. Check for
  207.     a routine that does this (by a different name, of course) in your
  208.     system already, and make it a define.
  209. 6) Either a function or a define for typeahead() needs to exist. It returns
  210.     true if there are input characters to be had. Easy case is to
  211.     #define it as FALSE.
  212. 7) abort has turned into panic, with a string argument. Panic should
  213.     spit out the string, and then leave a core image if possible.
  214. 8) All #if's were changed to #ifdef's.  Most configuration #define XXX 0 
  215.     lines should be commented out.
  216. 9) Several optional defines have been added: VARARGS, SYSINIT, 
  217.     STANDOUT_GLITCH, MOVE_STANDOUT, XCHAR + XSHORT, NLINE, DPROMPT,
  218.     XKEYS. 
  219. 10) Define KEYDUP_ERROR for debugging symbol.c (and a (sometimes MUCH) 
  220.     larger executable.)
  221. 11) User preference options have been moved to Makefile from def.h.
  222. 12) To use with DPROMPT, a ttwait function is needed in ttyio.c.  An
  223.     example is in sys/osk.
  224. SHAR_EOF
  225. fi # end of overwriting check
  226. if test -f 'functions'
  227. then
  228.     echo shar: will not over-write existing file "'functions'"
  229. else
  230. cat << \SHAR_EOF > 'functions'
  231. Format:
  232. #!function-name            [default binding]
  233.     Description
  234. !    How it differs from GNU.
  235.  
  236. The '!' in the function name is optional.  If present, it means that the
  237. function does not exist in GNU.
  238.  
  239. To get a function list with bindings, do
  240.     "grep ^# this_file | sed -e 's/^#//' -e 's/^#!//' > your_file"
  241. Other interesting things can be extracted as you see fit.
  242.  
  243. -------------------------------------------------------------------------------
  244.  
  245. #auto-fill-mode
  246.     Cause word-wrap at fill-column, after space is typed.
  247. !    Modes are global across all buffers.
  248. #!auto-indent-mode
  249.     Cause indent to first whitespace after a newline.
  250. #backward-char            [C-b]
  251.     Move point left ARG characters (right if ARG negative).
  252.     On reaching end of buffer, stop and signal error.
  253. #backward-delete-char        [DEL]
  254.     Delete characters backwards. Delete ARG chars, and save in
  255.     kill buffer if ARG was specified
  256. #backward-kill-word        [ESC DEL]
  257.     Kill characters backward until encountering the end of a word.
  258.     With argument, do this that many times.
  259. !    When deleting backwards across line boundaries onto non-null
  260. !    kill buffers, things get put in the kill buffer in the wrong
  261. !    order.
  262. #backward-paragraph        [ESC [ ]
  263.     Move backward to start of paragraph.  With arg, do it arg times.
  264. !    Definition of paragraph isn't quite the same as with GNU, need
  265. !    to fill it in.
  266. #backward-word            [ESC b]
  267.     Move backward until encountering the end of a word.
  268.     With argument, do this that many times.
  269. #beginning-of-buffer        [ESC < ]
  270.     Move point to the beginning of the buffer; leave mark at
  271.     previous position.
  272. !    Doesn't understand arguments.
  273. #beginning-of-line        [C-a]
  274.     Move point to beginning of current line.
  275. #!bsmap-mode
  276.     If no argument, turns on a mode that maps ^H to del and del
  277.     to ^H, where the editor can't see it. If there is an argument,
  278.     turns that mode off.
  279. #call-last-kbd-macro        [C-x e]
  280.     Call the last keyboard macro that you defined with C-x (.
  281. !    Not as fancy as GNU version.
  282. #capitalize-word        [ESC c]
  283.     Convert following word (or ARG words) to upper case, moving over.
  284. !    Doesn't handle negative arguments.
  285. #copy-region-as-kill        [ESC w]
  286.     Save the region as if killed, but don't kill it.
  287. #!ctrlx-four-hack
  288.     Exists to support the Ctl-x 4 <things> code.
  289. #delete-blank-lines        [C-x C-o]
  290.     On blank line, delete all surrounding blank lines, leaving just one.
  291. !    Always behaves that way, doesn't do the isolated blank and non-blank
  292. !    lines as does GNU.
  293. #delete-char            [C-d]
  294.     Delete the following ARG characters (previous, with negative arg).
  295.     If ARG is specified, appends deleted characters to the kill buffer.
  296. #delete-other-windows        [C-x 1]
  297.     Make current window fill the screen.
  298. #delete-window            [C-x 0]
  299.     Remove current window from the display.
  300. #describe-bindings        [C-h b]
  301.     Show a list of all defined keys, and their definitions.
  302.     The list is put in a buffer, which is displayed.
  303. !    No heading on columns in output buffer
  304. #describe-key-briefly        [C-h c]
  305.     Print the name of the function KEY invokes.
  306. #downcase-region        [C-x C-l]
  307.     Convert the region to lower case.
  308. #downcase-word            [ESC l]
  309.     Convert following word (or ARG words) to lower case, moving over.
  310. !    Doesn't handle negative arguments.
  311. #emacs-version
  312.     Print string describing the version of Emacs that is running.
  313. #end-kbd-macro            [C-x ) ]
  314.     Finish defining a keyboard macro.
  315.     The definition was started by C-x (.
  316.     The macro is now available for use via C-x e,
  317. !    Can't use end-kbd-macro to execute macro.
  318. #end-of-buffer            [ESC > ]
  319.     Move point to the end of the buffer; leave mark at previous position.
  320. !    Doesn't understand arguments
  321. #end-of-line            [C-e]
  322.     Move point to end of current line.
  323. !    Doesn't understand arguments.
  324. #enlarge-window            [C-x ^]
  325.     Make current window ARG lines bigger.
  326. !    Won't make other windows vanish to make room for enlarging window.
  327. #eval-current-buffer
  328.     Execute the current buffer as an Emacs command file.
  329. !    Doesn't exist in the MICRO version.
  330. #eval-expression
  331.     Get Emacs command and evaluate.
  332. !    Doesn't exist in MICRO version. No autocompletion.
  333. #exchange-point-and-mark    [C-x C-x]
  334.     Put the mark where point is now, and point where the mark is now.
  335. #execute-extended-command
  336.     Read function name, then read its arguments and call it.
  337. #fill-paragraph            [ESC q]
  338.     Fill paragraph at or after point.
  339. !    Leaves point at end of paragraph, instead of where it started.
  340. !    Other differences, such as paragraph definition and what
  341. !    characters to doublespace after also exist.
  342. #find-file            [C-x C-f]
  343.     Edit file FILENAME.
  344.     Switch to a buffer visiting file FILENAME,
  345.     creating one if none already exists.
  346. !    MicroGnuEmacs will put a newline at the end of the last line
  347. !    if there is not one there already.
  348. #find-file-other-window        [C-x 4 f] [C-x 4 C-f]
  349.     Edit file FILENAME, in another window.
  350.     May create a new window, or reuse an existing one;
  351. !    See find-file.
  352. #!flow-mode
  353.     Without an argument, sets a mode that maps ^\ to ^S and ^^ to ^Q,
  354.     and silently eats ^S and ^Q at a level where the editor can't see
  355.     it. With an argument, turns that mode off.
  356. #forward-char            [C-f]
  357.     Move point right ARG characters (left if ARG negative).
  358.     On reaching end of buffer, stop and signal error.
  359. #forward-paragraph        [ESC ] ]
  360.     Move forward to end of paragraph.  With arg, do it arg times.
  361. !    See backward-paragraph
  362. #forward-word            [ESC f]
  363.     Move point forward ARG words (backward if ARG is negative).
  364. #global-set-key
  365.     Give KEY a definition of COMMAND.
  366. #global-unset-key
  367.     Remove global definition of KEY.
  368. #goto-line
  369.     goto LINE in the current buffer.
  370. !    Want to leave mark at old position, but....
  371. #help                [C-h]
  372.     Prompt user to find out what kind of help to supply
  373. !    Only b (describe-bindings), c (describe-key-briefly) and ^H
  374. !    (help) work.
  375. #insert-file            [C-x i]
  376.     Insert contents of file FILENAME into buffer after point.
  377.     Set mark after the inserted text.
  378. !    File not found handling differs from GNU Emacs.
  379. !    see find-file.
  380. #!insert-newline        [RET]
  381.     Bound to newline so that it does the right things.  Usually
  382.     ignorable.
  383. #!insert-with-wrap
  384.     Bound to space in auto-fill-mode. Check current column, and adds
  385.     a newline if past it.
  386. #isearch-backward        [C-r]
  387.     Do incremental search backward.
  388.     See isearch-forward for more information.
  389. !    Not as fancy as the GNU version.
  390. #isearch-forward        [C-s]
  391.     Do incremental search forward.
  392.     As you type characters, they add to the search string and are found.
  393.     Type Delete to cancel characters from end of search string.
  394.     Type ESC to exit, leaving point at location found.
  395.     Type C-S to search again forward, C-R to search again backward.
  396.     Type C-Q to quote control character to search for it.
  397.     C-G while searching or when search has failed
  398.     cancels input back to what has been found successfully.
  399.     C-G when search is successful aborts and moves point to starting point.
  400.     Other control and meta characters terminate the search
  401.      and are then executed normally.
  402. !    See isearch-backward.
  403. #just-one-space            [ESC SPC]
  404. #keyboard-quit            [C-g]
  405.     Terminate the current function with an quit condition.
  406. #kill-buffer            [C-x k]
  407.     Get rid of the specified buffer.
  408. !    Has minor problems: if buffer being killed is open in any windows,
  409. !    those windows must have valid alternate buffers.  Leaves point and 
  410. !    mark at end of buffer if alternate buffer is open on another window.
  411. #kill-line            [C-k]
  412.     Kill the rest of the current line; before a newline, kill the newline.
  413.     With prefix argument, kill that many lines from point.
  414.     Negative arguments kill lines backward.
  415. !    When killing backwards across line boundaries (args of < 0) onto a
  416. !    non-empty kill buffer, it appends things in the wrong order.
  417. #kill-paragraph
  418.     Kill current paragraph.
  419. !    NEEDS TO BE CHANGED TO KILL TO END OF CURRENT PARAGRAPH!!!
  420. #kill-region            [C-w]
  421.     Kill between point and mark.
  422.     The text is deleted but saved in the kill buffer.
  423.     The command C-y can retrieve it from there.
  424. #kill-word            [ESC d]
  425.     Kill characters forward until encountering the end of a word.
  426.     With argument, do this that many times.
  427. #list-buffers
  428.     Display a list of names of existing buffers.
  429.     Inserts it in buffer *Buffer List* and displays that.
  430. !    Note that buffers with names starting with spaces are listed, where
  431. !    GNU omits them. Less information listed.
  432. #load
  433.     Execute a file of Emacs commands.
  434. !    Mucho different; any of '();' comments outside of strings; only
  435. !    one-line "S-expressions" work; only present if compilation option 
  436. !    specified.
  437. #newline-and-indent        [C-j]
  438.     Insert a newline, then indent.
  439. #next-line            [C-n]
  440.     Move cursor vertically down ARG lines.
  441. !    Not like GNU, not sure of the differences.
  442. #!next-window
  443.     Move to the next window down the screen.
  444. !    Named other-window in GNU. Done this way for GOSLING freaks
  445. !    who want next and previous window.
  446. #not-modified            [ESC ~]
  447.     Clear buffer modified flag.
  448. #open-line            [C-o]
  449.     Insert a newline and leave point before it.
  450.     With arg, inserts that many newlines.
  451. #!prefix-region
  452.     Prepend a string (set by set-prefix-string) to each line
  453.     in the curernt region.  If given an argument, prompts
  454.     you for the string to use.
  455. !    Probably available in GNU under a different name or through a
  456. !    different functionality.  Intended purpose is mail quoting and
  457. !    bar comments in C code.  Compilation option.
  458. previous-line            [C-p]
  459.     Move cursor vertically up ARG lines.
  460. !    See next-line.
  461. #!previous-window
  462.     Move to the next window up the screen.
  463. !    previous-window is there for GOSLING freaks (like me).
  464. #query-replace            [ESC % ]
  465.     Replace some occurrences of FROM-STRING with TO-STRING.
  466.     As each match is found, the user must type a character saying
  467.     what to do with it.
  468.     Type Help char within query-replace for directions.
  469. !    Not quite as sharp as GNU version
  470. #quoted-insert            [C-q]
  471.     Read next input character and insert it.
  472.     Useful for inserting control characters.
  473. !    Doesn't handle the 3 octal digits case.
  474. #recenter            [C-l]
  475.     Center point in window and redisplay screen.  With ARG, put point
  476.     on line ARG.  The desired position of point is always relative
  477.     to the current window.  Also forces full screen refresh.
  478. #save-buffer            [C-x C-s]
  479.     Save current buffer in visited file.
  480. !    Always saves buffer, even if it isn't modified.
  481. #save-buffers-kill-emacs    [C-x C-c]
  482.     Offer to save each buffer, then kill this Emacs.
  483. #save-some-buffers        [C-x s]
  484.     Save some modified file-visiting buffers.  Asks user about each one.
  485.     With argument, saves all with no questions.
  486. #scroll-down            [ESC v]
  487.     Scroll text of current window downward ARG lines; or near full
  488.     screen if no ARG.
  489. #scroll-other-window        [ESC C-v]
  490.     Scroll text of next window upward ARG lines; or near full screen
  491.     if no ARG. The next window is the one below the current one; or
  492.     the one at the top if the current one is at the bottom.
  493. #scroll-up            [C-v]
  494.     Scroll text of current window upward ARG lines; or near full
  495.     screen if no ARG.
  496. #!search-again
  497.     Handy to have around for function keys/menus, etc.
  498. #search-backward        [ESC r]
  499.     Search backward from point for STRING.
  500. !    Last search pattern is remembered, including isearches
  501. !    Bound to C-s in uemacs, not bound in GNU
  502. #search-forward            [ESC s]
  503.     Search forward from point for STRING.
  504.     see search-backward
  505. #self-insert-command        [All printing characters]
  506.     Insert this character.
  507. #set-fill-column        [C-x f]
  508.     Set fill-column to current column, or to argument if given.
  509. !    Global, not buffer-local (no buffer-local stuff in uemacs)
  510. #set-mark-command        [C-@]
  511.     Set mark to where point is.
  512. !    No mark ring, so args don't make sense.
  513. #!set-prefix-string
  514. !    Set string used by prefix-region to put in front of each line text.
  515. !    Probably available in GNU in some other form, but this specific
  516. !    form suits a number of situations.  Compilation option.
  517. #shrink-window
  518.     Make the current window ARG lines smaller.
  519. !    Will not make the current window vanish if you try and make it
  520. !    to small; won't shrink window if you only have one window.
  521. #split-window-vertically    [C-x 2]
  522.     Split current window into two windows, one above the other.
  523. !    Behaves differently about which is going to be current window,
  524. !    Doesn't use ARG to decide how many lines to use.
  525. #start-kbd-macro        [C-x ( ]
  526.     Record subsequent keyboard input, defining a keyboard macro.
  527.     The commands are recorded even as they are executed.
  528. #suspend-emacs            [C-z] [C-x C-z]
  529.     Get a shell.  Exactly what shell depends on the system you
  530.     are on.
  531. #switch-to-buffer        [C-x b]
  532.     Select the specified buffer in the current window.
  533. !    Memory of old buffer names doesn't work quite as well.
  534. #switch-to-buffer-other-window    [C-x 4 b]
  535.     Switch to specified buffer in another window.
  536. !    See switch-to-buffer
  537. #transpose-chars        [C-t]
  538.     Interchange characters around point, moving forward one character.
  539. !    Doesn't work across newlines, ignores args
  540. #upcase-region            [C-x C-u]
  541.     Convert the region to upper case.
  542. #upcase-word            [ESC u]
  543.     Convert the following word (or ARG words) to upper case, moving over.
  544. !    Doesn't handle negative arguments.
  545. #what-cursor-position        [C-x =]
  546.     Print info on cursor position.
  547. !    slightly more information in output.
  548. #write-file            [C-x C-w]
  549.     Write current buffer into file FILENAME. Makes FILENAME the file for
  550.     the current buffer.
  551. #yank
  552.     Reinsert the last stretch of killed text.
  553. !    Doesn't keep a kill ring, so no yanks of stuff older than
  554. !    last delete, and arg-yank does yank arg times, instead of
  555. !    getting the arg'th thing off the kill ring.
  556.  
  557.  
  558.  
  559.  
  560. SHAR_EOF
  561. fi # end of overwriting check
  562. if test -f 'def.h'
  563. then
  564.     echo shar: will not over-write existing file "'def.h'"
  565. else
  566. cat << \SHAR_EOF > 'def.h'
  567. /*
  568.  * This file is the general header file for all parts
  569.  * of the MicroEMACS display editor. It contains all of the
  570.  * general definitions and macros. It also contains some
  571.  * conditional compilation flags. All of the per-system and
  572.  * per-terminal definitions are in special header files.
  573.  * The most common reason to edit this file would be to zap
  574.  * the definition of CVMVAS or BACKUP.
  575.  */
  576. #include    "sysdef.h"        /* Order is critical.        */
  577. #include    "ttydef.h"
  578. #include    <stdio.h>
  579.  
  580. /*
  581.  * If your system and/or compiler does not support the "void" type
  582.  * then define NO_VOID_TYPE in sysdef.h.  In the absence of some
  583.  * other definition for VOID, the default in that case will be to
  584.  * turn it into an int, which works with most compilers that don't
  585.  * support void.  In the absence of any definition of VOID or
  586.  * NO_VOID_TYPE, the default is to assume void is supported, which
  587.  * should be the case for most modern C compilers.
  588.  */
  589.  
  590. #ifndef VOID
  591. #ifdef NO_VOID_TYPE
  592. #  define VOID int            /* Default for no void is int */
  593. #else
  594. #  define VOID void            /* Just use normal void */
  595. #endif /* NO_VOID_TYPE */
  596. #endif /* VOID */
  597.  
  598. /*
  599.  * Table sizes, etc.
  600.  */
  601. #ifdef    HASH
  602. #define    NSHASH    31            /* Symbol table hash size.    */
  603. #endif
  604. #define    NFILEN    80            /* Length, file name.        */
  605. #define    NBUFN    24            /* Length, buffer name.        */
  606. #ifndef NLINE            /* allow it to be defined in makefile */
  607. #define    NLINE    256            /* Length, line.        */
  608. #endif
  609. #define    NKBDM    256            /* Length, keyboard macro.    */
  610. #define    NPAT    80            /* Length, pattern.        */
  611. #define    HUGE    1000            /* A rather large number.    */
  612. #define NSRCH    128            /* Undoable search commands.    */
  613. #define    NXNAME    64            /* Length, extended command.    */
  614. #define    NKNAME    20            /* Length, key names        */
  615. /*
  616.  * Universal.
  617.  */
  618. #define    FALSE    0            /* False, no, bad, etc.        */
  619. #define    TRUE    1            /* True, yes, good, etc.    */
  620. #define    ABORT    2            /* Death, ^G, abort, etc.    */
  621.  
  622. /*
  623.  * These flag bits keep track of
  624.  * some aspects of the last command. The CFCPCN
  625.  * flag controls goal column setting. The CFKILL
  626.  * flag controls the clearing versus appending
  627.  * of data in the kill buffer.
  628.  */
  629. #define    CFCPCN    0x0001            /* Last command was C-P, C-N    */
  630. #define    CFKILL    0x0002            /* Last command was a kill    */
  631.  
  632. /*
  633.  * File I/O.
  634.  */
  635. #define    FIOSUC    0            /* Success.            */
  636. #define    FIOFNF    1            /* File not found.        */
  637. #define    FIOEOF    2            /* End of file.            */
  638. #define    FIOERR    3            /* Error.            */
  639.  
  640. /*
  641.  * Directory I/O.
  642.  */
  643. #define    DIOSUC    0            /* Success.            */
  644. #define    DIOEOF    1            /* End of file.            */
  645. #define    DIOERR    2            /* Error.            */
  646.  
  647. /*
  648.  * Display colors.
  649.  */
  650. #define    CNONE    0            /* Unknown color.        */
  651. #define    CTEXT    1            /* Text color.            */
  652. #define    CMODE    2            /* Mode line color.        */
  653.  
  654. /*
  655.  * global mode
  656.  */
  657. #define    MBSMAP    0x0001            /* Map bs<->del            */
  658. #define MFLOW    0x0002            /* Use ^^ for ^Q and ^/ for ^S    */
  659. #define    MINDENT    0x0004            /* autoindent            */
  660. #define    MFILL    0x0008            /* fill mode            */
  661.  
  662. /*
  663.  * Flags for "eread".
  664.  */
  665. #define    EFFUNC    0x0001            /* Autocomplete functions.    */
  666. #define EFBUF    0x0002            /* Autocomplete buffers.    */
  667. #define EFFILE    0x0004            /* " files (maybe someday)    */
  668. #define    EFAUTO    0x0007            /* Some autocompleteion on    */
  669. #define    EFNEW    0x0008            /* New prompt.            */
  670. #define    EFCR    0x0010            /* Echo CR at end; last read.    */
  671.  
  672. /*
  673.  * Flags for "getkey".
  674.  */
  675. #define KQUOTE    0x0001            /* Get raw character        */
  676. #define    KNOMAC    0x0002            /* Don't record for macros    */
  677. #define    KPROMPT 0x0004            /* do delayed prompting        */
  678.  
  679. /*
  680.  * Flags for "ldelete"/"kinsert"
  681.  */
  682.  
  683. #define KNONE    0
  684. #define KFORW    1
  685. #define KBACK    2
  686.  
  687. /*
  688.  * Keys are represented inside using an 11 bit
  689.  * keyboard code. The transformation between the keys on
  690.  * the keyboard and 11 bit code is done by terminal specific
  691.  * code in the "kbd.c" file. The actual character is stored
  692.  * in 8 bits (DEC multinationals work); there is also a control
  693.  * flag KCTRL, a meta flag KMETA, and a control-X flag KCTLX.
  694.  * ASCII control characters are always represented using the
  695.  * KCTRL form. Although the C0 control set is free, it is
  696.  * reserved for C0 controls because it makes the communication
  697.  * between "getkey" and "getkbd" easier. The funny keys get
  698.  * mapped into the C1 control area. The KEY type is typedefed in
  699.  * sysdef.h, as it may depeond on compiler/machine.
  700.  */
  701. #define    NKEYS    2048            /* 11 bit code.            */
  702.  
  703. #define    METACH    0x1B            /* M- prefix,   Control-[, ESC    */
  704. #define    CTMECH    0x1C            /* C-M- prefix, Control-\    */
  705. #define    EXITCH    0x1D            /* Exit level,  Control-]    */
  706. #define    CTRLCH    0x1E            /* C- prefix,    Control-^    */
  707. #define    HELPCH    0x1F            /* Help key,    Control-_    */
  708.  
  709. #define    KCHAR    0x00FF            /* The basic character code.    */
  710. #define    KCTRL    0x0100            /* Control flag.        */
  711. #define    KMETA    0x0200            /* Meta flag.            */
  712. #define    KCTLX    0x0400            /* Control-X flag.        */
  713.  
  714. #define    KFIRST    0x0080            /* First special.        */
  715. #define    KLAST    0x009F            /* Last special.        */
  716.  
  717. #define    KRANDOM    0x0080            /* A "no key" code.        */
  718. #define    K01    0x0081            /* Use these names to define    */
  719. #define    K02    0x0082            /* the special keys on your    */
  720. #define    K03    0x0083            /* terminal.            */
  721. #define    K04    0x0084
  722. #define    K05    0x0085
  723. #define    K06    0x0086
  724. #define    K07    0x0087
  725. #define    K08    0x0088
  726. #define    K09    0x0089
  727. #define    K0A    0x008A
  728. #define    K0B    0x008B
  729. #define    K0C    0x008C
  730. #define    K0D    0x008D
  731. #define    K0E    0x008E
  732. #define    K0F    0x008F
  733. #define    K10    0x0090
  734. #define    K11    0x0091
  735. #define    K12    0x0092
  736. #define    K13    0x0093
  737. #define    K14    0x0094
  738. #define    K15    0x0095
  739. #define    K16    0x0096
  740. #define    K17    0x0097
  741. #define    K18    0x0098
  742. #define    K19    0x0099
  743. #define    K1A    0x009A
  744. #define    K1B    0x009B
  745. #define    K1C    0x009C
  746. #define    K1D    0x009D
  747. #define    K1E    0x009E
  748. #define    K1F    0x009F
  749.  
  750. #ifndef SEOL        /* needed for OSK, where '\r' == '\n' */
  751. #  define SEOL '\n'
  752. #endif
  753.  
  754. /*
  755.  * These flags, and the macros below them,
  756.  * make up a do-it-yourself set of "ctype" macros that
  757.  * understand the DEC multinational set, and let me ask
  758.  * a slightly different set of questions.
  759.  */
  760. #define    _W    0x01            /* Word.            */
  761. #define    _U    0x02            /* Upper case letter.        */
  762. #define    _L    0x04            /* Lower case letter.        */
  763. #define    _C    0x08            /* Control.            */
  764. #define _P    0x10            /* end of sentence punctuation    */
  765.  
  766. #define    ISWORD(c)    ((cinfo[(c)]&_W)!=0)
  767. #define    ISCTRL(c)    ((cinfo[(c)]&_C)!=0)
  768. #define    ISUPPER(c)    ((cinfo[(c)]&_U)!=0)
  769. #define    ISLOWER(c)    ((cinfo[(c)]&_L)!=0)
  770. #define    ISEOSP(c)    ((cinfo[(c)]&_P)!=0)
  771. #define    TOUPPER(c)    ((c)-0x20)
  772. #define    TOLOWER(c)    ((c)+0x20)
  773.  
  774. /*
  775.  * generally useful thing for chars
  776.  */
  777. #define CCHR(x)        ((x)-'@')
  778.  
  779. /*
  780.  * All repeated structures are kept as linked lists of structures.
  781.  * All of these start with a LIST structure (except lines, which
  782.  * have their own abstraction). This will allow for
  783.  * later conversion to generic list manipulation routines should
  784.  * I decide to do that. it does mean that there are four extra
  785.  * bytes per window. I feel that this is an acceptable price,
  786.  * considering that there are usually only one or two windows.
  787.  */
  788. typedef struct LIST {
  789.     union {
  790.         struct SYMBOL    *l_sp;
  791.         struct WINDOW    *l_wp;
  792.         struct BUFFER    *l_bp;
  793.         struct LIST    *l_nxt;
  794.     } l_p;
  795.     char    *l_name;
  796. } LIST;
  797. /*
  798.  * Usual hack - to keep from uglifying the code with lotsa
  799.  * references through the union, we #define something for it.
  800.  */
  801. #define    l_next    l_p.l_nxt
  802.  
  803. /*
  804.  * The symbol table links editing functions
  805.  * to names. Entries in the key map point at the symbol
  806.  * table entry.
  807.  */
  808. typedef    struct    SYMBOL {
  809.     LIST    s_list;            /* List chain.            */
  810.     int    (*s_funcp)();        /* Function.            */
  811. #ifdef    HASH
  812.     short    s_flags;        /* Flags for this symbol    */
  813. #endif
  814. }    SYMBOL;
  815. #define    s_symp    s_list.l_p.l_sp
  816. #define s_name    s_list.l_name
  817. #ifdef    HASH
  818. #define SFEND    0x001            /* End of has list        */
  819. #endif
  820.  
  821. /*
  822.  * There is a window structure allocated for
  823.  * every active display window. The windows are kept in a
  824.  * big list, in top to bottom screen order, with the listhead at
  825.  * "wheadp". Each window contains its own values of dot and mark.
  826.  * The flag field contains some bits that are set by commands
  827.  * to guide redisplay; although this is a bit of a compromise in
  828.  * terms of decoupling, the full blown redisplay is just too
  829.  * expensive to run for every input character. 
  830.  */
  831. typedef    struct    WINDOW {
  832.     LIST    w_list;            /* List header               */
  833.     struct    BUFFER *w_bufp;        /* Buffer displayed in window    */
  834.     struct    LINE *w_linep;        /* Top line in the window    */
  835.     struct    LINE *w_dotp;        /* Line containing "."        */
  836.     struct    LINE *w_markp;        /* Line containing "mark"    */
  837.     short    w_doto;            /* Byte offset for "."        */
  838.     short    w_marko;        /* Byte offset for "mark"    */
  839.     char    w_toprow;        /* Origin 0 top row of window    */
  840.     char    w_ntrows;        /* # of rows of text in window    */
  841.     char    w_force;        /* If NZ, forcing row.        */
  842.     char    w_flag;            /* Flags.            */
  843. }    WINDOW;
  844. #define    w_wndp    w_list.l_p.l_wp
  845. #define w_name    w_list.l_name
  846.  
  847. /*
  848.  * Window flags are set by command processors to
  849.  * tell the display system what has happened to the buffer
  850.  * mapped by the window. Setting "WFHARD" is always a safe thing
  851.  * to do, but it may do more work than is necessary. Always try
  852.  * to set the simplest action that achieves the required update.
  853.  * Because commands set bits in the "w_flag", update will see
  854.  * all change flags, and do the most general one.
  855.  */
  856. #define    WFFORCE    0x01            /* Force reframe.        */
  857. #define    WFMOVE    0x02            /* Movement from line to line.    */
  858. #define    WFEDIT    0x04            /* Editing within a line.    */
  859. #define    WFHARD    0x08            /* Better to a full display.    */
  860. #define    WFMODE    0x10            /* Update mode line.        */
  861.  
  862. /*
  863.  * Text is kept in buffers. A buffer header, described
  864.  * below, exists for every buffer in the system. The buffers are
  865.  * kept in a big list, so that commands that search for a buffer by
  866.  * name can find the buffer header. There is a safe store for the
  867.  * dot and mark in the header, but this is only valid if the buffer
  868.  * is not being displayed (that is, if "b_nwnd" is 0). The text for
  869.  * the buffer is kept in a circularly linked list of lines, with
  870.  * a pointer to the header line in "b_linep".
  871.  */
  872. typedef    struct    BUFFER {
  873.     LIST    b_list;            /* buffer list pointer        */
  874.     struct    BUFFER *b_altb;        /* Link to alternate buffer    */
  875.     struct    LINE *b_dotp;        /* Link to "." LINE structure    */
  876.     struct    LINE *b_markp;        /* The same as the above two,    */
  877.     struct    LINE *b_linep;        /* Link to the header LINE    */
  878.     short    b_doto;            /* Offset of "." in above LINE    */
  879.     short    b_marko;        /* but for the "mark"        */
  880.     char    b_nwnd;            /* Count of windows on buffer    */
  881.     char    b_flag;            /* Flags            */
  882.     char    b_fname[NFILEN];    /* File name            */
  883. }    BUFFER;
  884. #define    b_bufp    b_list.l_p.l_bp
  885. #define b_bname    b_list.l_name
  886.  
  887. #define    BFCHG    0x01            /* Changed.            */
  888. #define    BFBAK    0x02            /* Need to make a backup.    */
  889.  
  890. /*
  891.  * This structure holds the starting position
  892.  * (as a line/offset pair) and the number of characters in a
  893.  * region of a buffer. This makes passing the specification
  894.  * of a region around a little bit easier.
  895.  */
  896. typedef    struct    {
  897.     struct    LINE *r_linep;        /* Origin LINE address.        */
  898.     short    r_offset;        /* Origin LINE offset.        */
  899.     RSIZE    r_size;            /* Length in characters.    */
  900. }    REGION;
  901.  
  902. /*
  903.  * All text is kept in circularly linked
  904.  * lists of "LINE" structures. These begin at the
  905.  * header line (which is the blank line beyond the
  906.  * end of the buffer). This line is pointed to by
  907.  * the "BUFFER". Each line contains a the number of
  908.  * bytes in the line (the "used" size), the size
  909.  * of the text array, and the text. The end of line
  910.  * is not stored as a byte; it's implied. Future
  911.  * additions will include update hints, and a
  912.  * list of marks into the line.
  913.  */
  914. typedef    struct    LINE {
  915.     struct    LINE *l_fp;        /* Link to the next line    */
  916.     struct    LINE *l_bp;        /* Link to the previous line    */
  917.     short    l_size;            /* Allocated size        */
  918.     short    l_used;            /* Used size            */
  919. #ifdef    PCC
  920.     char    l_text[1];        /* A bunch of characters.    */
  921. #else
  922.     char    l_text[];        /* A bunch of characters.    */
  923. #endif
  924. }    LINE;
  925.  
  926. /*
  927.  * The rationale behind these macros is that you
  928.  * could (with some editing, like changing the type of a line
  929.  * link from a "LINE *" to a "REFLINE", and fixing the commands
  930.  * like file reading that break the rules) change the actual
  931.  * storage representation of lines to use something fancy on
  932.  * machines with small address spaces.
  933.  */
  934. #define    lforw(lp)    ((lp)->l_fp)
  935. #define    lback(lp)    ((lp)->l_bp)
  936. #define    lgetc(lp, n)    ((lp)->l_text[(n)]&0xFF)
  937. #define    lputc(lp, n, c)    ((lp)->l_text[(n)]=(c))
  938. #define    llength(lp)    ((lp)->l_used)
  939. #define    ltext(lp)    ((lp)->l_text)
  940.  
  941. /*
  942.  * Externals.
  943.  */
  944. extern    int    thisflag;
  945. extern    int    lastflag;
  946. extern    int    curgoal;
  947. extern    int    epresf;
  948. extern    int    sgarbf;
  949. extern    int    mode;
  950. extern    WINDOW    *curwp;
  951. extern    BUFFER    *curbp;
  952. extern    WINDOW    *wheadp;
  953. extern    BUFFER    *bheadp;
  954. extern    KEY    kbdm[];
  955. extern    KEY    *kbdmip;
  956. extern    KEY    *kbdmop;
  957. extern    KEY    getkey();
  958. extern    char    pat[];
  959. extern    SYMBOL    *symbol[];
  960. extern    SYMBOL    *binding[];
  961. extern    BUFFER    *bfind();
  962. extern    WINDOW    *popbuf();
  963. extern    WINDOW    *wpopup();
  964. extern    LINE    *lalloc();
  965. extern  int    nrow;
  966. extern  int    ncol;
  967. extern    char    *version;
  968. extern    int    ttrow;
  969. extern    int    ttcol;
  970. extern    int    tceeol;
  971. extern    int    tcinsl;
  972. extern    int    tcdell;
  973. extern    char    cinfo[];
  974. extern    char    *keystrings[];
  975. extern    SYMBOL    *symlookup();
  976. VOID        update();
  977. VOID        keyname();
  978. /*
  979.  * Standard I/O.
  980.  */
  981. extern    char    *strcpy();
  982. extern    char    *strcat();
  983. extern    char    *malloc();
  984. SHAR_EOF
  985. fi # end of overwriting check
  986. if test -f 'display.c'
  987. then
  988.     echo shar: will not over-write existing file "'display.c'"
  989. else
  990. cat << \SHAR_EOF > 'display.c'
  991. /*
  992.  * The functions in this file handle redisplay. The
  993.  * redisplay system knows almost nothing about the editing
  994.  * process; the editing functions do, however, set some
  995.  * hints to eliminate a lot of the grinding. There is more
  996.  * that can be done; the "vtputc" interface is a real
  997.  * pig. Two conditional compilation flags; the GOSLING
  998.  * flag enables dynamic programming redisplay, using the
  999.  * algorithm published by Jim Gosling in SIGOA. The MEMMAP
  1000.  * changes things around for memory mapped video. With
  1001.  * both off, the terminal is a VT52.
  1002.  */
  1003. #include    "def.h"
  1004.  
  1005. /*
  1006.  * You can change these back to the types
  1007.  * implied by the name if you get tight for space. If you
  1008.  * make both of them "int" you get better code on the VAX.
  1009.  * They do nothing if this is not Gosling redisplay, except
  1010.  * for change the size of a structure that isn't used.
  1011.  * A bit of a cheat.
  1012.  */
  1013. /* These defines really belong in sysdef.h */
  1014. #ifndef XCHAR
  1015. #  define    XCHAR    int
  1016. #  define    XSHORT    int
  1017. #endif
  1018.  
  1019. #ifdef    STANDOUT_GLITCH
  1020. extern int SG;                /* number of standout glitches    */
  1021. #endif
  1022.  
  1023. /*
  1024.  * A video structure always holds
  1025.  * an array of characters whose length is equal to
  1026.  * the longest line possible. Only some of this is
  1027.  * used if "ncol" isn't the same as "NCOL".
  1028.  */
  1029. typedef    struct    {
  1030.     short    v_hash;            /* Hash code, for compares.    */
  1031.     short    v_flag;            /* Flag word.            */
  1032.     short    v_color;        /* Color of the line.        */
  1033.     XSHORT    v_cost;            /* Cost of display.        */
  1034.     char    v_text[NCOL];        /* The actual characters.    */
  1035. }    VIDEO;
  1036.  
  1037. #define    VFCHG    0x0001            /* Changed.            */
  1038. #define    VFHBAD    0x0002            /* Hash and cost are bad.    */
  1039.  
  1040. /*
  1041.  * SCORE structures hold the optimal
  1042.  * trace trajectory, and the cost of redisplay, when
  1043.  * the dynamic programming redisplay code is used.
  1044.  * If no fancy redisplay, this isn't used. The trace index
  1045.  * fields can be "char", and the score a "short", but
  1046.  * this makes the code worse on the VAX.
  1047.  */
  1048. typedef    struct    {
  1049.     XCHAR    s_itrace;        /* "i" index for track back.    */
  1050.     XCHAR    s_jtrace;        /* "j" index for trace back.    */
  1051.     XSHORT    s_cost;            /* Display cost.        */
  1052. }    SCORE;
  1053.  
  1054. int    sgarbf    = TRUE;            /* TRUE if screen is garbage.    */
  1055. int    vtrow    = 0;            /* Virtual cursor row.        */
  1056. int    vtcol    = 0;            /* Virtual cursor column.    */
  1057. int    tthue    = CNONE;        /* Current color.        */
  1058. int    ttrow    = HUGE;            /* Physical cursor row.        */
  1059. int    ttcol    = HUGE;            /* Physical cursor column.    */
  1060. int    tttop    = HUGE;            /* Top of scroll region.    */
  1061. int    ttbot    = HUGE;            /* Bottom of scroll region.    */
  1062.  
  1063. VIDEO    *vscreen[NROW-1];        /* Edge vector, virtual.    */
  1064. VIDEO    *pscreen[NROW-1];        /* Edge vector, physical.    */
  1065. VIDEO    video[2*(NROW-1)];        /* Actual screen data.        */
  1066. VIDEO    blanks;                /* Blank line image.        */
  1067.  
  1068. #ifdef    GOSLING
  1069. /*
  1070.  * This matrix is written as an array because
  1071.  * we do funny things in the "setscores" routine, which
  1072.  * is very compute intensive, to make the subscripts go away.
  1073.  * It would be "SCORE    score[NROW][NROW]" in old speak.
  1074.  * Look at "setscores" to understand what is up.
  1075.  */
  1076. SCORE    score[NROW*NROW];
  1077. #endif
  1078.  
  1079. /*
  1080.  * Initialize the data structures used
  1081.  * by the display code. The edge vectors used
  1082.  * to access the screens are set up. The operating
  1083.  * system's terminal I/O channel is set up. Fill the
  1084.  * "blanks" array with ASCII blanks. The rest is done
  1085.  * at compile time. The original window is marked
  1086.  * as needing full update, and the physical screen
  1087.  * is marked as garbage, so all the right stuff happens
  1088.  * on the first call to redisplay.
  1089.  */
  1090. vtinit() {
  1091.     register VIDEO    *vp;
  1092.     register int    i;
  1093.  
  1094.     ttopen();
  1095.     ttinit();
  1096.     vp = &video[0];
  1097.     for (i=0; i<NROW-1; ++i) {
  1098.         vscreen[i] = vp;
  1099.         ++vp;
  1100.         pscreen[i] = vp;
  1101.         ++vp;
  1102.     }
  1103.     blanks.v_color = CTEXT;
  1104.     for (i=0; i<NCOL; ++i)
  1105.         blanks.v_text[i] = ' ';
  1106. }
  1107.  
  1108. /*
  1109.  * Tidy up the virtual display system
  1110.  * in anticipation of a return back to the host
  1111.  * operating system. Right now all we do is position
  1112.  * the cursor to the last line, erase the line, and
  1113.  * close the terminal channel.
  1114.  */
  1115. vttidy() {
  1116.     ttcolor(CTEXT);
  1117.     ttnowindow();                /* No scroll window.    */
  1118.     ttmove(nrow-1, 0);            /* Echo line.        */
  1119.     tteeol();
  1120.     tttidy();
  1121.     ttflush();
  1122.     ttclose();
  1123. }
  1124.  
  1125. /*
  1126.  * Move the virtual cursor to an origin
  1127.  * 0 spot on the virtual display screen. I could
  1128.  * store the column as a character pointer to the spot
  1129.  * on the line, which would make "vtputc" a little bit
  1130.  * more efficient. No checking for errors.
  1131.  */
  1132. vtmove(row, col) {
  1133.     vtrow = row;
  1134.     vtcol = col;
  1135. }
  1136.  
  1137. /*
  1138.  * Write a character to the virtual display,
  1139.  * dealing with long lines and the display of unprintable
  1140.  * things like control characters. Also expand tabs every 8
  1141.  * columns. This code only puts printing characters into 
  1142.  * the virtual display image. Special care must be taken when
  1143.  * expanding tabs. On a screen whose width is not a multiple
  1144.  * of 8, it is possible for the virtual cursor to hit the
  1145.  * right margin before the next tab stop is reached. This
  1146.  * makes the tab code loop if you are not careful.
  1147.  * Three guesses how we found this.
  1148.  */
  1149. vtputc(c) register int c; {
  1150.     register VIDEO    *vp;
  1151.  
  1152.     vp = vscreen[vtrow];
  1153.     if (vtcol >= ncol)
  1154.         vp->v_text[ncol-1] = '$';
  1155.     else if (c == '\t') {
  1156.         do {
  1157.             vtputc(' ');
  1158.         } while (vtcol<ncol && (vtcol&0x07)!=0);
  1159.     } else if (ISCTRL(c) != FALSE) {
  1160.         vtputc('^');
  1161.         vtputc(c ^ 0x40);
  1162.     } else
  1163.         vp->v_text[vtcol++] = c;        
  1164. }
  1165.  
  1166. /*
  1167.  * Erase from the end of the
  1168.  * software cursor to the end of the
  1169.  * line on which the software cursor is
  1170.  * located. The display routines will decide
  1171.  * if a hardware erase to end of line command
  1172.  * should be used to display this.
  1173.  */
  1174. vteeol() {
  1175.     register VIDEO    *vp;
  1176.  
  1177.     vp = vscreen[vtrow];
  1178.     while (vtcol < ncol)
  1179.         vp->v_text[vtcol++] = ' ';
  1180. }
  1181.  
  1182. /*
  1183.  * Make sure that the display is
  1184.  * right. This is a three part process. First,
  1185.  * scan through all of the windows looking for dirty
  1186.  * ones. Check the framing, and refresh the screen.
  1187.  * Second, make sure that "currow" and "curcol" are
  1188.  * correct for the current window. Third, make the
  1189.  * virtual and physical screens the same.
  1190.  */
  1191. VOID
  1192. update() {
  1193.     register LINE    *lp;
  1194.     register WINDOW    *wp;
  1195.     register VIDEO    *vp1;
  1196.     register VIDEO    *vp2;
  1197.     register int    i;
  1198.     register int    j;
  1199.     register int    c;
  1200.     register int    hflag;
  1201.     register int    currow;
  1202.     register int    curcol;
  1203.     register int    offs;
  1204.     register int    size;
  1205.     VOID traceback ();
  1206.     VOID uline ();
  1207.  
  1208.     if (typeahead()) return;
  1209.     if (sgarbf) {                /* must update everything */
  1210.         wp = wheadp; 
  1211.         while(wp != NULL) {
  1212.             wp->w_flag |= WFMODE | WFHARD;
  1213.             wp = wp->w_wndp;
  1214.         }
  1215.     }
  1216.     hflag = FALSE;                /* Not hard.        */
  1217.     wp = wheadp;
  1218.     while (wp != NULL) {
  1219.         if (wp->w_flag != 0) {        /* Need update.        */
  1220.             if ((wp->w_flag&WFFORCE) == 0) {
  1221.                 lp = wp->w_linep;
  1222.                 for (i=0; i<wp->w_ntrows; ++i) {
  1223.                     if (lp == wp->w_dotp)
  1224.                         goto out;
  1225.                     if (lp == wp->w_bufp->b_linep)
  1226.                         break;
  1227.                     lp = lforw(lp);
  1228.                 }
  1229.             }
  1230.             i = wp->w_force;    /* Reframe this one.    */
  1231.             if (i > 0) {
  1232.                 --i;
  1233.                 if (i >= wp->w_ntrows)
  1234.                     i = wp->w_ntrows-1;
  1235.             } else if (i < 0) {
  1236.                 i += wp->w_ntrows;
  1237.                 if (i < 0)
  1238.                     i = 0;
  1239.             } else
  1240.                 i = wp->w_ntrows/2;
  1241.             lp = wp->w_dotp;
  1242.             while (i!=0 && lback(lp)!=wp->w_bufp->b_linep) {
  1243.                 --i;
  1244.                 lp = lback(lp);
  1245.             }
  1246.             wp->w_linep = lp;
  1247.             wp->w_flag |= WFHARD;    /* Force full.        */
  1248.         out:
  1249.             lp = wp->w_linep;    /* Try reduced update.    */
  1250.             i  = wp->w_toprow;
  1251.             if ((wp->w_flag&~WFMODE) == WFEDIT) {
  1252.                 while (lp != wp->w_dotp) {
  1253.                     ++i;
  1254.                     lp = lforw(lp);
  1255.                 }
  1256.                 vscreen[i]->v_color = CTEXT;
  1257.                 vscreen[i]->v_flag |= (VFCHG|VFHBAD);
  1258.                 vtmove(i, 0);
  1259.                 for (j=0; j<llength(lp); ++j)
  1260.                     vtputc(lgetc(lp, j));
  1261.                 vteeol();
  1262.             } else if ((wp->w_flag&(WFEDIT|WFHARD)) != 0) {
  1263.                 hflag = TRUE;
  1264.                 while (i < wp->w_toprow+wp->w_ntrows) {
  1265.                     vscreen[i]->v_color = CTEXT;
  1266.                     vscreen[i]->v_flag |= (VFCHG|VFHBAD);
  1267.                     vtmove(i, 0);
  1268.                     if (lp != wp->w_bufp->b_linep) {
  1269.                         for (j=0; j<llength(lp); ++j)
  1270.                             vtputc(lgetc(lp, j));
  1271.                         lp = lforw(lp);
  1272.                     }
  1273.                     vteeol();
  1274.                     ++i;
  1275.                 }
  1276.             }
  1277.             if ((wp->w_flag&WFMODE) != 0)
  1278.                 modeline(wp);
  1279.             wp->w_flag  = 0;
  1280.             wp->w_force = 0;
  1281.         }        
  1282.         wp = wp->w_wndp;
  1283.     }
  1284.     lp = curwp->w_linep;            /* Cursor location.    */
  1285.     currow = curwp->w_toprow;
  1286.     while (lp != curwp->w_dotp) {
  1287.         ++currow;
  1288.         lp = lforw(lp);
  1289.     }
  1290.     curcol = 0;
  1291.     i = 0;
  1292.     while (i < curwp->w_doto) {
  1293.         c = lgetc(lp, i++);
  1294.         if (c == '\t')
  1295.             curcol |= 0x07;
  1296.         else if (ISCTRL(c) != FALSE)
  1297.             ++curcol;
  1298.         ++curcol;
  1299.     }
  1300.     if (curcol >= ncol)            /* Long line.        */
  1301.         curcol = ncol-1;
  1302.     if (sgarbf != FALSE) {            /* Screen is garbage.    */
  1303.         sgarbf = FALSE;            /* Erase-page clears    */
  1304.         epresf = FALSE;            /* the message area.    */
  1305.         tttop  = HUGE;            /* Forget where you set    */
  1306.         ttbot  = HUGE;            /* scroll region.    */
  1307.         tthue  = CNONE;            /* Color unknown.    */
  1308.         ttmove(0, 0);
  1309.         tteeop();
  1310.         for (i=0; i<nrow-1; ++i) {
  1311.             uline(i, vscreen[i], &blanks);
  1312.             ucopy(vscreen[i], pscreen[i]);
  1313.         }
  1314.         ttmove(currow, curcol);
  1315.         ttflush();
  1316.         return;
  1317.     }
  1318. #ifdef    GOSLING
  1319.     if (hflag != FALSE) {            /* Hard update?        */
  1320.         for (i=0; i<nrow-1; ++i) {    /* Compute hash data.    */
  1321.             hash(vscreen[i]);
  1322.             hash(pscreen[i]);
  1323.         }
  1324.         offs = 0;            /* Get top match.    */
  1325.         while (offs != nrow-1) {
  1326.             vp1 = vscreen[offs];
  1327.             vp2 = pscreen[offs];
  1328.             if (vp1->v_color != vp2->v_color
  1329.             ||  vp1->v_hash  != vp2->v_hash)
  1330.                 break;
  1331.             uline(offs, vp1, vp2);
  1332.             ucopy(vp1, vp2);
  1333.             ++offs;
  1334.         }
  1335.         if (offs == nrow-1) {        /* Might get it all.    */
  1336.             ttmove(currow, curcol);
  1337.             ttflush();
  1338.             return;
  1339.         }
  1340.         size = nrow-1;            /* Get bottom match.    */
  1341.         while (size != offs) {
  1342.             vp1 = vscreen[size-1];
  1343.             vp2 = pscreen[size-1];
  1344.             if (vp1->v_color != vp2->v_color
  1345.             ||  vp1->v_hash  != vp2->v_hash)
  1346.                 break;
  1347.             uline(size-1, vp1, vp2);
  1348.             ucopy(vp1, vp2);
  1349.             --size;
  1350.         }
  1351.         if ((size -= offs) == 0)    /* Get screen size.    */
  1352.             panic("Illegal screen size in update");
  1353.         setscores(offs, size);        /* Do hard update.    */
  1354.         traceback(offs, size, size, size);
  1355.         for (i=0; i<size; ++i)
  1356.             ucopy(vscreen[offs+i], pscreen[offs+i]);
  1357.         ttmove(currow, curcol);
  1358.         ttflush();
  1359.         return;            
  1360.     }
  1361. #endif
  1362.     for (i=0; i<nrow-1; ++i) {        /* Easy update.        */
  1363.         vp1 = vscreen[i];
  1364.         vp2 = pscreen[i];
  1365.         if ((vp1->v_flag&VFCHG) != 0) {
  1366.             uline(i, vp1, vp2);
  1367.             ucopy(vp1, vp2);
  1368.         }
  1369.     }
  1370.     ttmove(currow, curcol);
  1371.     ttflush();
  1372. }
  1373.  
  1374. /*
  1375.  * Update a saved copy of a line,
  1376.  * kept in a VIDEO structure. The "vvp" is
  1377.  * the one in the "vscreen". The "pvp" is the one
  1378.  * in the "pscreen". This is called to make the
  1379.  * virtual and physical screens the same when
  1380.  * display has done an update.
  1381.  */
  1382. ucopy(vvp, pvp) register VIDEO *vvp; register VIDEO *pvp; {
  1383.  
  1384.     vvp->v_flag &= ~VFCHG;            /* Changes done.    */
  1385.     pvp->v_flag  = vvp->v_flag;        /* Update model.    */
  1386.     pvp->v_hash  = vvp->v_hash;
  1387.     pvp->v_cost  = vvp->v_cost;
  1388.     pvp->v_color = vvp->v_color;
  1389.     bcopy(vvp->v_text, pvp->v_text, ncol);
  1390. }
  1391.  
  1392. /*
  1393.  * Update a single line. This routine only
  1394.  * uses basic functionality (no insert and delete character,
  1395.  * but erase to end of line). The "vvp" points at the VIDEO
  1396.  * structure for the line on the virtual screen, and the "pvp"
  1397.  * is the same for the physical screen. Avoid erase to end of
  1398.  * line when updating CMODE color lines, because of the way that
  1399.  * reverse video works on most terminals.
  1400.  */
  1401. VOID uline(row, vvp, pvp) VIDEO *vvp; VIDEO *pvp; {
  1402. #ifdef    MEMMAP
  1403.     putline(row+1, 1, &vvp->v_text[0]);
  1404. #else
  1405.     register char    *cp1;
  1406.     register char    *cp2;
  1407.     register char    *cp3;
  1408.     register char    *cp4;
  1409.     register char    *cp5;
  1410.     register int    nbflag;
  1411.  
  1412.     if (vvp->v_color != pvp->v_color) {    /* Wrong color, do a    */
  1413.         ttmove(row, 0);            /* full redraw.        */
  1414. #ifdef    STANDOUT_GLITCH
  1415.         if (pvp->v_color != CTEXT && SG >= 0) tteeol();
  1416. #endif
  1417.         ttcolor(vvp->v_color);
  1418. #ifdef    STANDOUT_GLITCH
  1419.         cp1 = &vvp->v_text[SG > 0 ? SG : 0];
  1420.         /* the odd code for SG==0 is to avoid putting the invisable
  1421.          * glitch character on the next line.  
  1422.          * (Hazeltine executive 80 model 30)
  1423.          */
  1424.         cp2 = &vvp->v_text[ncol - (SG >= 0 ? (SG!=0 ? SG : 1) : 0)];
  1425. #else
  1426.         cp1 = &vvp->v_text[0];
  1427.         cp2 = &vvp->v_text[ncol];
  1428. #endif
  1429.         while (cp1 != cp2) {
  1430.             ttputc(*cp1++);
  1431.             ++ttcol;
  1432.         }
  1433. #ifndef    MOVE_STANDOUT
  1434.         ttcolor(CTEXT);
  1435. #endif
  1436.         return;
  1437.     }
  1438.     cp1 = &vvp->v_text[0];            /* Compute left match.    */
  1439.     cp2 = &pvp->v_text[0];
  1440.     while (cp1!=&vvp->v_text[ncol] && cp1[0]==cp2[0]) {
  1441.         ++cp1;
  1442.         ++cp2;
  1443.     }
  1444.     if (cp1 == &vvp->v_text[ncol])        /* All equal.        */
  1445.         return;
  1446.     nbflag = FALSE;
  1447.     cp3 = &vvp->v_text[ncol];        /* Compute right match.    */
  1448.     cp4 = &pvp->v_text[ncol];
  1449.     while (cp3[-1] == cp4[-1]) {
  1450.         --cp3;
  1451.         --cp4;
  1452.         if (cp3[0] != ' ')        /* Note non-blanks in    */
  1453.             nbflag = TRUE;        /* the right match.    */
  1454.     }
  1455.     cp5 = cp3;                /* Is erase good?    */
  1456.     if (nbflag==FALSE && vvp->v_color==CTEXT) {
  1457.         while (cp5!=cp1 && cp5[-1]==' ')
  1458.             --cp5;
  1459.         /* Alcyon hack */
  1460.         if ((int)(cp3-cp5) <= tceeol)
  1461.             cp5 = cp3;
  1462.     }
  1463.     /* Alcyon hack */
  1464.     ttmove(row, (int)(cp1-&vvp->v_text[0]));
  1465. #ifdef    STANDOUT_GLITCH
  1466.     if (vvp->v_color != CTEXT && SG > 0) {
  1467.         if(cp1 < &vvp->v_text[SG]) cp1 = &vvp->v_text[SG];
  1468.         if(cp5 > &vvp->v_text[ncol-SG]) cp5 = &vvp->v_text[ncol-SG];
  1469.     } else if (SG < 0)
  1470. #endif
  1471.     ttcolor(vvp->v_color);
  1472.     while (cp1 != cp5) {
  1473.         ttputc(*cp1++);
  1474.         ++ttcol;
  1475.     }
  1476.     if (cp5 != cp3)                /* Do erase.        */
  1477.         tteeol();
  1478. #endif
  1479. }
  1480.  
  1481. /*
  1482.  * Redisplay the mode line for
  1483.  * the window pointed to by the "wp".
  1484.  * This is the only routine that has any idea
  1485.  * of how the modeline is formatted. You can
  1486.  * change the modeline format by hacking at
  1487.  * this routine. Called by "update" any time
  1488.  * there is a dirty window.
  1489.  * Note that if STANDOUT_GLITCH is defined, first and last SG characters
  1490.  * may never be seen.
  1491.  */
  1492. modeline(wp) register WINDOW *wp; {
  1493.     register int    n;
  1494.     register BUFFER    *bp;
  1495.  
  1496.     n = wp->w_toprow+wp->w_ntrows;        /* Location.        */
  1497.     vscreen[n]->v_color = CMODE;        /* Mode line color.    */
  1498.     vscreen[n]->v_flag |= (VFCHG|VFHBAD);    /* Recompute, display.    */
  1499.     vtmove(n, 0);                /* Seek to right line.    */
  1500.     bp = wp->w_bufp;
  1501.     vtputc('-'); vtputc('-');
  1502.     if ((bp->b_flag&BFCHG) != 0) {        /* "*" if changed.    */
  1503.         vtputc('*'); vtputc('*');
  1504.     } else {
  1505.         vtputc('-'); vtputc('-');
  1506.     }
  1507.     vtputc('-');
  1508.     n  = 5;
  1509.     n += vtputs("MicroGnuEmacs:");
  1510.     if (bp->b_bname[0] != 0) {
  1511.         vtputc(' ');
  1512.         ++n;
  1513.         n += vtputs(&(bp->b_bname[0]));
  1514.     }
  1515.     while (n < 42) {            /* Pad out with blanks    */
  1516.         vtputc(' ');
  1517.         ++n;
  1518.     }
  1519.     vtputc('(');
  1520.     ++n;
  1521.     if (mode == 0) n += vtputs("Fundamental");
  1522.     else {
  1523.         if ((mode&MBSMAP) != 0) {
  1524.             n += vtputs("bsmap");
  1525.             if ((mode&~MBSMAP) != 0) {
  1526.                 vtputc('-');
  1527.                 ++n;
  1528.             }
  1529.         }
  1530.         if ((mode&MFLOW) != 0) {
  1531.             n += vtputs("flow");
  1532.             if ((mode&~(MFLOW|MBSMAP)) != 0) {
  1533.                 vtputc('-');
  1534.                 ++n;
  1535.             }
  1536.         }
  1537.         if ((mode&MINDENT) != 0) {
  1538.             n += vtputs("indent");
  1539.             if ((mode&~(MINDENT|MFLOW|MBSMAP)) != 0) {
  1540.                 vtputc('-');
  1541.                 ++n;
  1542.             }
  1543.         }
  1544.         if ((mode&MFILL) != 0)
  1545.             n += vtputs("fill");
  1546.     }
  1547.     vtputc(')');
  1548.     ++n;
  1549.     while (n < ncol) {            /* Pad out.        */
  1550.         vtputc('-');
  1551.         ++n;
  1552.     }
  1553. }
  1554. /*
  1555.  * output a string to the mode line, report how long it was.
  1556.  */
  1557. vtputs(s) register char *s; {
  1558.     register int n = 0;
  1559.  
  1560.     while (*s != '\0') {
  1561.         vtputc(*s++);
  1562.         ++n;
  1563.     }
  1564.     return n;
  1565. }
  1566. #ifdef    GOSLING
  1567. /*
  1568.  * Compute the hash code for
  1569.  * the line pointed to by the "vp". Recompute
  1570.  * it if necessary. Also set the approximate redisplay
  1571.  * cost. The validity of the hash code is marked by
  1572.  * a flag bit. The cost understand the advantages
  1573.  * of erase to end of line. Tuned for the VAX
  1574.  * by Bob McNamara; better than it used to be on
  1575.  * just about any machine.
  1576.  */
  1577. hash(vp) register VIDEO *vp; {
  1578.     register int    i;
  1579.     register int    n;
  1580.     register char    *s;
  1581.  
  1582.     if ((vp->v_flag&VFHBAD) != 0) {        /* Hash bad.        */
  1583.         s = &vp->v_text[ncol-1];
  1584.         for (i=ncol; i!=0; --i, --s)
  1585.             if (*s != ' ')
  1586.                 break;
  1587.         n = ncol-i;            /* Erase cheaper?    */
  1588.         if (n > tceeol)
  1589.             n = tceeol;
  1590.         vp->v_cost = i+n;        /* Bytes + blanks.    */
  1591.         for (n=0; i!=0; --i, --s)
  1592.             n = (n<<5) + n + *s;
  1593.         vp->v_hash = n;            /* Hash code.        */
  1594.         vp->v_flag &= ~VFHBAD;        /* Flag as all done.    */
  1595.     }
  1596. }
  1597.  
  1598. /*
  1599.  * Compute the Insert-Delete
  1600.  * cost matrix. The dynamic programming algorithm
  1601.  * described by James Gosling is used. This code assumes
  1602.  * that the line above the echo line is the last line involved
  1603.  * in the scroll region. This is easy to arrange on the VT100
  1604.  * because of the scrolling region. The "offs" is the origin 0
  1605.  * offset of the first row in the virtual/physical screen that
  1606.  * is being updated; the "size" is the length of the chunk of
  1607.  * screen being updated. For a full screen update, use offs=0
  1608.  * and size=nrow-1.
  1609.  *
  1610.  * Older versions of this code implemented the score matrix by
  1611.  * a two dimensional array of SCORE nodes. This put all kinds of
  1612.  * multiply instructions in the code! This version is written to
  1613.  * use a linear array and pointers, and contains no multiplication
  1614.  * at all. The code has been carefully looked at on the VAX, with
  1615.  * only marginal checking on other machines for efficiency. In
  1616.  * fact, this has been tuned twice! Bob McNamara tuned it even
  1617.  * more for the VAX, which is a big issue for him because of
  1618.  * the 66 line X displays.
  1619.  *
  1620.  * On some machines, replacing the "for (i=1; i<=size; ++i)" with
  1621.  * i = 1; do { } while (++i <=size)" will make the code quite a
  1622.  * bit better; but it looks ugly.
  1623.  */
  1624. setscores(offs, size) {
  1625.     register SCORE    *sp;
  1626.     SCORE        *sp1;
  1627.     register int    tempcost;
  1628.     register int    bestcost;
  1629.     register int    j;
  1630.     register int    i;
  1631.     register VIDEO    **vp;
  1632.     VIDEO        **pp, **vbase, **pbase;
  1633.  
  1634.     vbase = &vscreen[offs-1];        /* By hand CSE's.    */
  1635.     pbase = &pscreen[offs-1];
  1636.     score[0].s_itrace = 0;            /* [0, 0]        */
  1637.     score[0].s_jtrace = 0;
  1638.     score[0].s_cost   = 0;
  1639.     sp = &score[1];                /* Row 0, inserts.    */
  1640.     tempcost = 0;
  1641.     vp = &vbase[1];
  1642.     for (j=1; j<=size; ++j) {
  1643.         sp->s_itrace = 0;
  1644.         sp->s_jtrace = j-1;
  1645.         tempcost += tcinsl;
  1646.         tempcost += (*vp)->v_cost;
  1647.         sp->s_cost = tempcost;
  1648.         ++vp;
  1649.         ++sp;
  1650.     }
  1651.     sp = &score[NROW];            /* Column 0, deletes.    */
  1652.     tempcost = 0;
  1653.     for (i=1; i<=size; ++i) {
  1654.         sp->s_itrace = i-1;
  1655.         sp->s_jtrace = 0;
  1656.         tempcost  += tcdell;
  1657.         sp->s_cost = tempcost;
  1658.         sp += NROW;
  1659.     }
  1660.     sp1 = &score[NROW+1];            /* [1, 1].        */
  1661.     pp = &pbase[1];
  1662.     for (i=1; i<=size; ++i) {
  1663.         sp = sp1;
  1664.         vp = &vbase[1];
  1665.         for (j=1; j<=size; ++j) {
  1666.             sp->s_itrace = i-1;
  1667.             sp->s_jtrace = j;
  1668.             bestcost = (sp-NROW)->s_cost;
  1669.             if (j != size)        /* Cd(A[i])=0 @ Dis.    */
  1670.                 bestcost += tcdell;
  1671.             tempcost = (sp-1)->s_cost;
  1672.             tempcost += (*vp)->v_cost;
  1673.             if (i != size)        /* Ci(B[j])=0 @ Dsj.    */
  1674.                 tempcost += tcinsl;
  1675.             if (tempcost < bestcost) {
  1676.                 sp->s_itrace = i;
  1677.                 sp->s_jtrace = j-1;
  1678.                 bestcost = tempcost;
  1679.             }
  1680.             tempcost = (sp-NROW-1)->s_cost;
  1681.             if ((*pp)->v_color != (*vp)->v_color
  1682.             ||  (*pp)->v_hash  != (*vp)->v_hash)
  1683.                 tempcost += (*vp)->v_cost;
  1684.             if (tempcost < bestcost) {
  1685.                 sp->s_itrace = i-1;
  1686.                 sp->s_jtrace = j-1;
  1687.                 bestcost = tempcost;
  1688.             }
  1689.             sp->s_cost = bestcost;
  1690.             ++sp;            /* Next column.        */
  1691.             ++vp;
  1692.         }
  1693.         ++pp;
  1694.         sp1 += NROW;            /* Next row.        */
  1695.     }
  1696. }
  1697.  
  1698. /*
  1699.  * Trace back through the dynamic programming cost
  1700.  * matrix, and update the screen using an optimal sequence
  1701.  * of redraws, insert lines, and delete lines. The "offs" is
  1702.  * the origin 0 offset of the chunk of the screen we are about to
  1703.  * update. The "i" and "j" are always started in the lower right
  1704.  * corner of the matrix, and imply the size of the screen.
  1705.  * A full screen traceback is called with offs=0 and i=j=nrow-1.
  1706.  * There is some do-it-yourself double subscripting here,
  1707.  * which is acceptable because this routine is much less compute
  1708.  * intensive then the code that builds the score matrix!
  1709.  */
  1710. VOID traceback(offs, size, i, j) {
  1711.     register int    itrace;
  1712.     register int    jtrace;
  1713.     register int    k;
  1714.     register int    ninsl;
  1715.     register int    ndraw;
  1716.     register int    ndell;
  1717.  
  1718.     if (i==0 && j==0)            /* End of update.    */
  1719.         return;
  1720.     itrace = score[(NROW*i) + j].s_itrace;
  1721.     jtrace = score[(NROW*i) + j].s_jtrace;
  1722.     if (itrace == i) {            /* [i, j-1]        */
  1723.         ninsl = 0;            /* Collect inserts.    */
  1724.         if (i != size)
  1725.             ninsl = 1;
  1726.         ndraw = 1;
  1727.         while (itrace!=0 || jtrace!=0) {
  1728.             if (score[(NROW*itrace) + jtrace].s_itrace != itrace)
  1729.                 break;
  1730.             jtrace = score[(NROW*itrace) + jtrace].s_jtrace;
  1731.             if (i != size)
  1732.                 ++ninsl;
  1733.             ++ndraw;
  1734.         }
  1735.         traceback(offs, size, itrace, jtrace);
  1736.         if (ninsl != 0) {
  1737.             ttcolor(CTEXT);
  1738.             ttinsl(offs+j-ninsl, offs+size-1, ninsl);
  1739.         }
  1740.         do {                /* B[j], A[j] blank.    */
  1741.             k = offs+j-ndraw;
  1742.             uline(k, vscreen[k], &blanks);
  1743.         } while (--ndraw);
  1744.         return;
  1745.     }
  1746.     if (jtrace == j) {            /* [i-1, j]        */
  1747.         ndell = 0;            /* Collect deletes.    */
  1748.         if (j != size)
  1749.             ndell = 1;
  1750.         while (itrace!=0 || jtrace!=0) {
  1751.             if (score[(NROW*itrace) + jtrace].s_jtrace != jtrace)
  1752.                 break;
  1753.             itrace = score[(NROW*itrace) + jtrace].s_itrace;
  1754.             if (j != size)
  1755.                 ++ndell;
  1756.         }
  1757.         if (ndell != 0) {
  1758.             ttcolor(CTEXT);
  1759.             ttdell(offs+i-ndell, offs+size-1, ndell);
  1760.         }
  1761.         traceback(offs, size, itrace, jtrace);
  1762.         return;
  1763.     }
  1764.     traceback(offs, size, itrace, jtrace);
  1765.     k = offs+j-1;
  1766.     uline(k, vscreen[k], pscreen[offs+i-1]);
  1767. }
  1768. #endif
  1769. SHAR_EOF
  1770. fi # end of overwriting check
  1771. if test -f 'kbd.c'
  1772. then
  1773.     echo shar: will not over-write existing file "'kbd.c'"
  1774. else
  1775. cat << \SHAR_EOF > 'kbd.c'
  1776. /*
  1777.  *        Terminal independent keyboard handling.
  1778.  */
  1779. #include    "def.h"
  1780.  
  1781. #ifdef    DPROMPT
  1782. #define    PROMPTL    80
  1783.   char    prompt[PROMPTL], *promptp;
  1784. #endif
  1785.  
  1786. /*
  1787.  * All input from the user (should!) go through
  1788.  * getkey. Quotep is true to get raw keys, false to
  1789.  * get 11-bit code keys.
  1790.  * Getkey is responsible for putting keystrokes away
  1791.  * for macros. It also takes keystrokes out of the macro,
  1792.  * though other input routines will can also do this.
  1793.  * Read in a key, doing the terminal
  1794.  * independent prefix handling. The terminal specific
  1795.  * "getkbd" routine gets the first swing, and may return
  1796.  * one of the special codes used by the special keys
  1797.  * on the keyboard. The "getkbd" routine returns the
  1798.  * C0 controls as received; this routine moves them to
  1799.  * the right spot in 11 bit code.
  1800.  * If the KPROMPT bit in the flags is set and DPROMPT is
  1801.  * defined, do delayed prompting.  (dprompt routine is 
  1802.  * in sys/???/ttyio.c)
  1803.  */
  1804. KEY
  1805. getkey(f) register int f; {
  1806.     register KEY    c;
  1807.     KEY        keychar();
  1808.     int        getkbd(), ttgetc();
  1809.  
  1810.     if (kbdmop != NULL) return *kbdmop++;
  1811. #ifdef    DPROMPT
  1812.     if(!(f&KPROMPT)) prompt[0] = '\0';
  1813. #endif
  1814.     c = (KEY) mapin(getkbd);
  1815. #ifdef    DPROMPT
  1816.     if(f&KPROMPT) {
  1817.         if(promptp > prompt) *(promptp-1) = ' ';
  1818.         if(promptp >= &prompt[PROMPTL-8]) f &= ~KPROMPT;
  1819.                 /* must have a lot of prefixes.... */
  1820.     }
  1821. #endif
  1822.     if ((f&KQUOTE) == 0) {
  1823. #ifdef    DO_METAKEY
  1824.         if ((c & ~KCHAR) == KCTRL)    /* Function key        */
  1825.             c &= KCHAR;        /* remove wrapping    */
  1826.         else if ((c >= 0x80) && (c <= 0xFF)) /* real meta key    */
  1827.             c = KMETA | keychar(c & ~0x80, TRUE);
  1828. #endif
  1829. #ifdef    DPROMPT
  1830.         if(f&KPROMPT) {
  1831.             keyname(promptp, (c<=0x1F && c>=0x00)?KCTRL|(c+'@'):c);
  1832.             strcat(promptp, "-");
  1833.         }
  1834. #endif
  1835.         if (c == METACH)        /* M-            */
  1836.             c = KMETA | keychar(mapin(ttgetc), TRUE);
  1837.         else if (c == CTRLCH)        /* C-            */
  1838.             c = KCTRL | keychar(mapin(ttgetc), TRUE);
  1839.         else if (c == CTMECH)        /* C-M-            */
  1840.             c = KCTRL | KMETA | keychar(mapin(ttgetc), TRUE);
  1841.         else if (c<=0x1F && c>=0x00)    /* Relocate control.    */
  1842.             c = KCTRL | (c+'@');
  1843.         if (c == (KCTRL|'X'))        /* C-X            */
  1844.             c = KCTLX | keychar(mapin(ttgetc), TRUE);
  1845.     }
  1846.  
  1847.     if ((f&KNOMAC) == 0 && kbdmip != NULL) {
  1848.         if (kbdmip+1 > &kbdm[NKBDM-3]) {    /* macro overflow */
  1849.             (VOID) ctrlg(FALSE, 0, KRANDOM);
  1850.             ewprintf("Keyboard macro overflow");
  1851.             ttflush();
  1852.             return (KCTRL|'G');        /* ^G it for us    */
  1853.         }
  1854.         *kbdmip++ = c;
  1855.     }
  1856. #ifdef    DPROMPT
  1857.     if(f&KPROMPT) {
  1858.         keyname(promptp, c);
  1859.         promptp += strlen(promptp);
  1860.         *promptp++ = '-';
  1861.         *promptp = '\0';
  1862.     }
  1863. #endif
  1864.     return (c);
  1865. }
  1866.  
  1867. /*
  1868.  * go get a key, and run it through whatever mapping the modes
  1869.  * specify.
  1870.  */
  1871. static mapin(get) int (*get)(); {
  1872.     register int    c;
  1873.  
  1874. #ifdef    DPROMPT
  1875.     if(prompt[0]!='\0' && ttwait()) {
  1876.         ewprintf("%s", prompt);        /* avoid problems with % */
  1877.         update();            /* put the cursor back     */
  1878.         epresf = KPROMPT;
  1879.     }
  1880. #endif
  1881.     c = (*get)();
  1882.     if ((mode&MFLOW) != 0) {
  1883.         while (c == CCHR('S') || c == CCHR('Q'))
  1884.             c = (*get)();
  1885.         if (c == CCHR('^')) c = CCHR('Q');
  1886.         else if (c == CCHR('\\')) c = CCHR('S');
  1887.     }
  1888.     if ((mode&MBSMAP) != 0)
  1889.         if (c == CCHR('H')) c = 0x7f;
  1890.         else if (c == 0x7f) c = CCHR('H');
  1891.     return c;
  1892. }
  1893. /*
  1894.  * Transform a key code into a name,
  1895.  * using a table for the special keys and combination
  1896.  * of some hard code and some general processing for
  1897.  * the rest. None of this code is terminal specific any
  1898.  * more. This makes adding keys easier.
  1899.  */
  1900. VOID
  1901. keyname(cp, k) register char *cp; register int k; {
  1902.     register char    *np;
  1903.     register int    c;
  1904.     char        nbuf[3];
  1905.  
  1906.     static    char    hex[] = {
  1907.         '0',    '1',    '2',    '3',
  1908.         '4',    '5',    '6',    '7',
  1909.         '8',    '9',    'A',    'B',
  1910.         'C',    'D',    'E',    'F'
  1911.     };
  1912.  
  1913.     if ((k&KCTLX) != 0) {            /* C-X prefix.        */
  1914.         *cp++ = 'C';
  1915.         *cp++ = '-';
  1916.         *cp++ = 'x';
  1917.         *cp++ = ' ';
  1918.     }
  1919.     if ((k&KMETA) != 0) {            /* Add M- mark.        */
  1920.         *cp++ = 'E';
  1921.         *cp++ = 'S';
  1922.         *cp++ = 'C';
  1923.         *cp++ = ' ';
  1924.     }
  1925.     if ((k&KCHAR)>=KFIRST && (k&KCHAR)<=KLAST) {
  1926.         if ((np=keystrings[(k&KCHAR)-KFIRST]) != NULL) {
  1927.             if ((k&KCTRL) != 0) {
  1928.                 *cp++ = 'C';
  1929.                 *cp++ = '-';
  1930.             }
  1931.             (VOID) strcpy(cp, np);
  1932.             return;
  1933.         }
  1934.     }
  1935.     c = k & ~(KMETA|KCTLX);
  1936.     if (c == (KCTRL|'I'))    /* Some specials.    */
  1937.         np = "TAB";
  1938.     else if (c == (KCTRL|'M'))
  1939.         np = "RET";
  1940.     else if (c == (KCTRL|'J'))
  1941.         np = "LFD";
  1942.     else if (c == ' ')
  1943.         np = "SPC";
  1944.     else if (c == 0x7F)
  1945.         np = "DEL";
  1946.     else if (c == (KCTRL|'['))
  1947.         np = "ESC";
  1948.     else {
  1949.         if ((k&KCTRL) != 0) {        /* Add C- mark.        */
  1950.             *cp++ = 'C';
  1951.             *cp++ = '-';
  1952.         }
  1953.         if ((k&(KCTRL|KMETA|KCTLX)) != 0 && ISUPPER(k&KCHAR) != FALSE)
  1954.             k = TOLOWER(k&KCHAR);
  1955.         np = &nbuf[0];
  1956.         if (((k&KCHAR)>=0x20 && (k&KCHAR)<=0x7E)
  1957.         ||  ((k&KCHAR)>=0xA0 && (k&KCHAR)<=0xFE)) {
  1958.             nbuf[0] = k&KCHAR;    /* Graphic.        */
  1959.             nbuf[1] = 0;
  1960.         } else {            /* Non graphic.        */
  1961.             nbuf[0] = hex[(k>>4)&0x0F];
  1962.             nbuf[1] = hex[k&0x0F];
  1963.             nbuf[2] = 0;
  1964.         }
  1965.     }
  1966.     (VOID) strcpy(cp, np);
  1967. }
  1968.  
  1969. /*
  1970.  * turn a key into an internal char.
  1971.  */
  1972. KEY
  1973. keychar(c, f) register int c, f; {
  1974.  
  1975.     if (f == TRUE && ISLOWER(c) != FALSE)
  1976.         c = TOUPPER(c);
  1977.     else if (c>=0x00 && c<=0x1F)        /* Relocate control.    */
  1978.         c = (KCTRL|(c+'@'));
  1979.     return (KEY) c;
  1980. }
  1981. SHAR_EOF
  1982. fi # end of overwriting check
  1983. #    End of shell archive
  1984. exit 0
  1985.  
  1986.