home *** CD-ROM | disk | FTP | other *** search
- Subject: v08i008: A Micro-Emacs variant that resembles GNU Emacs
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: Bob Larson <seismo!usc-oberon!blarson>
- Mod.sources: Volume 8, Issue 8
- Archive-name: micrognu/Part01
-
- [ It's editor week at mod.sources... -r$ ]
-
- #! /bin/sh
- #
- # distribution note: This distribution of mg 1a is 11 shar files:
- # mg_1.shar through mg_5.shar system indepentend, termcap,
- # bsd, sysv, and osk files.
- # mg_amiga1.shar, mg_amiga2.shar amiga specific files
- # mg_vms1.shar through mg_vms4.shar
- # vms and eunice specific files.
- #
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- # README
- # systty.mods
- # functions
- # def.h
- # display.c
- # kbd.c
- export PATH; PATH=/bin:$PATH
- if test -f 'README'
- then
- echo shar: will not over-write existing file "'README'"
- else
- cat << \SHAR_EOF > 'README'
- MG 1a README Nov 16, 1986
-
- MicroGnuEmacs (mg) is a Public Domain EMACS style editor. It is
- "broadly" compatible with GNU Emacs, the latest creation of Richard M.
- Stallman, Chief GNUisance and inventor of Emacs. GNU Emacs (and other
- portions of GNU as they are released) are essentially free, (there are
- handling charges for obtaining it) and so is MicroGnuEmacs. You may
- never have to learn another editor. (But probably will, at least long
- enough to port MicroGnuEmacs...)
-
- MicroGnuEmacs is not associated with the GNU project, and does not
- have the copyright restrictions present in GNU Emacs. (However, a few
- of the system dependent modules do have copyright notices, specificly
- the VMS termcap routines and the amiga specific routines. Look at the
- source code for exact copyright restrictions.) The MicroGnuEmacs
- authors individually may or may not agree with the opinions expressed
- by Richard Stallman and the GNU project.
-
- This program is intended to be a small, fast, and portable editor for
- people who can't run real Emacs thing for one reason or another. It
- is compatible with GNU because there shouldn't be any reason to learn
- more than one Emacs flavor. We have excised most MicroEMACS features
- that were incompatible with the big brother, and added missing
- features that seemed essential.
-
- There are at least two other major versions of MicroEMACS in
- circulation. One comes from Daniel Lawrence, (based on an old version
- from Dave Conroy) and is available from mod.sources. It uses a 3.x
- version numbering scheme, and the latest I know about is 3.7i. It has
- some features not found in MicroGnuEmacs, is bigger, and is
- incompatible with GNU Emacs. It might be a better choice for you if
- you *must* have something not present here and can't run GNU.
-
- Another variety uses a different numbering scheme, and is up to v30.
- This also comes from mod.sources, and is the latest version from the
- original MicroEMACS author Dave Conroy. MicroGnuEmacs is derived from
- this version, and we hope to replace it.
-
- Code will move fairly easily between MicroGnuEmacs and v30
- derivatives. It will not move easily to the 3.x strain because of
- diverging ideas about how things should work internally. Command
- functions and keymapping, for instance, are completely different
- between the two flavors.
-
- This is the first distribution release of MicroGnuEmacs. (It went
- through four beta releases to iron out the changes made by the various
- autors.) Beyond the work of Dave Conroy, author of the original
- public domain v30, this contains the efforts of:
-
- mwm@ucbopal.berkeley.edu Mike Meyer
- mic@ngp.utexas.edu Mic Kaczmarczik
- blarson@usc-oberon.arpa Bob Larson
- rtech!daveb@sun.com Dave Brower
-
- Special thanks are due the first three fellows, who did most of the
- work.
-
- These systems are known to work in the current version:
-
- 4.2 & 4.3 BSD Unix
- OS9/68k
- VMS
- Amiga
- System V
- Eunice
-
- As far as MG is concerned, Ultrix-32 is equivalent to BSD unix.
-
- It should support MSDOS, PCDOS, and the Rainbow if you swipe the sys
- and tty files from the v30 distribution and modify them as specified
- in the file systty.mods. It obviously hasn't been tested.
-
- How to Make a MicroGnuEmacs
- ---------------------------
-
- On UNIX at least, it's easy. (Note that even on these systems you may
- want to change a compile time option.) If you have BSD UNIX, do:
-
- ln sys/bsd/Makefile .
- make
-
- For System V, do:
-
- ln sys/sysv/Makefile .
- make
-
- There are several other directories under sys: osk, vms, and eunice
- and amiga. You should follow the directions contained therein to make
- one of those versions.
-
- For most systems (everyting except the amiga currently), the termcap
- terminal definition is used. There is a readme file in the termcap
- subdirectory of the tty directory explaining what entries are used and
- how. (Termcap is a way to do display manipulation in a terminal
- independent manner.)
-
- ----------------------------------------------------------------------
-
- Known limitaions and minor bugs descovered immeditatly before release:
-
- A newline will be appended to the last line of a file if it does
- not have one.
-
- There is a fixed maximum line length on files read. (Defaults
- to 256, but may be changed at compile time.)
-
- See functions for function by function differences from real
- GNU Emacs.
-
- DPROMPT code has not been added to ttyio.c for all systems
- where it could be supported.
-
- The Amiga code has not been extensivly tested with all options
- on all compilers. A problem have been discovered but not
- duplicated, possibly a compiler problem.
-
- Multi-case buffer names can be created on case-insensitive systems
- (i.e. OSK) for files specified on the command line.
-
- ------------------------------------------------------------------------
-
- If you have a change to make that you think should be incorporated
- into the next version of MicroGnuEmacs, send it to the contact for
- your system:
-
- Amiga Lattice C: Mike Meyer:
- mwm@berkeley.edu
- ucbvax!mwm
-
- Amiga Manx C & VMS: Mic Kaczmarczik:
- ut-sally!ut-ngp!mic
- mic@ngp.utexas.edu
- CCEP001@UTADNX.BITNET
-
- OSK & BSD: Bob Larson:
- blarson@usc-oberon.arpa
- sdcrdcf!usc-oberon!blarson
-
- Support for additional systems and terminals should include being
- available for beta testing as other changes are made. (Send a short
- note to all three contacts above.) If you can't reach one of us via a
- computer network, I suppose you could send a change to my snail mail
- address below on 5" os9 format disks or 9 track tape (ANSI variable
- label or Prime magsav format), but this efectivly rules you out as a
- potential beta tester. (Don't expect the disk or tape back unless you
- inculude a SASE with sufficent postage.) I will not be sending out
- copies on magnetic media, so please don't ask. If you somehow got an
- incomplete or non-standard copy, (i.e. missing one of the sys
- directories mentioned here as working) complain to who you got it from
- not to me.
-
- Robert Larson
- 309 S. Alexandria Ave.
- Apt. 117
- Los Angeles, CA 90020
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'systty.mods'
- then
- echo shar: will not over-write existing file "'systty.mods'"
- else
- cat << \SHAR_EOF > 'systty.mods'
- 1) All the function names have changed, so fix function bindings.
- 2) version has changed from char *[] to char *, fix all references.
- 3) if STARTUP is defined, startupfile (which returns a pointer to the
- name of the users startupfile) should be in fileio.c
- 4) The typedefs for KEY (the internal key type, an 11 bit value) and
- RSIZE (how big a region can be) need to be in sysdef.h
- 5) Either a function or a define for bcopy() needs to come in for the
- system. It looks like bcopy(b1, b2, length), and copies length
- bytes from b1 to b2. IT MUST DO A NON-DESTRUCTIVE COPY. Check for
- a routine that does this (by a different name, of course) in your
- system already, and make it a define.
- 6) Either a function or a define for typeahead() needs to exist. It returns
- true if there are input characters to be had. Easy case is to
- #define it as FALSE.
- 7) abort has turned into panic, with a string argument. Panic should
- spit out the string, and then leave a core image if possible.
- 8) All #if's were changed to #ifdef's. Most configuration #define XXX 0
- lines should be commented out.
- 9) Several optional defines have been added: VARARGS, SYSINIT,
- STANDOUT_GLITCH, MOVE_STANDOUT, XCHAR + XSHORT, NLINE, DPROMPT,
- XKEYS.
- 10) Define KEYDUP_ERROR for debugging symbol.c (and a (sometimes MUCH)
- larger executable.)
- 11) User preference options have been moved to Makefile from def.h.
- 12) To use with DPROMPT, a ttwait function is needed in ttyio.c. An
- example is in sys/osk.
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'functions'
- then
- echo shar: will not over-write existing file "'functions'"
- else
- cat << \SHAR_EOF > 'functions'
- Format:
- #!function-name [default binding]
- Description
- ! How it differs from GNU.
-
- The '!' in the function name is optional. If present, it means that the
- function does not exist in GNU.
-
- To get a function list with bindings, do
- "grep ^# this_file | sed -e 's/^#//' -e 's/^#!//' > your_file"
- Other interesting things can be extracted as you see fit.
-
- -------------------------------------------------------------------------------
-
- #auto-fill-mode
- Cause word-wrap at fill-column, after space is typed.
- ! Modes are global across all buffers.
- #!auto-indent-mode
- Cause indent to first whitespace after a newline.
- #backward-char [C-b]
- Move point left ARG characters (right if ARG negative).
- On reaching end of buffer, stop and signal error.
- #backward-delete-char [DEL]
- Delete characters backwards. Delete ARG chars, and save in
- kill buffer if ARG was specified
- #backward-kill-word [ESC DEL]
- Kill characters backward until encountering the end of a word.
- With argument, do this that many times.
- ! When deleting backwards across line boundaries onto non-null
- ! kill buffers, things get put in the kill buffer in the wrong
- ! order.
- #backward-paragraph [ESC [ ]
- Move backward to start of paragraph. With arg, do it arg times.
- ! Definition of paragraph isn't quite the same as with GNU, need
- ! to fill it in.
- #backward-word [ESC b]
- Move backward until encountering the end of a word.
- With argument, do this that many times.
- #beginning-of-buffer [ESC < ]
- Move point to the beginning of the buffer; leave mark at
- previous position.
- ! Doesn't understand arguments.
- #beginning-of-line [C-a]
- Move point to beginning of current line.
- #!bsmap-mode
- If no argument, turns on a mode that maps ^H to del and del
- to ^H, where the editor can't see it. If there is an argument,
- turns that mode off.
- #call-last-kbd-macro [C-x e]
- Call the last keyboard macro that you defined with C-x (.
- ! Not as fancy as GNU version.
- #capitalize-word [ESC c]
- Convert following word (or ARG words) to upper case, moving over.
- ! Doesn't handle negative arguments.
- #copy-region-as-kill [ESC w]
- Save the region as if killed, but don't kill it.
- #!ctrlx-four-hack
- Exists to support the Ctl-x 4 <things> code.
- #delete-blank-lines [C-x C-o]
- On blank line, delete all surrounding blank lines, leaving just one.
- ! Always behaves that way, doesn't do the isolated blank and non-blank
- ! lines as does GNU.
- #delete-char [C-d]
- Delete the following ARG characters (previous, with negative arg).
- If ARG is specified, appends deleted characters to the kill buffer.
- #delete-other-windows [C-x 1]
- Make current window fill the screen.
- #delete-window [C-x 0]
- Remove current window from the display.
- #describe-bindings [C-h b]
- Show a list of all defined keys, and their definitions.
- The list is put in a buffer, which is displayed.
- ! No heading on columns in output buffer
- #describe-key-briefly [C-h c]
- Print the name of the function KEY invokes.
- #downcase-region [C-x C-l]
- Convert the region to lower case.
- #downcase-word [ESC l]
- Convert following word (or ARG words) to lower case, moving over.
- ! Doesn't handle negative arguments.
- #emacs-version
- Print string describing the version of Emacs that is running.
- #end-kbd-macro [C-x ) ]
- Finish defining a keyboard macro.
- The definition was started by C-x (.
- The macro is now available for use via C-x e,
- ! Can't use end-kbd-macro to execute macro.
- #end-of-buffer [ESC > ]
- Move point to the end of the buffer; leave mark at previous position.
- ! Doesn't understand arguments
- #end-of-line [C-e]
- Move point to end of current line.
- ! Doesn't understand arguments.
- #enlarge-window [C-x ^]
- Make current window ARG lines bigger.
- ! Won't make other windows vanish to make room for enlarging window.
- #eval-current-buffer
- Execute the current buffer as an Emacs command file.
- ! Doesn't exist in the MICRO version.
- #eval-expression
- Get Emacs command and evaluate.
- ! Doesn't exist in MICRO version. No autocompletion.
- #exchange-point-and-mark [C-x C-x]
- Put the mark where point is now, and point where the mark is now.
- #execute-extended-command
- Read function name, then read its arguments and call it.
- #fill-paragraph [ESC q]
- Fill paragraph at or after point.
- ! Leaves point at end of paragraph, instead of where it started.
- ! Other differences, such as paragraph definition and what
- ! characters to doublespace after also exist.
- #find-file [C-x C-f]
- Edit file FILENAME.
- Switch to a buffer visiting file FILENAME,
- creating one if none already exists.
- ! MicroGnuEmacs will put a newline at the end of the last line
- ! if there is not one there already.
- #find-file-other-window [C-x 4 f] [C-x 4 C-f]
- Edit file FILENAME, in another window.
- May create a new window, or reuse an existing one;
- ! See find-file.
- #!flow-mode
- Without an argument, sets a mode that maps ^\ to ^S and ^^ to ^Q,
- and silently eats ^S and ^Q at a level where the editor can't see
- it. With an argument, turns that mode off.
- #forward-char [C-f]
- Move point right ARG characters (left if ARG negative).
- On reaching end of buffer, stop and signal error.
- #forward-paragraph [ESC ] ]
- Move forward to end of paragraph. With arg, do it arg times.
- ! See backward-paragraph
- #forward-word [ESC f]
- Move point forward ARG words (backward if ARG is negative).
- #global-set-key
- Give KEY a definition of COMMAND.
- #global-unset-key
- Remove global definition of KEY.
- #goto-line
- goto LINE in the current buffer.
- ! Want to leave mark at old position, but....
- #help [C-h]
- Prompt user to find out what kind of help to supply
- ! Only b (describe-bindings), c (describe-key-briefly) and ^H
- ! (help) work.
- #insert-file [C-x i]
- Insert contents of file FILENAME into buffer after point.
- Set mark after the inserted text.
- ! File not found handling differs from GNU Emacs.
- ! see find-file.
- #!insert-newline [RET]
- Bound to newline so that it does the right things. Usually
- ignorable.
- #!insert-with-wrap
- Bound to space in auto-fill-mode. Check current column, and adds
- a newline if past it.
- #isearch-backward [C-r]
- Do incremental search backward.
- See isearch-forward for more information.
- ! Not as fancy as the GNU version.
- #isearch-forward [C-s]
- Do incremental search forward.
- As you type characters, they add to the search string and are found.
- Type Delete to cancel characters from end of search string.
- Type ESC to exit, leaving point at location found.
- Type C-S to search again forward, C-R to search again backward.
- Type C-Q to quote control character to search for it.
- C-G while searching or when search has failed
- cancels input back to what has been found successfully.
- C-G when search is successful aborts and moves point to starting point.
- Other control and meta characters terminate the search
- and are then executed normally.
- ! See isearch-backward.
- #just-one-space [ESC SPC]
- #keyboard-quit [C-g]
- Terminate the current function with an quit condition.
- #kill-buffer [C-x k]
- Get rid of the specified buffer.
- ! Has minor problems: if buffer being killed is open in any windows,
- ! those windows must have valid alternate buffers. Leaves point and
- ! mark at end of buffer if alternate buffer is open on another window.
- #kill-line [C-k]
- Kill the rest of the current line; before a newline, kill the newline.
- With prefix argument, kill that many lines from point.
- Negative arguments kill lines backward.
- ! When killing backwards across line boundaries (args of < 0) onto a
- ! non-empty kill buffer, it appends things in the wrong order.
- #kill-paragraph
- Kill current paragraph.
- ! NEEDS TO BE CHANGED TO KILL TO END OF CURRENT PARAGRAPH!!!
- #kill-region [C-w]
- Kill between point and mark.
- The text is deleted but saved in the kill buffer.
- The command C-y can retrieve it from there.
- #kill-word [ESC d]
- Kill characters forward until encountering the end of a word.
- With argument, do this that many times.
- #list-buffers
- Display a list of names of existing buffers.
- Inserts it in buffer *Buffer List* and displays that.
- ! Note that buffers with names starting with spaces are listed, where
- ! GNU omits them. Less information listed.
- #load
- Execute a file of Emacs commands.
- ! Mucho different; any of '();' comments outside of strings; only
- ! one-line "S-expressions" work; only present if compilation option
- ! specified.
- #newline-and-indent [C-j]
- Insert a newline, then indent.
- #next-line [C-n]
- Move cursor vertically down ARG lines.
- ! Not like GNU, not sure of the differences.
- #!next-window
- Move to the next window down the screen.
- ! Named other-window in GNU. Done this way for GOSLING freaks
- ! who want next and previous window.
- #not-modified [ESC ~]
- Clear buffer modified flag.
- #open-line [C-o]
- Insert a newline and leave point before it.
- With arg, inserts that many newlines.
- #!prefix-region
- Prepend a string (set by set-prefix-string) to each line
- in the curernt region. If given an argument, prompts
- you for the string to use.
- ! Probably available in GNU under a different name or through a
- ! different functionality. Intended purpose is mail quoting and
- ! bar comments in C code. Compilation option.
- previous-line [C-p]
- Move cursor vertically up ARG lines.
- ! See next-line.
- #!previous-window
- Move to the next window up the screen.
- ! previous-window is there for GOSLING freaks (like me).
- #query-replace [ESC % ]
- Replace some occurrences of FROM-STRING with TO-STRING.
- As each match is found, the user must type a character saying
- what to do with it.
- Type Help char within query-replace for directions.
- ! Not quite as sharp as GNU version
- #quoted-insert [C-q]
- Read next input character and insert it.
- Useful for inserting control characters.
- ! Doesn't handle the 3 octal digits case.
- #recenter [C-l]
- Center point in window and redisplay screen. With ARG, put point
- on line ARG. The desired position of point is always relative
- to the current window. Also forces full screen refresh.
- #save-buffer [C-x C-s]
- Save current buffer in visited file.
- ! Always saves buffer, even if it isn't modified.
- #save-buffers-kill-emacs [C-x C-c]
- Offer to save each buffer, then kill this Emacs.
- #save-some-buffers [C-x s]
- Save some modified file-visiting buffers. Asks user about each one.
- With argument, saves all with no questions.
- #scroll-down [ESC v]
- Scroll text of current window downward ARG lines; or near full
- screen if no ARG.
- #scroll-other-window [ESC C-v]
- Scroll text of next window upward ARG lines; or near full screen
- if no ARG. The next window is the one below the current one; or
- the one at the top if the current one is at the bottom.
- #scroll-up [C-v]
- Scroll text of current window upward ARG lines; or near full
- screen if no ARG.
- #!search-again
- Handy to have around for function keys/menus, etc.
- #search-backward [ESC r]
- Search backward from point for STRING.
- ! Last search pattern is remembered, including isearches
- ! Bound to C-s in uemacs, not bound in GNU
- #search-forward [ESC s]
- Search forward from point for STRING.
- see search-backward
- #self-insert-command [All printing characters]
- Insert this character.
- #set-fill-column [C-x f]
- Set fill-column to current column, or to argument if given.
- ! Global, not buffer-local (no buffer-local stuff in uemacs)
- #set-mark-command [C-@]
- Set mark to where point is.
- ! No mark ring, so args don't make sense.
- #!set-prefix-string
- ! Set string used by prefix-region to put in front of each line text.
- ! Probably available in GNU in some other form, but this specific
- ! form suits a number of situations. Compilation option.
- #shrink-window
- Make the current window ARG lines smaller.
- ! Will not make the current window vanish if you try and make it
- ! to small; won't shrink window if you only have one window.
- #split-window-vertically [C-x 2]
- Split current window into two windows, one above the other.
- ! Behaves differently about which is going to be current window,
- ! Doesn't use ARG to decide how many lines to use.
- #start-kbd-macro [C-x ( ]
- Record subsequent keyboard input, defining a keyboard macro.
- The commands are recorded even as they are executed.
- #suspend-emacs [C-z] [C-x C-z]
- Get a shell. Exactly what shell depends on the system you
- are on.
- #switch-to-buffer [C-x b]
- Select the specified buffer in the current window.
- ! Memory of old buffer names doesn't work quite as well.
- #switch-to-buffer-other-window [C-x 4 b]
- Switch to specified buffer in another window.
- ! See switch-to-buffer
- #transpose-chars [C-t]
- Interchange characters around point, moving forward one character.
- ! Doesn't work across newlines, ignores args
- #upcase-region [C-x C-u]
- Convert the region to upper case.
- #upcase-word [ESC u]
- Convert the following word (or ARG words) to upper case, moving over.
- ! Doesn't handle negative arguments.
- #what-cursor-position [C-x =]
- Print info on cursor position.
- ! slightly more information in output.
- #write-file [C-x C-w]
- Write current buffer into file FILENAME. Makes FILENAME the file for
- the current buffer.
- #yank
- Reinsert the last stretch of killed text.
- ! Doesn't keep a kill ring, so no yanks of stuff older than
- ! last delete, and arg-yank does yank arg times, instead of
- ! getting the arg'th thing off the kill ring.
-
-
-
-
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'def.h'
- then
- echo shar: will not over-write existing file "'def.h'"
- else
- cat << \SHAR_EOF > 'def.h'
- /*
- * This file is the general header file for all parts
- * of the MicroEMACS display editor. It contains all of the
- * general definitions and macros. It also contains some
- * conditional compilation flags. All of the per-system and
- * per-terminal definitions are in special header files.
- * The most common reason to edit this file would be to zap
- * the definition of CVMVAS or BACKUP.
- */
- #include "sysdef.h" /* Order is critical. */
- #include "ttydef.h"
- #include <stdio.h>
-
- /*
- * If your system and/or compiler does not support the "void" type
- * then define NO_VOID_TYPE in sysdef.h. In the absence of some
- * other definition for VOID, the default in that case will be to
- * turn it into an int, which works with most compilers that don't
- * support void. In the absence of any definition of VOID or
- * NO_VOID_TYPE, the default is to assume void is supported, which
- * should be the case for most modern C compilers.
- */
-
- #ifndef VOID
- #ifdef NO_VOID_TYPE
- # define VOID int /* Default for no void is int */
- #else
- # define VOID void /* Just use normal void */
- #endif /* NO_VOID_TYPE */
- #endif /* VOID */
-
- /*
- * Table sizes, etc.
- */
- #ifdef HASH
- #define NSHASH 31 /* Symbol table hash size. */
- #endif
- #define NFILEN 80 /* Length, file name. */
- #define NBUFN 24 /* Length, buffer name. */
- #ifndef NLINE /* allow it to be defined in makefile */
- #define NLINE 256 /* Length, line. */
- #endif
- #define NKBDM 256 /* Length, keyboard macro. */
- #define NPAT 80 /* Length, pattern. */
- #define HUGE 1000 /* A rather large number. */
- #define NSRCH 128 /* Undoable search commands. */
- #define NXNAME 64 /* Length, extended command. */
- #define NKNAME 20 /* Length, key names */
- /*
- * Universal.
- */
- #define FALSE 0 /* False, no, bad, etc. */
- #define TRUE 1 /* True, yes, good, etc. */
- #define ABORT 2 /* Death, ^G, abort, etc. */
-
- /*
- * These flag bits keep track of
- * some aspects of the last command. The CFCPCN
- * flag controls goal column setting. The CFKILL
- * flag controls the clearing versus appending
- * of data in the kill buffer.
- */
- #define CFCPCN 0x0001 /* Last command was C-P, C-N */
- #define CFKILL 0x0002 /* Last command was a kill */
-
- /*
- * File I/O.
- */
- #define FIOSUC 0 /* Success. */
- #define FIOFNF 1 /* File not found. */
- #define FIOEOF 2 /* End of file. */
- #define FIOERR 3 /* Error. */
-
- /*
- * Directory I/O.
- */
- #define DIOSUC 0 /* Success. */
- #define DIOEOF 1 /* End of file. */
- #define DIOERR 2 /* Error. */
-
- /*
- * Display colors.
- */
- #define CNONE 0 /* Unknown color. */
- #define CTEXT 1 /* Text color. */
- #define CMODE 2 /* Mode line color. */
-
- /*
- * global mode
- */
- #define MBSMAP 0x0001 /* Map bs<->del */
- #define MFLOW 0x0002 /* Use ^^ for ^Q and ^/ for ^S */
- #define MINDENT 0x0004 /* autoindent */
- #define MFILL 0x0008 /* fill mode */
-
- /*
- * Flags for "eread".
- */
- #define EFFUNC 0x0001 /* Autocomplete functions. */
- #define EFBUF 0x0002 /* Autocomplete buffers. */
- #define EFFILE 0x0004 /* " files (maybe someday) */
- #define EFAUTO 0x0007 /* Some autocompleteion on */
- #define EFNEW 0x0008 /* New prompt. */
- #define EFCR 0x0010 /* Echo CR at end; last read. */
-
- /*
- * Flags for "getkey".
- */
- #define KQUOTE 0x0001 /* Get raw character */
- #define KNOMAC 0x0002 /* Don't record for macros */
- #define KPROMPT 0x0004 /* do delayed prompting */
-
- /*
- * Flags for "ldelete"/"kinsert"
- */
-
- #define KNONE 0
- #define KFORW 1
- #define KBACK 2
-
- /*
- * Keys are represented inside using an 11 bit
- * keyboard code. The transformation between the keys on
- * the keyboard and 11 bit code is done by terminal specific
- * code in the "kbd.c" file. The actual character is stored
- * in 8 bits (DEC multinationals work); there is also a control
- * flag KCTRL, a meta flag KMETA, and a control-X flag KCTLX.
- * ASCII control characters are always represented using the
- * KCTRL form. Although the C0 control set is free, it is
- * reserved for C0 controls because it makes the communication
- * between "getkey" and "getkbd" easier. The funny keys get
- * mapped into the C1 control area. The KEY type is typedefed in
- * sysdef.h, as it may depeond on compiler/machine.
- */
- #define NKEYS 2048 /* 11 bit code. */
-
- #define METACH 0x1B /* M- prefix, Control-[, ESC */
- #define CTMECH 0x1C /* C-M- prefix, Control-\ */
- #define EXITCH 0x1D /* Exit level, Control-] */
- #define CTRLCH 0x1E /* C- prefix, Control-^ */
- #define HELPCH 0x1F /* Help key, Control-_ */
-
- #define KCHAR 0x00FF /* The basic character code. */
- #define KCTRL 0x0100 /* Control flag. */
- #define KMETA 0x0200 /* Meta flag. */
- #define KCTLX 0x0400 /* Control-X flag. */
-
- #define KFIRST 0x0080 /* First special. */
- #define KLAST 0x009F /* Last special. */
-
- #define KRANDOM 0x0080 /* A "no key" code. */
- #define K01 0x0081 /* Use these names to define */
- #define K02 0x0082 /* the special keys on your */
- #define K03 0x0083 /* terminal. */
- #define K04 0x0084
- #define K05 0x0085
- #define K06 0x0086
- #define K07 0x0087
- #define K08 0x0088
- #define K09 0x0089
- #define K0A 0x008A
- #define K0B 0x008B
- #define K0C 0x008C
- #define K0D 0x008D
- #define K0E 0x008E
- #define K0F 0x008F
- #define K10 0x0090
- #define K11 0x0091
- #define K12 0x0092
- #define K13 0x0093
- #define K14 0x0094
- #define K15 0x0095
- #define K16 0x0096
- #define K17 0x0097
- #define K18 0x0098
- #define K19 0x0099
- #define K1A 0x009A
- #define K1B 0x009B
- #define K1C 0x009C
- #define K1D 0x009D
- #define K1E 0x009E
- #define K1F 0x009F
-
- #ifndef SEOL /* needed for OSK, where '\r' == '\n' */
- # define SEOL '\n'
- #endif
-
- /*
- * These flags, and the macros below them,
- * make up a do-it-yourself set of "ctype" macros that
- * understand the DEC multinational set, and let me ask
- * a slightly different set of questions.
- */
- #define _W 0x01 /* Word. */
- #define _U 0x02 /* Upper case letter. */
- #define _L 0x04 /* Lower case letter. */
- #define _C 0x08 /* Control. */
- #define _P 0x10 /* end of sentence punctuation */
-
- #define ISWORD(c) ((cinfo[(c)]&_W)!=0)
- #define ISCTRL(c) ((cinfo[(c)]&_C)!=0)
- #define ISUPPER(c) ((cinfo[(c)]&_U)!=0)
- #define ISLOWER(c) ((cinfo[(c)]&_L)!=0)
- #define ISEOSP(c) ((cinfo[(c)]&_P)!=0)
- #define TOUPPER(c) ((c)-0x20)
- #define TOLOWER(c) ((c)+0x20)
-
- /*
- * generally useful thing for chars
- */
- #define CCHR(x) ((x)-'@')
-
- /*
- * All repeated structures are kept as linked lists of structures.
- * All of these start with a LIST structure (except lines, which
- * have their own abstraction). This will allow for
- * later conversion to generic list manipulation routines should
- * I decide to do that. it does mean that there are four extra
- * bytes per window. I feel that this is an acceptable price,
- * considering that there are usually only one or two windows.
- */
- typedef struct LIST {
- union {
- struct SYMBOL *l_sp;
- struct WINDOW *l_wp;
- struct BUFFER *l_bp;
- struct LIST *l_nxt;
- } l_p;
- char *l_name;
- } LIST;
- /*
- * Usual hack - to keep from uglifying the code with lotsa
- * references through the union, we #define something for it.
- */
- #define l_next l_p.l_nxt
-
- /*
- * The symbol table links editing functions
- * to names. Entries in the key map point at the symbol
- * table entry.
- */
- typedef struct SYMBOL {
- LIST s_list; /* List chain. */
- int (*s_funcp)(); /* Function. */
- #ifdef HASH
- short s_flags; /* Flags for this symbol */
- #endif
- } SYMBOL;
- #define s_symp s_list.l_p.l_sp
- #define s_name s_list.l_name
- #ifdef HASH
- #define SFEND 0x001 /* End of has list */
- #endif
-
- /*
- * There is a window structure allocated for
- * every active display window. The windows are kept in a
- * big list, in top to bottom screen order, with the listhead at
- * "wheadp". Each window contains its own values of dot and mark.
- * The flag field contains some bits that are set by commands
- * to guide redisplay; although this is a bit of a compromise in
- * terms of decoupling, the full blown redisplay is just too
- * expensive to run for every input character.
- */
- typedef struct WINDOW {
- LIST w_list; /* List header */
- struct BUFFER *w_bufp; /* Buffer displayed in window */
- struct LINE *w_linep; /* Top line in the window */
- struct LINE *w_dotp; /* Line containing "." */
- struct LINE *w_markp; /* Line containing "mark" */
- short w_doto; /* Byte offset for "." */
- short w_marko; /* Byte offset for "mark" */
- char w_toprow; /* Origin 0 top row of window */
- char w_ntrows; /* # of rows of text in window */
- char w_force; /* If NZ, forcing row. */
- char w_flag; /* Flags. */
- } WINDOW;
- #define w_wndp w_list.l_p.l_wp
- #define w_name w_list.l_name
-
- /*
- * Window flags are set by command processors to
- * tell the display system what has happened to the buffer
- * mapped by the window. Setting "WFHARD" is always a safe thing
- * to do, but it may do more work than is necessary. Always try
- * to set the simplest action that achieves the required update.
- * Because commands set bits in the "w_flag", update will see
- * all change flags, and do the most general one.
- */
- #define WFFORCE 0x01 /* Force reframe. */
- #define WFMOVE 0x02 /* Movement from line to line. */
- #define WFEDIT 0x04 /* Editing within a line. */
- #define WFHARD 0x08 /* Better to a full display. */
- #define WFMODE 0x10 /* Update mode line. */
-
- /*
- * Text is kept in buffers. A buffer header, described
- * below, exists for every buffer in the system. The buffers are
- * kept in a big list, so that commands that search for a buffer by
- * name can find the buffer header. There is a safe store for the
- * dot and mark in the header, but this is only valid if the buffer
- * is not being displayed (that is, if "b_nwnd" is 0). The text for
- * the buffer is kept in a circularly linked list of lines, with
- * a pointer to the header line in "b_linep".
- */
- typedef struct BUFFER {
- LIST b_list; /* buffer list pointer */
- struct BUFFER *b_altb; /* Link to alternate buffer */
- struct LINE *b_dotp; /* Link to "." LINE structure */
- struct LINE *b_markp; /* The same as the above two, */
- struct LINE *b_linep; /* Link to the header LINE */
- short b_doto; /* Offset of "." in above LINE */
- short b_marko; /* but for the "mark" */
- char b_nwnd; /* Count of windows on buffer */
- char b_flag; /* Flags */
- char b_fname[NFILEN]; /* File name */
- } BUFFER;
- #define b_bufp b_list.l_p.l_bp
- #define b_bname b_list.l_name
-
- #define BFCHG 0x01 /* Changed. */
- #define BFBAK 0x02 /* Need to make a backup. */
-
- /*
- * This structure holds the starting position
- * (as a line/offset pair) and the number of characters in a
- * region of a buffer. This makes passing the specification
- * of a region around a little bit easier.
- */
- typedef struct {
- struct LINE *r_linep; /* Origin LINE address. */
- short r_offset; /* Origin LINE offset. */
- RSIZE r_size; /* Length in characters. */
- } REGION;
-
- /*
- * All text is kept in circularly linked
- * lists of "LINE" structures. These begin at the
- * header line (which is the blank line beyond the
- * end of the buffer). This line is pointed to by
- * the "BUFFER". Each line contains a the number of
- * bytes in the line (the "used" size), the size
- * of the text array, and the text. The end of line
- * is not stored as a byte; it's implied. Future
- * additions will include update hints, and a
- * list of marks into the line.
- */
- typedef struct LINE {
- struct LINE *l_fp; /* Link to the next line */
- struct LINE *l_bp; /* Link to the previous line */
- short l_size; /* Allocated size */
- short l_used; /* Used size */
- #ifdef PCC
- char l_text[1]; /* A bunch of characters. */
- #else
- char l_text[]; /* A bunch of characters. */
- #endif
- } LINE;
-
- /*
- * The rationale behind these macros is that you
- * could (with some editing, like changing the type of a line
- * link from a "LINE *" to a "REFLINE", and fixing the commands
- * like file reading that break the rules) change the actual
- * storage representation of lines to use something fancy on
- * machines with small address spaces.
- */
- #define lforw(lp) ((lp)->l_fp)
- #define lback(lp) ((lp)->l_bp)
- #define lgetc(lp, n) ((lp)->l_text[(n)]&0xFF)
- #define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
- #define llength(lp) ((lp)->l_used)
- #define ltext(lp) ((lp)->l_text)
-
- /*
- * Externals.
- */
- extern int thisflag;
- extern int lastflag;
- extern int curgoal;
- extern int epresf;
- extern int sgarbf;
- extern int mode;
- extern WINDOW *curwp;
- extern BUFFER *curbp;
- extern WINDOW *wheadp;
- extern BUFFER *bheadp;
- extern KEY kbdm[];
- extern KEY *kbdmip;
- extern KEY *kbdmop;
- extern KEY getkey();
- extern char pat[];
- extern SYMBOL *symbol[];
- extern SYMBOL *binding[];
- extern BUFFER *bfind();
- extern WINDOW *popbuf();
- extern WINDOW *wpopup();
- extern LINE *lalloc();
- extern int nrow;
- extern int ncol;
- extern char *version;
- extern int ttrow;
- extern int ttcol;
- extern int tceeol;
- extern int tcinsl;
- extern int tcdell;
- extern char cinfo[];
- extern char *keystrings[];
- extern SYMBOL *symlookup();
- VOID update();
- VOID keyname();
- /*
- * Standard I/O.
- */
- extern char *strcpy();
- extern char *strcat();
- extern char *malloc();
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'display.c'
- then
- echo shar: will not over-write existing file "'display.c'"
- else
- cat << \SHAR_EOF > 'display.c'
- /*
- * The functions in this file handle redisplay. The
- * redisplay system knows almost nothing about the editing
- * process; the editing functions do, however, set some
- * hints to eliminate a lot of the grinding. There is more
- * that can be done; the "vtputc" interface is a real
- * pig. Two conditional compilation flags; the GOSLING
- * flag enables dynamic programming redisplay, using the
- * algorithm published by Jim Gosling in SIGOA. The MEMMAP
- * changes things around for memory mapped video. With
- * both off, the terminal is a VT52.
- */
- #include "def.h"
-
- /*
- * You can change these back to the types
- * implied by the name if you get tight for space. If you
- * make both of them "int" you get better code on the VAX.
- * They do nothing if this is not Gosling redisplay, except
- * for change the size of a structure that isn't used.
- * A bit of a cheat.
- */
- /* These defines really belong in sysdef.h */
- #ifndef XCHAR
- # define XCHAR int
- # define XSHORT int
- #endif
-
- #ifdef STANDOUT_GLITCH
- extern int SG; /* number of standout glitches */
- #endif
-
- /*
- * A video structure always holds
- * an array of characters whose length is equal to
- * the longest line possible. Only some of this is
- * used if "ncol" isn't the same as "NCOL".
- */
- typedef struct {
- short v_hash; /* Hash code, for compares. */
- short v_flag; /* Flag word. */
- short v_color; /* Color of the line. */
- XSHORT v_cost; /* Cost of display. */
- char v_text[NCOL]; /* The actual characters. */
- } VIDEO;
-
- #define VFCHG 0x0001 /* Changed. */
- #define VFHBAD 0x0002 /* Hash and cost are bad. */
-
- /*
- * SCORE structures hold the optimal
- * trace trajectory, and the cost of redisplay, when
- * the dynamic programming redisplay code is used.
- * If no fancy redisplay, this isn't used. The trace index
- * fields can be "char", and the score a "short", but
- * this makes the code worse on the VAX.
- */
- typedef struct {
- XCHAR s_itrace; /* "i" index for track back. */
- XCHAR s_jtrace; /* "j" index for trace back. */
- XSHORT s_cost; /* Display cost. */
- } SCORE;
-
- int sgarbf = TRUE; /* TRUE if screen is garbage. */
- int vtrow = 0; /* Virtual cursor row. */
- int vtcol = 0; /* Virtual cursor column. */
- int tthue = CNONE; /* Current color. */
- int ttrow = HUGE; /* Physical cursor row. */
- int ttcol = HUGE; /* Physical cursor column. */
- int tttop = HUGE; /* Top of scroll region. */
- int ttbot = HUGE; /* Bottom of scroll region. */
-
- VIDEO *vscreen[NROW-1]; /* Edge vector, virtual. */
- VIDEO *pscreen[NROW-1]; /* Edge vector, physical. */
- VIDEO video[2*(NROW-1)]; /* Actual screen data. */
- VIDEO blanks; /* Blank line image. */
-
- #ifdef GOSLING
- /*
- * This matrix is written as an array because
- * we do funny things in the "setscores" routine, which
- * is very compute intensive, to make the subscripts go away.
- * It would be "SCORE score[NROW][NROW]" in old speak.
- * Look at "setscores" to understand what is up.
- */
- SCORE score[NROW*NROW];
- #endif
-
- /*
- * Initialize the data structures used
- * by the display code. The edge vectors used
- * to access the screens are set up. The operating
- * system's terminal I/O channel is set up. Fill the
- * "blanks" array with ASCII blanks. The rest is done
- * at compile time. The original window is marked
- * as needing full update, and the physical screen
- * is marked as garbage, so all the right stuff happens
- * on the first call to redisplay.
- */
- vtinit() {
- register VIDEO *vp;
- register int i;
-
- ttopen();
- ttinit();
- vp = &video[0];
- for (i=0; i<NROW-1; ++i) {
- vscreen[i] = vp;
- ++vp;
- pscreen[i] = vp;
- ++vp;
- }
- blanks.v_color = CTEXT;
- for (i=0; i<NCOL; ++i)
- blanks.v_text[i] = ' ';
- }
-
- /*
- * Tidy up the virtual display system
- * in anticipation of a return back to the host
- * operating system. Right now all we do is position
- * the cursor to the last line, erase the line, and
- * close the terminal channel.
- */
- vttidy() {
- ttcolor(CTEXT);
- ttnowindow(); /* No scroll window. */
- ttmove(nrow-1, 0); /* Echo line. */
- tteeol();
- tttidy();
- ttflush();
- ttclose();
- }
-
- /*
- * Move the virtual cursor to an origin
- * 0 spot on the virtual display screen. I could
- * store the column as a character pointer to the spot
- * on the line, which would make "vtputc" a little bit
- * more efficient. No checking for errors.
- */
- vtmove(row, col) {
- vtrow = row;
- vtcol = col;
- }
-
- /*
- * Write a character to the virtual display,
- * dealing with long lines and the display of unprintable
- * things like control characters. Also expand tabs every 8
- * columns. This code only puts printing characters into
- * the virtual display image. Special care must be taken when
- * expanding tabs. On a screen whose width is not a multiple
- * of 8, it is possible for the virtual cursor to hit the
- * right margin before the next tab stop is reached. This
- * makes the tab code loop if you are not careful.
- * Three guesses how we found this.
- */
- vtputc(c) register int c; {
- register VIDEO *vp;
-
- vp = vscreen[vtrow];
- if (vtcol >= ncol)
- vp->v_text[ncol-1] = '$';
- else if (c == '\t') {
- do {
- vtputc(' ');
- } while (vtcol<ncol && (vtcol&0x07)!=0);
- } else if (ISCTRL(c) != FALSE) {
- vtputc('^');
- vtputc(c ^ 0x40);
- } else
- vp->v_text[vtcol++] = c;
- }
-
- /*
- * Erase from the end of the
- * software cursor to the end of the
- * line on which the software cursor is
- * located. The display routines will decide
- * if a hardware erase to end of line command
- * should be used to display this.
- */
- vteeol() {
- register VIDEO *vp;
-
- vp = vscreen[vtrow];
- while (vtcol < ncol)
- vp->v_text[vtcol++] = ' ';
- }
-
- /*
- * Make sure that the display is
- * right. This is a three part process. First,
- * scan through all of the windows looking for dirty
- * ones. Check the framing, and refresh the screen.
- * Second, make sure that "currow" and "curcol" are
- * correct for the current window. Third, make the
- * virtual and physical screens the same.
- */
- VOID
- update() {
- register LINE *lp;
- register WINDOW *wp;
- register VIDEO *vp1;
- register VIDEO *vp2;
- register int i;
- register int j;
- register int c;
- register int hflag;
- register int currow;
- register int curcol;
- register int offs;
- register int size;
- VOID traceback ();
- VOID uline ();
-
- if (typeahead()) return;
- if (sgarbf) { /* must update everything */
- wp = wheadp;
- while(wp != NULL) {
- wp->w_flag |= WFMODE | WFHARD;
- wp = wp->w_wndp;
- }
- }
- hflag = FALSE; /* Not hard. */
- wp = wheadp;
- while (wp != NULL) {
- if (wp->w_flag != 0) { /* Need update. */
- if ((wp->w_flag&WFFORCE) == 0) {
- lp = wp->w_linep;
- for (i=0; i<wp->w_ntrows; ++i) {
- if (lp == wp->w_dotp)
- goto out;
- if (lp == wp->w_bufp->b_linep)
- break;
- lp = lforw(lp);
- }
- }
- i = wp->w_force; /* Reframe this one. */
- if (i > 0) {
- --i;
- if (i >= wp->w_ntrows)
- i = wp->w_ntrows-1;
- } else if (i < 0) {
- i += wp->w_ntrows;
- if (i < 0)
- i = 0;
- } else
- i = wp->w_ntrows/2;
- lp = wp->w_dotp;
- while (i!=0 && lback(lp)!=wp->w_bufp->b_linep) {
- --i;
- lp = lback(lp);
- }
- wp->w_linep = lp;
- wp->w_flag |= WFHARD; /* Force full. */
- out:
- lp = wp->w_linep; /* Try reduced update. */
- i = wp->w_toprow;
- if ((wp->w_flag&~WFMODE) == WFEDIT) {
- while (lp != wp->w_dotp) {
- ++i;
- lp = lforw(lp);
- }
- vscreen[i]->v_color = CTEXT;
- vscreen[i]->v_flag |= (VFCHG|VFHBAD);
- vtmove(i, 0);
- for (j=0; j<llength(lp); ++j)
- vtputc(lgetc(lp, j));
- vteeol();
- } else if ((wp->w_flag&(WFEDIT|WFHARD)) != 0) {
- hflag = TRUE;
- while (i < wp->w_toprow+wp->w_ntrows) {
- vscreen[i]->v_color = CTEXT;
- vscreen[i]->v_flag |= (VFCHG|VFHBAD);
- vtmove(i, 0);
- if (lp != wp->w_bufp->b_linep) {
- for (j=0; j<llength(lp); ++j)
- vtputc(lgetc(lp, j));
- lp = lforw(lp);
- }
- vteeol();
- ++i;
- }
- }
- if ((wp->w_flag&WFMODE) != 0)
- modeline(wp);
- wp->w_flag = 0;
- wp->w_force = 0;
- }
- wp = wp->w_wndp;
- }
- lp = curwp->w_linep; /* Cursor location. */
- currow = curwp->w_toprow;
- while (lp != curwp->w_dotp) {
- ++currow;
- lp = lforw(lp);
- }
- curcol = 0;
- i = 0;
- while (i < curwp->w_doto) {
- c = lgetc(lp, i++);
- if (c == '\t')
- curcol |= 0x07;
- else if (ISCTRL(c) != FALSE)
- ++curcol;
- ++curcol;
- }
- if (curcol >= ncol) /* Long line. */
- curcol = ncol-1;
- if (sgarbf != FALSE) { /* Screen is garbage. */
- sgarbf = FALSE; /* Erase-page clears */
- epresf = FALSE; /* the message area. */
- tttop = HUGE; /* Forget where you set */
- ttbot = HUGE; /* scroll region. */
- tthue = CNONE; /* Color unknown. */
- ttmove(0, 0);
- tteeop();
- for (i=0; i<nrow-1; ++i) {
- uline(i, vscreen[i], &blanks);
- ucopy(vscreen[i], pscreen[i]);
- }
- ttmove(currow, curcol);
- ttflush();
- return;
- }
- #ifdef GOSLING
- if (hflag != FALSE) { /* Hard update? */
- for (i=0; i<nrow-1; ++i) { /* Compute hash data. */
- hash(vscreen[i]);
- hash(pscreen[i]);
- }
- offs = 0; /* Get top match. */
- while (offs != nrow-1) {
- vp1 = vscreen[offs];
- vp2 = pscreen[offs];
- if (vp1->v_color != vp2->v_color
- || vp1->v_hash != vp2->v_hash)
- break;
- uline(offs, vp1, vp2);
- ucopy(vp1, vp2);
- ++offs;
- }
- if (offs == nrow-1) { /* Might get it all. */
- ttmove(currow, curcol);
- ttflush();
- return;
- }
- size = nrow-1; /* Get bottom match. */
- while (size != offs) {
- vp1 = vscreen[size-1];
- vp2 = pscreen[size-1];
- if (vp1->v_color != vp2->v_color
- || vp1->v_hash != vp2->v_hash)
- break;
- uline(size-1, vp1, vp2);
- ucopy(vp1, vp2);
- --size;
- }
- if ((size -= offs) == 0) /* Get screen size. */
- panic("Illegal screen size in update");
- setscores(offs, size); /* Do hard update. */
- traceback(offs, size, size, size);
- for (i=0; i<size; ++i)
- ucopy(vscreen[offs+i], pscreen[offs+i]);
- ttmove(currow, curcol);
- ttflush();
- return;
- }
- #endif
- for (i=0; i<nrow-1; ++i) { /* Easy update. */
- vp1 = vscreen[i];
- vp2 = pscreen[i];
- if ((vp1->v_flag&VFCHG) != 0) {
- uline(i, vp1, vp2);
- ucopy(vp1, vp2);
- }
- }
- ttmove(currow, curcol);
- ttflush();
- }
-
- /*
- * Update a saved copy of a line,
- * kept in a VIDEO structure. The "vvp" is
- * the one in the "vscreen". The "pvp" is the one
- * in the "pscreen". This is called to make the
- * virtual and physical screens the same when
- * display has done an update.
- */
- ucopy(vvp, pvp) register VIDEO *vvp; register VIDEO *pvp; {
-
- vvp->v_flag &= ~VFCHG; /* Changes done. */
- pvp->v_flag = vvp->v_flag; /* Update model. */
- pvp->v_hash = vvp->v_hash;
- pvp->v_cost = vvp->v_cost;
- pvp->v_color = vvp->v_color;
- bcopy(vvp->v_text, pvp->v_text, ncol);
- }
-
- /*
- * Update a single line. This routine only
- * uses basic functionality (no insert and delete character,
- * but erase to end of line). The "vvp" points at the VIDEO
- * structure for the line on the virtual screen, and the "pvp"
- * is the same for the physical screen. Avoid erase to end of
- * line when updating CMODE color lines, because of the way that
- * reverse video works on most terminals.
- */
- VOID uline(row, vvp, pvp) VIDEO *vvp; VIDEO *pvp; {
- #ifdef MEMMAP
- putline(row+1, 1, &vvp->v_text[0]);
- #else
- register char *cp1;
- register char *cp2;
- register char *cp3;
- register char *cp4;
- register char *cp5;
- register int nbflag;
-
- if (vvp->v_color != pvp->v_color) { /* Wrong color, do a */
- ttmove(row, 0); /* full redraw. */
- #ifdef STANDOUT_GLITCH
- if (pvp->v_color != CTEXT && SG >= 0) tteeol();
- #endif
- ttcolor(vvp->v_color);
- #ifdef STANDOUT_GLITCH
- cp1 = &vvp->v_text[SG > 0 ? SG : 0];
- /* the odd code for SG==0 is to avoid putting the invisable
- * glitch character on the next line.
- * (Hazeltine executive 80 model 30)
- */
- cp2 = &vvp->v_text[ncol - (SG >= 0 ? (SG!=0 ? SG : 1) : 0)];
- #else
- cp1 = &vvp->v_text[0];
- cp2 = &vvp->v_text[ncol];
- #endif
- while (cp1 != cp2) {
- ttputc(*cp1++);
- ++ttcol;
- }
- #ifndef MOVE_STANDOUT
- ttcolor(CTEXT);
- #endif
- return;
- }
- cp1 = &vvp->v_text[0]; /* Compute left match. */
- cp2 = &pvp->v_text[0];
- while (cp1!=&vvp->v_text[ncol] && cp1[0]==cp2[0]) {
- ++cp1;
- ++cp2;
- }
- if (cp1 == &vvp->v_text[ncol]) /* All equal. */
- return;
- nbflag = FALSE;
- cp3 = &vvp->v_text[ncol]; /* Compute right match. */
- cp4 = &pvp->v_text[ncol];
- while (cp3[-1] == cp4[-1]) {
- --cp3;
- --cp4;
- if (cp3[0] != ' ') /* Note non-blanks in */
- nbflag = TRUE; /* the right match. */
- }
- cp5 = cp3; /* Is erase good? */
- if (nbflag==FALSE && vvp->v_color==CTEXT) {
- while (cp5!=cp1 && cp5[-1]==' ')
- --cp5;
- /* Alcyon hack */
- if ((int)(cp3-cp5) <= tceeol)
- cp5 = cp3;
- }
- /* Alcyon hack */
- ttmove(row, (int)(cp1-&vvp->v_text[0]));
- #ifdef STANDOUT_GLITCH
- if (vvp->v_color != CTEXT && SG > 0) {
- if(cp1 < &vvp->v_text[SG]) cp1 = &vvp->v_text[SG];
- if(cp5 > &vvp->v_text[ncol-SG]) cp5 = &vvp->v_text[ncol-SG];
- } else if (SG < 0)
- #endif
- ttcolor(vvp->v_color);
- while (cp1 != cp5) {
- ttputc(*cp1++);
- ++ttcol;
- }
- if (cp5 != cp3) /* Do erase. */
- tteeol();
- #endif
- }
-
- /*
- * Redisplay the mode line for
- * the window pointed to by the "wp".
- * This is the only routine that has any idea
- * of how the modeline is formatted. You can
- * change the modeline format by hacking at
- * this routine. Called by "update" any time
- * there is a dirty window.
- * Note that if STANDOUT_GLITCH is defined, first and last SG characters
- * may never be seen.
- */
- modeline(wp) register WINDOW *wp; {
- register int n;
- register BUFFER *bp;
-
- n = wp->w_toprow+wp->w_ntrows; /* Location. */
- vscreen[n]->v_color = CMODE; /* Mode line color. */
- vscreen[n]->v_flag |= (VFCHG|VFHBAD); /* Recompute, display. */
- vtmove(n, 0); /* Seek to right line. */
- bp = wp->w_bufp;
- vtputc('-'); vtputc('-');
- if ((bp->b_flag&BFCHG) != 0) { /* "*" if changed. */
- vtputc('*'); vtputc('*');
- } else {
- vtputc('-'); vtputc('-');
- }
- vtputc('-');
- n = 5;
- n += vtputs("MicroGnuEmacs:");
- if (bp->b_bname[0] != 0) {
- vtputc(' ');
- ++n;
- n += vtputs(&(bp->b_bname[0]));
- }
- while (n < 42) { /* Pad out with blanks */
- vtputc(' ');
- ++n;
- }
- vtputc('(');
- ++n;
- if (mode == 0) n += vtputs("Fundamental");
- else {
- if ((mode&MBSMAP) != 0) {
- n += vtputs("bsmap");
- if ((mode&~MBSMAP) != 0) {
- vtputc('-');
- ++n;
- }
- }
- if ((mode&MFLOW) != 0) {
- n += vtputs("flow");
- if ((mode&~(MFLOW|MBSMAP)) != 0) {
- vtputc('-');
- ++n;
- }
- }
- if ((mode&MINDENT) != 0) {
- n += vtputs("indent");
- if ((mode&~(MINDENT|MFLOW|MBSMAP)) != 0) {
- vtputc('-');
- ++n;
- }
- }
- if ((mode&MFILL) != 0)
- n += vtputs("fill");
- }
- vtputc(')');
- ++n;
- while (n < ncol) { /* Pad out. */
- vtputc('-');
- ++n;
- }
- }
- /*
- * output a string to the mode line, report how long it was.
- */
- vtputs(s) register char *s; {
- register int n = 0;
-
- while (*s != '\0') {
- vtputc(*s++);
- ++n;
- }
- return n;
- }
- #ifdef GOSLING
- /*
- * Compute the hash code for
- * the line pointed to by the "vp". Recompute
- * it if necessary. Also set the approximate redisplay
- * cost. The validity of the hash code is marked by
- * a flag bit. The cost understand the advantages
- * of erase to end of line. Tuned for the VAX
- * by Bob McNamara; better than it used to be on
- * just about any machine.
- */
- hash(vp) register VIDEO *vp; {
- register int i;
- register int n;
- register char *s;
-
- if ((vp->v_flag&VFHBAD) != 0) { /* Hash bad. */
- s = &vp->v_text[ncol-1];
- for (i=ncol; i!=0; --i, --s)
- if (*s != ' ')
- break;
- n = ncol-i; /* Erase cheaper? */
- if (n > tceeol)
- n = tceeol;
- vp->v_cost = i+n; /* Bytes + blanks. */
- for (n=0; i!=0; --i, --s)
- n = (n<<5) + n + *s;
- vp->v_hash = n; /* Hash code. */
- vp->v_flag &= ~VFHBAD; /* Flag as all done. */
- }
- }
-
- /*
- * Compute the Insert-Delete
- * cost matrix. The dynamic programming algorithm
- * described by James Gosling is used. This code assumes
- * that the line above the echo line is the last line involved
- * in the scroll region. This is easy to arrange on the VT100
- * because of the scrolling region. The "offs" is the origin 0
- * offset of the first row in the virtual/physical screen that
- * is being updated; the "size" is the length of the chunk of
- * screen being updated. For a full screen update, use offs=0
- * and size=nrow-1.
- *
- * Older versions of this code implemented the score matrix by
- * a two dimensional array of SCORE nodes. This put all kinds of
- * multiply instructions in the code! This version is written to
- * use a linear array and pointers, and contains no multiplication
- * at all. The code has been carefully looked at on the VAX, with
- * only marginal checking on other machines for efficiency. In
- * fact, this has been tuned twice! Bob McNamara tuned it even
- * more for the VAX, which is a big issue for him because of
- * the 66 line X displays.
- *
- * On some machines, replacing the "for (i=1; i<=size; ++i)" with
- * i = 1; do { } while (++i <=size)" will make the code quite a
- * bit better; but it looks ugly.
- */
- setscores(offs, size) {
- register SCORE *sp;
- SCORE *sp1;
- register int tempcost;
- register int bestcost;
- register int j;
- register int i;
- register VIDEO **vp;
- VIDEO **pp, **vbase, **pbase;
-
- vbase = &vscreen[offs-1]; /* By hand CSE's. */
- pbase = &pscreen[offs-1];
- score[0].s_itrace = 0; /* [0, 0] */
- score[0].s_jtrace = 0;
- score[0].s_cost = 0;
- sp = &score[1]; /* Row 0, inserts. */
- tempcost = 0;
- vp = &vbase[1];
- for (j=1; j<=size; ++j) {
- sp->s_itrace = 0;
- sp->s_jtrace = j-1;
- tempcost += tcinsl;
- tempcost += (*vp)->v_cost;
- sp->s_cost = tempcost;
- ++vp;
- ++sp;
- }
- sp = &score[NROW]; /* Column 0, deletes. */
- tempcost = 0;
- for (i=1; i<=size; ++i) {
- sp->s_itrace = i-1;
- sp->s_jtrace = 0;
- tempcost += tcdell;
- sp->s_cost = tempcost;
- sp += NROW;
- }
- sp1 = &score[NROW+1]; /* [1, 1]. */
- pp = &pbase[1];
- for (i=1; i<=size; ++i) {
- sp = sp1;
- vp = &vbase[1];
- for (j=1; j<=size; ++j) {
- sp->s_itrace = i-1;
- sp->s_jtrace = j;
- bestcost = (sp-NROW)->s_cost;
- if (j != size) /* Cd(A[i])=0 @ Dis. */
- bestcost += tcdell;
- tempcost = (sp-1)->s_cost;
- tempcost += (*vp)->v_cost;
- if (i != size) /* Ci(B[j])=0 @ Dsj. */
- tempcost += tcinsl;
- if (tempcost < bestcost) {
- sp->s_itrace = i;
- sp->s_jtrace = j-1;
- bestcost = tempcost;
- }
- tempcost = (sp-NROW-1)->s_cost;
- if ((*pp)->v_color != (*vp)->v_color
- || (*pp)->v_hash != (*vp)->v_hash)
- tempcost += (*vp)->v_cost;
- if (tempcost < bestcost) {
- sp->s_itrace = i-1;
- sp->s_jtrace = j-1;
- bestcost = tempcost;
- }
- sp->s_cost = bestcost;
- ++sp; /* Next column. */
- ++vp;
- }
- ++pp;
- sp1 += NROW; /* Next row. */
- }
- }
-
- /*
- * Trace back through the dynamic programming cost
- * matrix, and update the screen using an optimal sequence
- * of redraws, insert lines, and delete lines. The "offs" is
- * the origin 0 offset of the chunk of the screen we are about to
- * update. The "i" and "j" are always started in the lower right
- * corner of the matrix, and imply the size of the screen.
- * A full screen traceback is called with offs=0 and i=j=nrow-1.
- * There is some do-it-yourself double subscripting here,
- * which is acceptable because this routine is much less compute
- * intensive then the code that builds the score matrix!
- */
- VOID traceback(offs, size, i, j) {
- register int itrace;
- register int jtrace;
- register int k;
- register int ninsl;
- register int ndraw;
- register int ndell;
-
- if (i==0 && j==0) /* End of update. */
- return;
- itrace = score[(NROW*i) + j].s_itrace;
- jtrace = score[(NROW*i) + j].s_jtrace;
- if (itrace == i) { /* [i, j-1] */
- ninsl = 0; /* Collect inserts. */
- if (i != size)
- ninsl = 1;
- ndraw = 1;
- while (itrace!=0 || jtrace!=0) {
- if (score[(NROW*itrace) + jtrace].s_itrace != itrace)
- break;
- jtrace = score[(NROW*itrace) + jtrace].s_jtrace;
- if (i != size)
- ++ninsl;
- ++ndraw;
- }
- traceback(offs, size, itrace, jtrace);
- if (ninsl != 0) {
- ttcolor(CTEXT);
- ttinsl(offs+j-ninsl, offs+size-1, ninsl);
- }
- do { /* B[j], A[j] blank. */
- k = offs+j-ndraw;
- uline(k, vscreen[k], &blanks);
- } while (--ndraw);
- return;
- }
- if (jtrace == j) { /* [i-1, j] */
- ndell = 0; /* Collect deletes. */
- if (j != size)
- ndell = 1;
- while (itrace!=0 || jtrace!=0) {
- if (score[(NROW*itrace) + jtrace].s_jtrace != jtrace)
- break;
- itrace = score[(NROW*itrace) + jtrace].s_itrace;
- if (j != size)
- ++ndell;
- }
- if (ndell != 0) {
- ttcolor(CTEXT);
- ttdell(offs+i-ndell, offs+size-1, ndell);
- }
- traceback(offs, size, itrace, jtrace);
- return;
- }
- traceback(offs, size, itrace, jtrace);
- k = offs+j-1;
- uline(k, vscreen[k], pscreen[offs+i-1]);
- }
- #endif
- SHAR_EOF
- fi # end of overwriting check
- if test -f 'kbd.c'
- then
- echo shar: will not over-write existing file "'kbd.c'"
- else
- cat << \SHAR_EOF > 'kbd.c'
- /*
- * Terminal independent keyboard handling.
- */
- #include "def.h"
-
- #ifdef DPROMPT
- #define PROMPTL 80
- char prompt[PROMPTL], *promptp;
- #endif
-
- /*
- * All input from the user (should!) go through
- * getkey. Quotep is true to get raw keys, false to
- * get 11-bit code keys.
- * Getkey is responsible for putting keystrokes away
- * for macros. It also takes keystrokes out of the macro,
- * though other input routines will can also do this.
- * Read in a key, doing the terminal
- * independent prefix handling. The terminal specific
- * "getkbd" routine gets the first swing, and may return
- * one of the special codes used by the special keys
- * on the keyboard. The "getkbd" routine returns the
- * C0 controls as received; this routine moves them to
- * the right spot in 11 bit code.
- * If the KPROMPT bit in the flags is set and DPROMPT is
- * defined, do delayed prompting. (dprompt routine is
- * in sys/???/ttyio.c)
- */
- KEY
- getkey(f) register int f; {
- register KEY c;
- KEY keychar();
- int getkbd(), ttgetc();
-
- if (kbdmop != NULL) return *kbdmop++;
- #ifdef DPROMPT
- if(!(f&KPROMPT)) prompt[0] = '\0';
- #endif
- c = (KEY) mapin(getkbd);
- #ifdef DPROMPT
- if(f&KPROMPT) {
- if(promptp > prompt) *(promptp-1) = ' ';
- if(promptp >= &prompt[PROMPTL-8]) f &= ~KPROMPT;
- /* must have a lot of prefixes.... */
- }
- #endif
- if ((f&KQUOTE) == 0) {
- #ifdef DO_METAKEY
- if ((c & ~KCHAR) == KCTRL) /* Function key */
- c &= KCHAR; /* remove wrapping */
- else if ((c >= 0x80) && (c <= 0xFF)) /* real meta key */
- c = KMETA | keychar(c & ~0x80, TRUE);
- #endif
- #ifdef DPROMPT
- if(f&KPROMPT) {
- keyname(promptp, (c<=0x1F && c>=0x00)?KCTRL|(c+'@'):c);
- strcat(promptp, "-");
- }
- #endif
- if (c == METACH) /* M- */
- c = KMETA | keychar(mapin(ttgetc), TRUE);
- else if (c == CTRLCH) /* C- */
- c = KCTRL | keychar(mapin(ttgetc), TRUE);
- else if (c == CTMECH) /* C-M- */
- c = KCTRL | KMETA | keychar(mapin(ttgetc), TRUE);
- else if (c<=0x1F && c>=0x00) /* Relocate control. */
- c = KCTRL | (c+'@');
- if (c == (KCTRL|'X')) /* C-X */
- c = KCTLX | keychar(mapin(ttgetc), TRUE);
- }
-
- if ((f&KNOMAC) == 0 && kbdmip != NULL) {
- if (kbdmip+1 > &kbdm[NKBDM-3]) { /* macro overflow */
- (VOID) ctrlg(FALSE, 0, KRANDOM);
- ewprintf("Keyboard macro overflow");
- ttflush();
- return (KCTRL|'G'); /* ^G it for us */
- }
- *kbdmip++ = c;
- }
- #ifdef DPROMPT
- if(f&KPROMPT) {
- keyname(promptp, c);
- promptp += strlen(promptp);
- *promptp++ = '-';
- *promptp = '\0';
- }
- #endif
- return (c);
- }
-
- /*
- * go get a key, and run it through whatever mapping the modes
- * specify.
- */
- static mapin(get) int (*get)(); {
- register int c;
-
- #ifdef DPROMPT
- if(prompt[0]!='\0' && ttwait()) {
- ewprintf("%s", prompt); /* avoid problems with % */
- update(); /* put the cursor back */
- epresf = KPROMPT;
- }
- #endif
- c = (*get)();
- if ((mode&MFLOW) != 0) {
- while (c == CCHR('S') || c == CCHR('Q'))
- c = (*get)();
- if (c == CCHR('^')) c = CCHR('Q');
- else if (c == CCHR('\\')) c = CCHR('S');
- }
- if ((mode&MBSMAP) != 0)
- if (c == CCHR('H')) c = 0x7f;
- else if (c == 0x7f) c = CCHR('H');
- return c;
- }
- /*
- * Transform a key code into a name,
- * using a table for the special keys and combination
- * of some hard code and some general processing for
- * the rest. None of this code is terminal specific any
- * more. This makes adding keys easier.
- */
- VOID
- keyname(cp, k) register char *cp; register int k; {
- register char *np;
- register int c;
- char nbuf[3];
-
- static char hex[] = {
- '0', '1', '2', '3',
- '4', '5', '6', '7',
- '8', '9', 'A', 'B',
- 'C', 'D', 'E', 'F'
- };
-
- if ((k&KCTLX) != 0) { /* C-X prefix. */
- *cp++ = 'C';
- *cp++ = '-';
- *cp++ = 'x';
- *cp++ = ' ';
- }
- if ((k&KMETA) != 0) { /* Add M- mark. */
- *cp++ = 'E';
- *cp++ = 'S';
- *cp++ = 'C';
- *cp++ = ' ';
- }
- if ((k&KCHAR)>=KFIRST && (k&KCHAR)<=KLAST) {
- if ((np=keystrings[(k&KCHAR)-KFIRST]) != NULL) {
- if ((k&KCTRL) != 0) {
- *cp++ = 'C';
- *cp++ = '-';
- }
- (VOID) strcpy(cp, np);
- return;
- }
- }
- c = k & ~(KMETA|KCTLX);
- if (c == (KCTRL|'I')) /* Some specials. */
- np = "TAB";
- else if (c == (KCTRL|'M'))
- np = "RET";
- else if (c == (KCTRL|'J'))
- np = "LFD";
- else if (c == ' ')
- np = "SPC";
- else if (c == 0x7F)
- np = "DEL";
- else if (c == (KCTRL|'['))
- np = "ESC";
- else {
- if ((k&KCTRL) != 0) { /* Add C- mark. */
- *cp++ = 'C';
- *cp++ = '-';
- }
- if ((k&(KCTRL|KMETA|KCTLX)) != 0 && ISUPPER(k&KCHAR) != FALSE)
- k = TOLOWER(k&KCHAR);
- np = &nbuf[0];
- if (((k&KCHAR)>=0x20 && (k&KCHAR)<=0x7E)
- || ((k&KCHAR)>=0xA0 && (k&KCHAR)<=0xFE)) {
- nbuf[0] = k&KCHAR; /* Graphic. */
- nbuf[1] = 0;
- } else { /* Non graphic. */
- nbuf[0] = hex[(k>>4)&0x0F];
- nbuf[1] = hex[k&0x0F];
- nbuf[2] = 0;
- }
- }
- (VOID) strcpy(cp, np);
- }
-
- /*
- * turn a key into an internal char.
- */
- KEY
- keychar(c, f) register int c, f; {
-
- if (f == TRUE && ISLOWER(c) != FALSE)
- c = TOUPPER(c);
- else if (c>=0x00 && c<=0x1F) /* Relocate control. */
- c = (KCTRL|(c+'@'));
- return (KEY) c;
- }
- SHAR_EOF
- fi # end of overwriting check
- # End of shell archive
- exit 0
-
-