Merge branch 'vendor/EE'
authorSascha Wildner <saw@online.de>
Sun, 9 Feb 2014 05:09:01 +0000 (06:09 +0100)
committerSascha Wildner <saw@online.de>
Sun, 9 Feb 2014 05:09:01 +0000 (06:09 +0100)
13 files changed:
contrib/ee/Changes [new file with mode: 0644]
contrib/ee/Makefile [new file with mode: 0644]
contrib/ee/README.ee [new file with mode: 0644]
contrib/ee/create.make [new file with mode: 0755]
contrib/ee/ee.1 [new file with mode: 0644]
contrib/ee/ee.c [new file with mode: 0644]
contrib/ee/ee.i18n.guide [new file with mode: 0644]
contrib/ee/ee.msg [new file with mode: 0644]
contrib/ee/ee_version.h [new file with mode: 0644]
contrib/ee/genstr [new file with mode: 0755]
contrib/ee/make.default [new file with mode: 0644]
contrib/ee/new_curse.c [new file with mode: 0644]
contrib/ee/new_curse.h [new file with mode: 0644]

diff --git a/contrib/ee/Changes b/contrib/ee/Changes
new file mode 100644 (file)
index 0000000..0f2c8ab
--- /dev/null
@@ -0,0 +1,40 @@
+version 1.5.0 (2/16/2009)
+- added display of line number, column, and lines from top to separator line 
+  for info window
+- minor changes to reduce number of warnings when using -pedantic option
+
+version 1.4.7 (2/10/2009)
+- changed how strings are terminated from the old usage of NULL to the current 
+  use of character zero, '\0'
+- changed the licensing since the Artistic License is now considered 
+  restrictive
+
+version 1.4.6
+- modified new_curse.c to handle different subdirectory naming in terminfo 
+  directory; first noted on Mac OS 10.2
+
+version 1.4.5a (12/23/2001)
+- modified get_options to be cleaner for arg handling
+
+version 1.4.5 (12/15/2001)
+- made changes to check usage of arguments provided so that if a file is
+  specified options are no longer accepted (that is, they are treated as file
+  names)
+- changed to use ee_version.h to allow changing version number without need
+  to change ee.c directly
+
+version 1.4.4 (8/17/2001)
+- added code to check if the parent process has died, and if so to exit 
+  gracefully
+
+version 1.4.3 (6/25/2001)
+- modified create.make and new_curse.c to allow defining TERMCAP file 
+  location (since some distributions move the file)
+- source directory now has version number attached to directory name
+
+version 1.4.2 (1/19/2001)
+- change to create.make script to add unistd.h to files to search for 
+  select() declaration
+- change to new_curse.c for proper raw mode operation
+
+
diff --git a/contrib/ee/Makefile b/contrib/ee/Makefile
new file mode 100644 (file)
index 0000000..a6525ea
--- /dev/null
@@ -0,0 +1,29 @@
+# This is the make file for ee, the "easy editor".
+#
+# A file called 'make.local' will be generated which will contain information 
+# specific to the local system, such as if it is a BSD or System V based 
+# version of UNIX, whether or not it has catgets, or select.  
+#
+# The "install" target ("make install") will copy the ee binary to 
+# the /usr/local/bin directory on the local system.  The man page (ee.1) 
+# will be copied into the /usr/local/man/man1 directory.
+#
+# The "clean" target ("make clean") will remove the ee and new_curse.o 
+# object files, and the ee binary.
+#
+
+all :  localmake buildee
+
+buildee :      
+       make -f make.local
+
+localmake:
+       @./create.make
+
+install :
+       cp ee /usr/local/bin/ee
+       cp ee.1 /usr/local/man/man1/ee.1
+
+clean :
+       rm -f ee.o new_curse.o ee 
+
diff --git a/contrib/ee/README.ee b/contrib/ee/README.ee
new file mode 100644 (file)
index 0000000..bbb932f
--- /dev/null
@@ -0,0 +1,119 @@
+Copyright (c) 2009, Hugh Mahon
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above
+      copyright notice, this list of conditions and the following
+      disclaimer in the documentation and/or other materials provided
+      with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
+
+
+The editor 'ee' (easy editor) is intended to be a simple, easy to use 
+terminal-based screen oriented editor that requires no instruction to 
+use.  Its primary use would be for people who are new to computers, or who 
+use computers only for things like e-mail.
+
+ee's simplified interface is highlighted by the use of pop-up menus which 
+make it possible for users to carry out tasks without the need to 
+remember commands.  An information window at the top of the screen shows 
+the user the operations available with control-keys.
+
+ee allows users to use full eight-bit characters.  If the host system has 
+the capabilities, ee can use message catalogs, which would allow users to 
+translate the message catalog into other languages which use eight-bit 
+characters.  See the file ee.i18n.guide for more details.
+
+ee relies on the virtual memory abilities of the platform it is running on 
+and does not have its own memory management capabilities.
+
+I am releasing ee because I hate to see new users and non-computer types 
+get frustrated by vi, and would like to see more intuitive interfaces for 
+basic tools (both character-based and graphical) become more pervasive.
+Terminal capabilities and communication speeds have evolved considerably 
+since the time in which vi's interface was created, allowing much more 
+intuitive interfaces to be used.  Since character-based I/O won't be 
+completely replaced by graphical user interfaces for at least a few more 
+years, I'd like to do what I can to make using computers with less 
+glamorous interfaces as easy to use as possible.  If terminal interfaces 
+are still used in ten years, I hope neophytes won't still be stuck with 
+only vi.
+
+For a text editor to be easy to use requires a certain set of abilities.  In 
+order for ee to work, a terminal must have the ability to position the cursor 
+on the screen, and should have arrow keys that send unique sequences 
+(multiple characters, the first character is an "escape", octal code 
+'\033').  All of this information needs to be in a database called "terminfo" 
+(System V implementations) or "termcap" (usually used for BSD systems).  In 
+case the arrow keys do not transmit unique sequences, motion operations are 
+mapped to control keys as well, but this at least partially defeats the 
+purpose.  The curses package is used to handle the I/O which deals with the 
+terminal's capabilities.  
+
+While ee is based on curses, I have included here the source code to 
+new_curse, a subset of curses developed for use with ee.  'curses' often  
+will have a defect that reduces the usefulness of the editor relying upon 
+it.  
+
+The file new_curse.c contains a subset of 'curses', a package for 
+applications to use to handle screen output.  Unfortunately, curses 
+varies from system to system, so I developed new_curse to provide 
+consistent behavior across systems.  It works on both SystemV and BSD 
+systems, and while it can sometimes be slower than other curses packages, 
+it will get the information on the screen painted correctly more often 
+than vendor supplied curses.  Unless problems occur during the building 
+of ee, it is recommended that you use new_curse rather than the curses 
+supplied with your system.
+
+If you experience problems with data being displayed improperly, check 
+your terminal configuration, especially if you're using a terminal 
+emulator, and make sure that you are using the right terminfo entry 
+before rummaging through code.  Terminfo entries often contain 
+inaccuracies, or incomplete information, or may not totally match the 
+terminal or emulator the terminal information is being used with.  
+Complaints that ee isn't working quite right often end up being something 
+else (like the terminal emulator being used).  
+
+Both ee and new_curse were developed using K&R C (also known as "classic 
+C"), but it can also be compiled with ANSI C.  You should be able to 
+build ee by simply typing "make".  A make file which takes into account 
+the characteristics of your system will be created, and then ee will be 
+built.  If there are problems encountered, you will be notified about 
+them. 
+
+ee is the result of several conflicting design goals.  While I know that it 
+solves the problems of some users, I also have no doubt that some will decry 
+its lack of more features.  I will settle for knowing that ee does fulfill 
+the needs of a minority (but still large number) of users.  The goals of ee 
+are: 
+
+        1. To be so easy to use as to require no instruction.
+        2. To be easy to compile and, if necessary, port to new platforms 
+           by people with relatively little knowledge of C and UNIX.
+        3. To have a minimum number of files to be dealt with, for compile 
+           and installation.
+        4. To have enough functionality to be useful to a large number of 
+           people.
+
+Hugh Mahon              |___|     
+hugh4242@yahoo.com      |   |     
+                            |\  /|
+                            | \/ |
+
diff --git a/contrib/ee/create.make b/contrib/ee/create.make
new file mode 100755 (executable)
index 0000000..5d6ec30
--- /dev/null
@@ -0,0 +1,292 @@
+#!/bin/sh
+
+#
+#      This script will determine if the system is a System V or BSD based
+#      UNIX system and create a makefile for ee appropriate for the system.
+#
+# $Header: /home/hugh/sources/old_ae/RCS/create.make,v 1.13 2002/09/23 04:18:13 hugh Exp $
+#
+
+#set -x
+
+name_string="`uname`"
+
+# test for existence of termcap (exists on both BSD and SysV systems)
+
+if [ -f /etc/termcap -o -f /usr/share/lib/termcap -o -f /usr/share/misc/termcap ]
+then
+       if [ -f /usr/share/lib/termcap ]
+       then
+               termcap_exists="-DTERMCAP=\"\\\"/usr/share/lib/termcap\\\"\""
+       elif [ -f /usr/share/misc/termcap ]
+       then
+               termcap_exists="-DTERMCAP=\"\\\"/usr/share/misc/termcap\\\"\""
+       elif [ -f /etc/termcap ]
+       then
+               termcap_exists="-DTERMCAP=\"\\\"/etc/termcap\\\"\""
+       fi
+else
+       termcap_exists=""
+fi
+
+# test for terminfo directory (exists on SysV systems)
+
+if [ -d /usr/lib/terminfo -o -d /usr/share/lib/terminfo -o -d /usr/share/terminfo ]
+then
+       terminfo_exists=""
+else
+       terminfo_exists="-DCAP"
+fi
+
+# test for existence of termio header (on SysV systems)
+
+if [ -f /usr/include/termio.h ]
+then
+       termio="-DSYS5"
+else
+       termio=""
+fi
+
+# test for sgtty header (on BSD systems)
+
+if [ -f /usr/include/sgtty.h ]
+then
+       sgtty="TRUE"
+else
+       sgtty=""
+fi
+
+# look for select call in headers, make sure headers exist
+
+HEADER_FILES=""
+
+if [ -f /usr/include/sys/time.h ]
+then
+       HEADER_FILES="/usr/include/sys/time.h "
+fi
+
+if [ -f /usr/include/sys/types.h ]
+then
+       HEADER_FILES="$HEADER_FILES /usr/include/sys/types.h"
+fi
+
+# check for unistd.h
+
+if [ -f /usr/include/unistd.h ]
+then
+       HAS_UNISTD=-DHAS_UNISTD
+       HEADER_FILES="$HEADER_FILES /usr/include/unistd.h"
+else
+       HAS_UNISTD=""
+fi
+
+if [ -n "$HEADER_FILES" ]
+then
+       string="`grep select $HEADER_FILES`"
+       if [ -n "$string" ]
+       then
+               BSD_SELECT="-DBSD_SELECT"
+       else
+               BSD_SELECT=""
+       fi
+fi
+
+# check for existence of select.h (on AIX)
+
+if [ -f /usr/include/sys/select.h ]
+then
+       select_hdr="-DSLCT_HDR"
+else
+       select_hdr=""
+fi
+
+# check for stdlib.h
+
+if [ -f /usr/include/stdlib.h ]
+then
+       HAS_STDLIB=-DHAS_STDLIB
+else
+       HAS_STDLIB=""
+fi
+
+# check for stdarg.h
+
+if [ -f /usr/include/stdarg.h ]
+then
+       HAS_STDARG=-DHAS_STDARG
+else
+       HAS_STDARG=""
+fi
+
+# check for ctype.h
+
+if [ -f /usr/include/ctype.h ]
+then
+       HAS_CTYPE=-DHAS_CTYPE
+else
+       HAS_CTYPE=""
+fi
+
+# check for sys/ioctl.h
+
+if [ -f /usr/include/sys/ioctl.h ]
+then
+       HAS_SYS_IOCTL=-DHAS_SYS_IOCTL
+else
+       HAS_SYS_IOCTL=""
+fi
+
+# check for sys/wait.h
+
+if [ -f /usr/include/sys/wait.h ]
+then
+        HAS_SYS_WAIT=-DHAS_SYS_WAIT
+else
+        HAS_SYS_WAIT=""
+fi
+
+# check for localization headers
+
+if [ -f /usr/include/locale.h -a -f /usr/include/nl_types.h ]
+then
+       catgets=""
+else
+       catgets="-DNO_CATGETS"
+fi
+
+# make decisions about use of new_curse.c (use of new_curse is recommended 
+# rather than local curses)
+
+if [ -n "$terminfo_exists" -a -z "$termcap_exists" ]
+then
+       echo "Neither terminfo or termcap are on this system!  "
+       if [ -f /usr/include/curses.h ]
+       then
+               echo "Relying on local curses implementation."
+       else
+               cat <<-EOF
+               Don't know where to find curses, you'll need to modify 
+               source code to be able to build!
+               
+               Modify the file make.default and build ee by typing:
+               
+               make -f make.default
+               
+               EOF
+
+               exit 1
+       fi
+       
+       TARGET="curses"
+       curses=""
+else
+       curses="-DNCURSE"
+       TARGET="ee"
+fi
+
+if [ -z "$termio" -a -z "$sgtty" ]
+then
+       echo "Neither termio.h or sgtty.h are on this system!  "
+       if [ -f /usr/include/curses.h ]
+       then
+               echo "Relying on local curses implementation."
+       else
+               cat <<-EOF
+               Don't know where to find curses, you'll need to modify 
+               source code to be able to build!
+               
+               Modify the file make.default and build ee by typing:
+               
+               make -f make.default
+               
+               EOF
+
+               exit 1
+       fi
+       
+       TARGET="curses"
+       curses=""
+fi
+
+# check if this is a SunOS system
+
+if [ -d /usr/5include ]
+then
+       five_include="-I/usr/5include"
+else
+       five_include=""
+fi
+
+if [ -d /usr/5lib ]
+then
+       five_lib="-L/usr/5lib"
+else
+       five_lib=""
+fi
+
+
+if [ "$name_string" = "Darwin" ]
+then
+       if [ -n "$CFLAGS" ]
+       then
+               other_cflags="${CFLAGS} -DNO_CATGETS"
+       else
+               other_cflags="-DNO_CATGETS"
+       fi
+else
+
+       if [ -n "$CFLAGS" ]
+       then
+               if [ -z "`echo $CFLAGS | grep '[-]g'`" ]
+               then
+                       other_cflags="${CFLAGS} -s"
+               else
+                       other_cflags="${CFLAGS}"
+               fi
+       else
+               other_cflags="-s"
+       fi
+fi
+
+# time to write the makefile
+
+echo "Generating make.local"
+
+if [ -f make.local ]
+then
+       mv make.local make.lcl.old
+fi
+
+echo "DEFINES =        $termio $terminfo_exists $BSD_SELECT $catgets $select $curses " > make.local
+echo "" >> make.local
+echo "CFLAGS = $HAS_UNISTD $HAS_STDARG $HAS_STDLIB $HAS_CTYPE $HAS_SYS_IOCTL $HAS_SYS_WAIT $five_lib $five_include $select_hdr $other_cflags $termcap_exists" >> make.local
+echo "" >> make.local
+echo "" >> make.local
+echo "all :    $TARGET" >> make.local
+
+cat  >> make.local << EOF
+
+curses :       ee.c
+       cc ee.c -o ee \$(CFLAGS) -lcurses 
+
+ee :   ee.o new_curse.o
+       cc -o ee ee.o new_curse.o \$(CFLAGS) 
+
+ee.o : ee.c new_curse.h
+       cc -c ee.c \$(DEFINES) \$(CFLAGS) 
+
+new_curse.o :  new_curse.c new_curse.h
+       cc new_curse.c -c \$(DEFINES) \$(CFLAGS)
+
+EOF
+
+if [ -f make.lcl.old ]
+then
+       diffs="`cmp make.lcl.old make.local`"
+       if [ -n "${diffs}" ]
+       then
+               rm -f ee.o new_curse.o ee 
+       fi
+       rm -f make.lcl.old
+fi
+
diff --git a/contrib/ee/ee.1 b/contrib/ee/ee.1
new file mode 100644 (file)
index 0000000..18de1bb
--- /dev/null
@@ -0,0 +1,543 @@
+.\"
+.\"
+.\"  To format this reference page, use the command:
+.\"
+.\"    nroff -man ee.1
+.\"
+.\"  $Header: /home/hugh/sources/old_ae/RCS/ee.1,v 1.22 2001/12/16 04:49:27 hugh Exp $
+.\"
+.\"
+.TH ee 1 "" "" "" ""
+.SH NAME
+ee \- easy editor
+.SH SYNOPSIS
+.nf
+ee [-e] [-i] [-h] [+#] [\fIfile\fR ...]
+ree [-e] [-i] [-h] [+#] [\fIfile\fR ...]
+.ta
+.fi
+.ad b
+.SH DESCRIPTION
+The command 
+.I ee 
+is a simple screen oriented text editor.  It is always in text insertion 
+mode unless there is a prompt at the bottom of the terminal, or a 
+menu present (in a box in the middle of the terminal).  The command 
+.I ree 
+is the same as 
+.I ee, 
+but restricted to editing the named 
+file (no file operations, or shell escapes are allowed).
+.PP
+An editor with similar user-friendly qualities but more features is available 
+and is called 
+.I aee.
+.PP
+For 
+.I ee
+to work properly, the environment variable 
+.SM TERM 
+must be set to indicate the type of terminal being used.  For 
+example, for an 
+.SM HP 700/92 
+terminal, the 
+.SM TERM 
+variable should be set to "70092".  See your System Administrator if 
+you need more information.
+.\"
+.\"     options
+.\"
+.SS Options
+The following options are available from the command line:
+.PP
+.TP 4
+.B -e
+Turns off expansion of tab character to spaces.
+.TP 
+.B -i
+Turns off display of information window at top of terminal.
+.TP
+.B -h
+Turns off highlighting of borders of windows and menus (improves 
+performance on some terminals).
+.TP
+.B +#
+Moves the cursor to line '#' at startup.
+.br
+.\"
+.\"     control keys
+.\"
+.SS "Control keys"
+To do anything other than insert text, the user must use the control 
+keys (the 
+.B Control 
+key, represented by a "^",  pressed in conjunction with an 
+alphabetic key, e.g., ^a) and function keys available on the keyboard 
+(such as 
+.BR "Next Page" ", " "Prev Page" ,
+arrow keys, etc.).
+.PP
+Since not all terminals have function keys, 
+.I ee
+has the basic cursor movement functions assigned to control keys as 
+well as more intuitive keys on the keyboard when available.  For 
+instance, to move the cursor up, the user can use the up arrow key, 
+or 
+.BR ^u .
+.RS 4
+.nf
+.ta 1.4i
+.sp
+^a     Prompt for the decimal value of a character to insert.
+^b     Move to the bottom of the text.
+^c     Get the prompt for a command.
+^d     Move the cursor down.
+^e     Prompt for the string to search for.
+^f     Undelete the last deleted character.
+^g     Move to the beginning of the line.
+^h     Backspace.
+^i     Tab.
+^j     Insert a newline.
+^k     Delete the character the cursor is sitting on.
+^l     Move the cursor left.
+^m     Insert a newline.
+^n     Move to the next page.
+^o     Move to the end of the line.
+^p     Move to the previous page.
+^r     Move the cursor to the right.
+^t     Move to the top of the text.
+^u     Move the cursor up.
+^v     Undelete the last deleted word.
+^w     Delete the word beginning at the cursor position.
+^x     Search.
+^y     Delete from the cursor position to the end of line.
+^z     Undelete the last deleted line.
+^[ (ESC)       Pop up menu.
+.ta
+.fi
+.RE
+.sp
+.SS "EMACS keys mode"
+.PP
+Since many shells provide an Emacs mode (for cursor movement and other editing 
+operations), some bindings that may be more useful for people familiar with 
+those bindings have been provided.  These are accessible via the 
+.B settings 
+menu, or via the initialization file (see below).  The mappings are as follows:
+.RS
+.nf
+.ta 1.4i
+^a     Move to the beginning of the line.
+^b     Back 1 character.
+^c     Command prompt.
+^d     Delete character the cursor is sitting on.
+^e     End of line.
+^f     Forward 1 character.
+^g     Go back 1 page.
+^h     Backspace.
+^i     Tab.
+^j     Undelete last deleted character.
+^k     Delete line.
+^l     Undelete last deleted line.
+^m     Insert a newline.
+^n     Move to the next line.
+^o     Prompt for the decimal value of a character to insert.
+^p     Previous line.
+^r     Restore last deleted word.
+^t     Move to the top of the text.
+^u     Move to the bottom of the text.
+^v     Move to the next page.
+^w     Delete the word beginning at the cursor position.
+^y     Prompt for the string to search for.
+^z     Next word.
+^[ (ESC)       Pop up menu.
+.ta
+.fi
+.RE
+.sp
+.\"
+.\"     function keys
+.\"
+.SS "Function Keys"
+.RS 4
+.IP "\fBNext Page\fR"
+Move to the next page.
+.IP "\fBPrev Page\fR"
+Move to the previous page.
+.IP "\fBDelete Char\fR"
+Delete the character the cursor is on.
+.IP "\fBDelete Line\fR"
+Delete from the cursor to the end of line.
+.IP "\fBInsert line\fR"
+Insert a newline at the cursor position.
+.IP "\fBArrow keys\fR"
+Move the cursor in the direction indicated.
+.RE
+.\"
+.\"     commands
+.\"
+.SS Commands
+.PP
+Some operations require more information than a single keystroke can 
+provide.  For the most basic operations, there is a menu that can be 
+obtained by pressing the 
+.SM \fBESC\fR
+key.  The same operations, and more can be performed by obtaining the 
+command prompt (^c) and typing in one of the commands below.
+.RS 4
+.IP "!\fBcmd\fR"
+Execute \fBcmd\fR in a shell.
+.IP "\fB0-9\fR"
+Move to the line indicated.
+.IP "\fBcase\fR"
+Make searches case sensitive.
+.IP "\fBcharacter\fR"
+Display the ascii value of the character at the cursor.
+.IP "\fBexit\fR"
+Save the edited text, and leave the editor.
+.IP "\fBexpand\fR"
+Expand tabs to spaces.
+.IP "\fBfile\fR"
+Print the name of the file.
+.IP "\fBhelp\fR"
+Display help screen.
+.IP "\fBline\fR"
+Display the current line number.
+.IP "\fBnocase\fR
+Make searches insensitive to case (the default).
+.IP "\fBnoexpand\fR"
+Don't expand tab to spaces when the TAB key is pressed.
+.IP "\fBquit\fR"
+Leave the editor without saving changes.
+.IP "\fBread\fR \fIfile\fR"
+Read the named \fIfile\fR.
+.IP "\fBwrite\fR \fIfile\fR"
+Write the text to the named \fIfile\fR.
+.RE
+.\"
+.\"     menu operations
+.\"
+.SS "Menu Operations"
+.PP
+Pop-up menus can be obtained by pressing the 
+.B escape 
+key (or 
+.B ^[ 
+if no 
+.B escape 
+key is present).  When in the menu, the escape key can be 
+used to leave the menu without performing any operations.  Use the up and 
+down arrow keys, or 
+.B ^u
+for moving up and 
+.B ^d 
+for moving down to move to the desired items in the menu, then press 
+.B return 
+to perform the indicated task.
+.PP
+To the left of each menu item is a letter, which if the corresponding 
+letter is pressed on the keyboard selects that menu entry.
+.PP
+The main menu in \fIee\fR is as follows:
+.RS 4
+.IP "\fBleave editor\fR" 
+If changes have been made, the user will get a menu prompting whether or 
+not the changes should be saved.
+.IP "\fBhelp\fR"
+Displays a help screen, with all of the keyboard operations and commands.
+.IP "\fBfile operations\fR"
+Pops up a menu for selecting whether to read a file, write to a file, or 
+save the current contents of the editor, as well as send the contents of 
+the editor to a print command (see the section \fBInitializing ee from a 
+file\fR).
+.IP "\fBredraw screen\fR"
+Provides a means to repaint the screen if the screen has been corrupted.
+.IP "\fBsettings\fR"
+Shows the current values of the operating modes, and right margin.  By 
+pressing return when the cursor is on a particular item, the value can be 
+changed.  To leave this menu, press the \fBescape\fR key.  (See \fBModes\fR 
+below.)
+.IP "\fBsearch\fR"
+.br
+Pops up a menu in which the user may choose to enter a string to search 
+for, or search for a string already entered.
+.IP "\fBmiscellaneous\fR"
+Pops up a menu that allows the user to format the current paragraph, 
+execute a shell command, or check the spelling of the text in the editor.
+.RE
+.\"
+.\"     paragraph formatting
+.\"
+.SS "Paragraph Formatting"
+.PP
+Paragraphs are defined for \fIee\fR by a block of text bounded by:
+.sp 
+.RS 8
+.IP \(bu 
+Begin or end of file.
+.IP \(bu
+Line with no characters, or only spaces and/or tabs.
+.IP \(bu
+Line starting with a period ('.') or right angle bracket ('>').
+.RE
+.PP
+A paragraph may be formatted two ways:  explicitly by choosing the 
+\fBformat paragraph\fR menu item, or by setting \fIee\fR to automatically 
+format paragraphs.  The automatic mode may be set via a menu, or via the 
+initialization file.
+.PP
+There are three states for text operation in \fIee\fR: free-form, margins, 
+and automatic formatting.
+.PP
+"Free-form" is best used for things like programming.  There are no 
+restrictions on the length of lines, and no formatting takes place.
+.PP
+"Margins" allows the user to type in text without having to worry about going 
+beyond the right margin (the right margin may be set in the \fBsettings\fR 
+menu, the default is for the margin to be the right edge of the 
+terminal).  This is the mode that allows the \fBformat paragraph\fR menu 
+item to work.
+.PP
+"Automatic formatting" provides word-processor-like behavior.  The user 
+may type in text, while \fIee\fR will make sure the entire paragraph fits 
+within the width of the terminal every time the user inserts a space after 
+typing or deleting text.  Margin observation must also be enabled in order for 
+automatic formatting to occur.
+.\"
+.\"     modes
+.\"
+.SS Modes
+.PP
+Although ee is a 'modeless' editor (it is in text insertion mode all the 
+time), there are modes in some of the things it does.  These include:
+.RS 4
+.IP "\fBtab expansion\fR"
+Tabs may be inserted as a single tab character, or replaced with spaces.
+.IP "\fBcase sensitivity\fR"
+The search operation can be sensitive to whether characters are upper- or 
+lower-case, or ignore case completely.
+.IP "\fBmargins observed\fR"
+Lines can either be truncated at the right margin, or extend on forever.
+.IP "\fBauto paragraph formatting\fR"
+While typing in text, the editor can try to keep it looking reasonably well 
+within the width of the screen.
+.IP "\fBeightbit characters\fR"
+Toggles whether eight bit characters are displayed as their value in angle 
+brackets (e.g. "<220>") or as a character.
+.IP "\fBinfo window\fR"
+A window showing the keyboard operations that can be performed can be 
+displayed or not.
+.IP "\fBemacs keys\fR"
+Control keys may be given bindings similar to emacs, or not.
+.IP "\f16 bit characters\fR"
+Toggles whether sixteen bit characters are handled as one 16-bit quantities or 
+two 8-bit quantities.  This works primarily with the Chinese Big 5 code set.
+.RE
+.PP
+You may set these modes via the initialization file (see below), or with a 
+menu (see above).
+.\"
+.\"     spell checking
+.\"
+.SS "Spell Checking"
+.PP
+There are two ways to have the spelling in the text checked from \fIee\fR.  
+One is by the traditional \fIspell\fR(1) command, the other is with the 
+optional \fIispell\fR(1) command.
+.PP
+Using \fIspell\fR, the words that are not recognized will be placed at the top 
+of the file.  For the \fIispell\fR option, the file is written to disk, 
+then \fIispell\fR run on the file, and the file read back in once 
+\fIispell\fR has completed making changes to the file.
+.\"
+.\"     printing
+.\"
+.SS "Printing the contents of the editor"
+.PP
+The user may select a menu item which prints the contents of the editor.  
+.I ee
+pipes the text in the editor to the command specified by the 
+initialization command 
+.B printcommand
+(see the section 
+.B Initializing ee from a file 
+below).  The default is to send the contents to "lp".  
+.PP
+Whatever the user assigns to 
+.B printcommand 
+must take input from 
+standard input.  See your system administrator for more details.
+.\"
+.\"     shell operations
+.\"
+.SS "Shell operations"
+.PP
+Shell commands can be executed from within 
+.I ee 
+by selecting the 
+.B shell command 
+item in the 
+.B miscellaneous 
+menu, or by placing an exclamation mark ("!") before the command to 
+execute at the 
+.B command: 
+prompt.  Additionally, the user may direct the contents of the edit buffer 
+out to a shell operation (via a pipe) by using the left angle bracket 
+(">"), followed by a "!" and the shell command to execute.  The output of 
+a shell operation can also be directed into the edit buffer by using a 
+right angle bracket ("<") before the exclamation mark.  These can even be 
+used together to send output to a shell operation and read back the 
+results into the editor.  So, if the editor contained a list of words 
+to be sorted, they could be sorted by typing the following at the command 
+prompt:
+.RS 4
+.sp
+><!sort
+.sp
+.RE
+This would send the contents of the editor to be piped into the 
+.I sort 
+utility and the result would be placed into the edit buffer at the current 
+cursor location.  The old information would have to be deleted by the user.
+.\"
+.\"     initializing ee from a file
+.\"
+.SS "Initializing ee from a file"
+.PP
+Since different users have different preferences, \fIee\fR allows some 
+slight configurability.  There are three possible locations for an 
+initialization file for ee:  the file \fI/usr/local/lib/init.ee\fR, the 
+file \fI.init.ee\fR in the user's home directory, or the file \fI.init.ee\fR 
+in the current directory (if different from the home 
+directory).  This allows system administrators to set some preferences for 
+the users on a system-wide basis (for example, the \fBprint\fR command), 
+and the user to customize settings for particular directories (like one 
+for correspondence, and a different directory for programming).
+.PP
+The file \fI\/usr/local/lib/init.ee\fR is read first, then 
+\fI$HOME/.init.ee\fR, then \fI.init.ee\fR, with the settings specified by the 
+most recent file read taking precedence.
+.PP
+The following items may be entered in the initialization file:
+.RS 4
+.IP \fBcase\fR
+Sets searches to be case sensitive.
+.IP \fBnocase\fR
+Sets searches to be insensitive to case (default).
+.IP \fBexpand\fR
+Causes \fIee\fR to expand tabs to spaces (default).
+.IP \fBnoexpand\fR 
+Causes \fIee\fR to insert tabs as a single character.
+.IP \fBinfo\fR
+A small information window is displayed at the top of the terminal 
+(default).
+.IP \fBnoinfo\fR
+Turns off the display of the information window.
+.IP \fBmargins\fR
+Causes \fIee\fR to truncate lines at the right margin when the 
+cursor passes beyond the right margin as set by the user 
+while text is being inserted 
+(default).
+.IP \fBnomargins\fR
+Allows lines to extend beyond the right margin.
+.IP \fBautoformat\fR
+Causes \fIee\fR to automatically try to format the current paragraph while 
+text insertion is occurring.
+.IP \fBnoautoformat\fR
+Turns off automatic paragraph formatting (default).
+.IP \fBprintcommand\fR
+Allows the setting of the print command (default: "lp").
+.IP \fBrightmargin\fR
+The user can select a value for the right margin (the first column on the 
+screen is zero).
+.IP \fBhighlight\fR
+Turns on highlighting border of information window and menus (default).
+.IP \fBnohighlight\fR
+Turns off highlighting of border of information window and menus.
+.IP \fBeightbit\fR
+Turns on display of eight bit characters.
+.IP \fBnoeightbit\fR
+Turns off display of eight bit characters (they are displayed as their decimal 
+value inside angle brackets, e.g., "<220>").
+.IP \fB16bit\fR
+Turns on handling of 16-bit characters.
+.IP \fbno16bit\fR
+Turns off handling of 16-bit characters.
+.IP \fBemacs\fR
+Turns on emacs key bindings.
+.IP \fBnoemacs\fR
+Turns off emacs key bindings.
+.RE
+.\"
+.\"     save editor configuration
+.\"
+.SS "Save Editor Configuration"
+.PP
+When using this entry from the 
+.B settings 
+menu, the user may choose to save the current configuration of 
+the editor (see \fBInitializing ee from a 
+file\fR above) to a file named 
+.I .init.ee 
+in the current directory or the user's home directory.  If a file named 
+.I .init.ee 
+already exists, it will be renamed 
+.IR .init.ee.old .
+.\"
+.\"     Caveats
+.\"
+.SH CAVEATS
+.PP
+THIS MATERIAL IS PROVIDED "AS IS".  THERE ARE 
+NO WARRANTIES OF ANY KIND WITH REGARD TO THIS 
+MATERIAL, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND 
+FITNESS FOR A PARTICULAR PURPOSE.  Neither 
+Hewlett-Packard nor Hugh Mahon shall be liable 
+for errors contained herein, nor for 
+incidental or consequential damages in 
+connection with the furnishing, performance or 
+use of this material.  Neither Hewlett-Packard 
+nor Hugh Mahon assumes any responsibility for 
+the use or reliability of this software or 
+documentation.  This software and 
+documentation is totally UNSUPPORTED.  There 
+is no support contract available.  Hewlett-Packard 
+has done NO Quality Assurance on ANY 
+of the program or documentation.  You may find 
+the quality of the materials inferior to 
+supported materials. 
+.PP
+Always make a copy of files that cannot be easily reproduced before 
+editing.  Save files early, and save often.
+.SS "International Code Set Support"
+.I ee 
+supports single-byte character code sets (eight-bit clean), or the 
+Chinese Big-5 code set.  (Other multi-byte code sets may function, but the 
+reason Big-5 works is that a two-byte character also takes up two columns on 
+the screen.)
+.SH WARNINGS
+The automatic paragraph formatting operation 
+may be too slow for slower systems.
+.SH FILES
+.PP
+.I /usr/local/lib/init.ee
+.br
+.I $HOME/.init.ee
+.br
+.I .init.ee
+.SH AUTHOR
+.PP
+The software 
+.I ee
+was developed by Hugh Mahon.
+.PP
+This software and documentation contains 
+proprietary information which is protected by 
+copyright.  All rights are reserved. 
+.PP
+Copyright (c) 1990, 1991, 1992, 1993, 1995, 1996, 2001 Hugh Mahon.
+.SH "SEE ALSO"
+.PP
+termcap(4), terminfo(4), environ(5), spell(1), ispell(1), lp(1), aee(1)
+
diff --git a/contrib/ee/ee.c b/contrib/ee/ee.c
new file mode 100644 (file)
index 0000000..8deb569
--- /dev/null
@@ -0,0 +1,5350 @@
+/*
+ |     ee (easy editor)
+ |
+ |     An easy to use, simple screen oriented editor.
+ |
+ |     written by Hugh Mahon
+ |
+ |
+ |      Copyright (c) 2009, Hugh Mahon
+ |      All rights reserved.
+ |      
+ |      Redistribution and use in source and binary forms, with or without
+ |      modification, are permitted provided that the following conditions
+ |      are met:
+ |      
+ |          * Redistributions of source code must retain the above copyright
+ |            notice, this list of conditions and the following disclaimer.
+ |          * Redistributions in binary form must reproduce the above
+ |            copyright notice, this list of conditions and the following
+ |            disclaimer in the documentation and/or other materials provided
+ |            with the distribution.
+ |      
+ |      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ |      "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ |      LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ |      FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ |      COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ |      INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ |      BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ |      LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ |      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ |      LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ |      ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ |      POSSIBILITY OF SUCH DAMAGE.
+ |
+ |     -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
+ |
+ |     This editor was purposely developed to be simple, both in 
+ |     interface and implementation.  This editor was developed to 
+ |     address a specific audience: the user who is new to computers 
+ |     (especially UNIX).
+ |     
+ |     ee is not aimed at technical users; for that reason more 
+ |     complex features were intentionally left out.  In addition, 
+ |     ee is intended to be compiled by people with little computer 
+ |     experience, which means that it needs to be small, relatively 
+ |     simple in implementation, and portable.
+ |
+ |     This software and documentation contains
+ |     proprietary information which is protected by
+ |     copyright.  All rights are reserved.
+ |
+ |     $Header: /home/hugh/sources/old_ae/RCS/ee.c,v 1.104 2010/06/04 01:55:31 hugh Exp hugh $
+ |
+ */
+
+char *ee_copyright_message = 
+"Copyright (c) 1986, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 2009 Hugh Mahon ";
+
+#include "ee_version.h"
+
+char *version = "@(#) ee, version "  EE_VERSION  " $Revision: 1.104 $";
+
+#ifdef NCURSE
+#include "new_curse.h"
+#elif HAS_NCURSES
+#include <ncurses.h>
+#else
+#include <curses.h>
+#endif
+
+#ifdef HAS_CTYPE
+#include <ctype.h>
+#endif
+
+#include <signal.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <string.h>
+#include <pwd.h>
+
+#ifdef HAS_SYS_WAIT
+#include <sys/wait.h>
+#endif
+
+#ifdef HAS_STDLIB
+#include <stdlib.h>
+#endif
+
+#ifdef HAS_STDARG
+#include <stdarg.h>
+#endif
+
+#ifdef HAS_UNISTD
+#include <unistd.h>
+#endif
+
+
+#ifndef NO_CATGETS
+#include <locale.h>
+#include <nl_types.h>
+
+nl_catd catalog;
+#else
+#define catgetlocal(a, b) (b)
+#endif /* NO_CATGETS */
+
+#ifndef SIGCHLD
+#define SIGCHLD SIGCLD
+#endif
+
+#define TAB 9
+#define max(a, b)      (a > b ? a : b)
+#define min(a, b)      (a < b ? a : b)
+
+/*
+ |     defines for type of data to show in info window
+ */
+
+#define CONTROL_KEYS 1
+#define COMMANDS     2
+
+struct text {
+       unsigned char *line;            /* line of characters           */
+       int line_number;                /* line number                  */
+       int line_length;        /* actual number of characters in the line */
+       int max_length; /* maximum number of characters the line handles */
+       struct text *next_line;         /* next line of text            */
+       struct text *prev_line;         /* previous line of text        */
+       };
+
+struct text *first_line;       /* first line of current buffer         */
+struct text *dlt_line;         /* structure for info on deleted line   */
+struct text *curr_line;                /* current line cursor is on            */
+struct text *tmp_line;         /* temporary line pointer               */
+struct text *srch_line;                /* temporary pointer for search routine */
+
+struct files {         /* structure to store names of files to be edited*/
+       unsigned char *name;            /* name of file                         */
+       struct files *next_name;
+       };
+
+struct files *top_of_stack = NULL;
+
+int d_wrd_len;                 /* length of deleted word               */
+int position;                  /* offset in bytes from begin of line   */
+int scr_pos;                   /* horizontal position                  */
+int scr_vert;                  /* vertical position on screen          */
+int scr_horz;                  /* horizontal position on screen        */
+int absolute_lin;              /* number of lines from top             */
+int tmp_vert, tmp_horz;
+int input_file;                        /* indicate to read input file          */
+int recv_file;                 /* indicate reading a file              */
+int edit;                      /* continue executing while true        */
+int gold;                      /* 'gold' function key pressed          */
+int fildes;                    /* file descriptor                      */
+int case_sen;                  /* case sensitive search flag           */
+int last_line;                 /* last line for text display           */
+int last_col;                  /* last column for text display         */
+int horiz_offset = 0;          /* offset from left edge of text        */
+int clear_com_win;             /* flag to indicate com_win needs clearing */
+int text_changes = FALSE;      /* indicate changes have been made to text */
+int get_fd;                    /* file descriptor for reading a file   */
+int info_window = TRUE;                /* flag to indicate if help window visible */
+int info_type = CONTROL_KEYS;  /* flag to indicate type of info to display */
+int expand_tabs = TRUE;                /* flag for expanding tabs              */
+int right_margin = 0;          /* the right margin                     */
+int observ_margins = TRUE;     /* flag for whether margins are observed */
+int shell_fork;
+int temp_stdin;                        /* temporary storage for stdin          */
+int temp_stdout;               /* temp storage for stdout descriptor   */
+int temp_stderr;               /* temp storage for stderr descriptor   */
+int pipe_out[2];               /* pipe file desc for output            */
+int pipe_in[2];                        /* pipe file descriptors for input      */
+int out_pipe;                  /* flag that info is piped out          */
+int in_pipe;                   /* flag that info is piped in           */
+int formatted = FALSE;         /* flag indicating paragraph formatted  */
+int auto_format = FALSE;       /* flag for auto_format mode            */
+int restricted = FALSE;                /* flag to indicate restricted mode     */
+int nohighlight = FALSE;       /* turns off highlighting               */
+int eightbit = TRUE;           /* eight bit character flag             */
+int local_LINES = 0;           /* copy of LINES, to detect when win resizes */
+int local_COLS = 0;            /* copy of COLS, to detect when win resizes  */
+int curses_initialized = FALSE;        /* flag indicating if curses has been started*/
+int emacs_keys_mode = FALSE;   /* mode for if emacs key binings are used    */
+int ee_chinese = FALSE;                /* allows handling of multi-byte characters  */
+                               /* by checking for high bit in a byte the    */
+                               /* code recognizes a two-byte character      */
+                               /* sequence                                  */
+
+unsigned char *point;          /* points to current position in line   */
+unsigned char *srch_str;       /* pointer for search string            */
+unsigned char *u_srch_str;     /* pointer to non-case sensitive search */
+unsigned char *srch_1;         /* pointer to start of suspect string   */
+unsigned char *srch_2;         /* pointer to next character of string  */
+unsigned char *srch_3;
+unsigned char *in_file_name = NULL;    /* name of input file           */
+char *tmp_file;        /* temporary file name                  */
+unsigned char *d_char;         /* deleted character                    */
+unsigned char *d_word;         /* deleted word                         */
+unsigned char *d_line;         /* deleted line                         */
+char in_string[513];   /* buffer for reading a file            */
+unsigned char *print_command = (unsigned char *)"lpr"; /* string to use for the print command  */
+unsigned char *start_at_line = NULL;   /* move to this line at start of session*/
+int in;                                /* input character                      */
+
+FILE *temp_fp;                 /* temporary file pointer               */
+FILE *bit_bucket;              /* file pointer to /dev/null            */
+
+char *table[] = { 
+       "^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "\t", "^J", 
+       "^K", "^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", 
+       "^V", "^W", "^X", "^Y", "^Z", "^[", "^\\", "^]", "^^", "^_"
+       };
+
+WINDOW *com_win;
+WINDOW *text_win;
+WINDOW *help_win;
+WINDOW *info_win;
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define P_(s) s
+#else
+#define P_(s) ()
+#endif
+
+
+/*
+ |     The following structure allows menu items to be flexibly declared.
+ |     The first item is the string describing the selection, the second 
+ |     is the address of the procedure to call when the item is selected,
+ |     and the third is the argument for the procedure.
+ |
+ |     For those systems with i18n, the string should be accompanied by a
+ |     catalog number.  The 'int *' should be replaced with 'void *' on 
+ |     systems with that type.
+ |
+ |     The first menu item will be the title of the menu, with NULL 
+ |     parameters for the procedure and argument, followed by the menu items.
+ |
+ |     If the procedure value is NULL, the menu item is displayed, but no 
+ |     procedure is called when the item is selected.  The number of the 
+ |     item will be returned.  If the third (argument) parameter is -1, no 
+ |     argument is given to the procedure when it is called.
+ */
+
+struct menu_entries {
+       char *item_string;
+       int (*procedure)P_((struct menu_entries *));
+       struct menu_entries *ptr_argument;
+       int (*iprocedure)P_((int));
+       void (*nprocedure)P_((void));
+       int argument;
+       };
+
+int main P_((int argc, char *argv[]));
+unsigned char *resiz_line P_((int factor, struct text *rline, int rpos));
+void insert P_((int character));
+void delete P_((int disp));
+void scanline P_((unsigned char *pos));
+int tabshift P_((int temp_int));
+int out_char P_((WINDOW *window, int character, int column));
+int len_char P_((int character, int column));
+void draw_line P_((int vertical, int horiz, unsigned char *ptr, int t_pos, int length));
+void insert_line P_((int disp));
+struct text *txtalloc P_((void));
+struct files *name_alloc P_((void));
+unsigned char *next_word P_((unsigned char *string));
+void prev_word P_((void));
+void control P_((void));
+void emacs_control P_((void));
+void bottom P_((void));
+void top P_((void));
+void nextline P_((void));
+void prevline P_((void));
+void left P_((int disp));
+void right P_((int disp));
+void find_pos P_((void));
+void up P_((void));
+void down P_((void));
+void function_key P_((void));
+void print_buffer P_((void));
+void command_prompt P_((void));
+void command P_((char *cmd_str1));
+int scan P_((char *line, int offset, int column));
+char *get_string P_((char *prompt, int advance));
+int compare P_((char *string1, char *string2, int sensitive));
+void goto_line P_((char *cmd_str));
+void midscreen P_((int line, unsigned char *pnt));
+void get_options P_((int numargs, char *arguments[]));
+void check_fp P_((void));
+void get_file P_((char *file_name));
+void get_line P_((int length, unsigned char *in_string, int *append));
+void draw_screen P_((void));
+void finish P_((void));
+int quit P_((int noverify));
+void edit_abort P_((int arg));
+void delete_text P_((void));
+int write_file P_((char *file_name, int warn_if_exists));
+int search P_((int display_message));
+void search_prompt P_((void));
+void del_char P_((void));
+void undel_char P_((void));
+void del_word P_((void));
+void undel_word P_((void));
+void del_line P_((void));
+void undel_line P_((void));
+void adv_word P_((void));
+void move_rel P_((char direction, int lines));
+void eol P_((void));
+void bol P_((void));
+void adv_line P_((void));
+void sh_command P_((char *string));
+void set_up_term P_((void));
+void resize_check P_((void));
+int menu_op P_((struct menu_entries *));
+void paint_menu P_((struct menu_entries menu_list[], int max_width, int max_height, int list_size, int top_offset, WINDOW *menu_win, int off_start, int vert_size));
+void help P_((void));
+void paint_info_win P_((void));
+void no_info_window P_((void));
+void create_info_window P_((void));
+int file_op P_((int arg));
+void shell_op P_((void));
+void leave_op P_((void));
+void redraw P_((void));
+int Blank_Line P_((struct text *test_line));
+void Format P_((void));
+void ee_init P_((void));
+void dump_ee_conf P_((void));
+void echo_string P_((char *string));
+void spell_op P_((void));
+void ispell_op P_((void));
+int first_word_len P_((struct text *test_line));
+void Auto_Format P_((void));
+void modes_op P_((void));
+char *is_in_string P_((char *string, char *substring));
+char *resolve_name P_((char *name));
+int restrict_mode P_((void));
+int unique_test P_((char *string, char *list[]));
+void strings_init P_((void));
+
+#undef P_
+/*
+ |     allocate space here for the strings that will be in the menu
+ */
+
+struct menu_entries modes_menu[] = {
+       {"", NULL, NULL, NULL, NULL, 0},        /* title                */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 1. tabs to spaces    */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 2. case sensitive search*/
+       {"", NULL, NULL, NULL, NULL, -1},       /* 3. margins observed  */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 4. auto-paragraph    */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 5. eightbit characters*/
+       {"", NULL, NULL, NULL, NULL, -1},       /* 6. info window       */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 7. emacs key bindings*/
+       {"", NULL, NULL, NULL, NULL, -1},       /* 8. right margin      */
+       {"", NULL, NULL, NULL, NULL, -1},       /* 9. chinese text      */
+       {"", NULL, NULL, NULL, dump_ee_conf, -1}, /* 10. save editor config */
+       {NULL, NULL, NULL, NULL, NULL, -1}      /* terminator           */
+       };
+
+char *mode_strings[11]; 
+
+#define NUM_MODES_ITEMS 10
+
+struct menu_entries config_dump_menu[] = {
+       {"", NULL, NULL, NULL, NULL, 0}, 
+       {"", NULL, NULL, NULL, NULL, -1},
+       {"", NULL, NULL, NULL, NULL, -1},
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+struct menu_entries leave_menu[] = {
+       {"", NULL, NULL, NULL, NULL, -1}, 
+       {"", NULL, NULL, NULL, finish, -1}, 
+       {"", NULL, NULL, quit, NULL, TRUE}, 
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+#define READ_FILE 1
+#define WRITE_FILE 2
+#define SAVE_FILE 3
+
+struct menu_entries file_menu[] = {
+       {"", NULL, NULL, NULL, NULL, -1},
+       {"", NULL, NULL, file_op, NULL, READ_FILE},
+       {"", NULL, NULL, file_op, NULL, WRITE_FILE},
+       {"", NULL, NULL, file_op, NULL, SAVE_FILE},
+       {"", NULL, NULL, NULL, print_buffer, -1},
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+struct menu_entries search_menu[] = {
+       {"", NULL, NULL, NULL, NULL, 0}, 
+       {"", NULL, NULL, NULL, search_prompt, -1},
+       {"", NULL, NULL, search, NULL, TRUE},
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+struct menu_entries spell_menu[] = {
+       {"", NULL, NULL, NULL, NULL, -1}, 
+       {"", NULL, NULL, NULL, spell_op, -1},
+       {"", NULL, NULL, NULL, ispell_op, -1},
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+struct menu_entries misc_menu[] = {
+       {"", NULL, NULL, NULL, NULL, -1}, 
+       {"", NULL, NULL, NULL, Format, -1},
+       {"", NULL, NULL, NULL, shell_op, -1}, 
+       {"", menu_op, spell_menu, NULL, NULL, -1}, 
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+struct menu_entries main_menu[] = {
+       {"", NULL, NULL, NULL, NULL, -1}, 
+       {"", NULL, NULL, NULL, leave_op, -1}, 
+       {"", NULL, NULL, NULL, help, -1},
+       {"", menu_op, file_menu, NULL, NULL, -1}, 
+       {"", NULL, NULL, NULL, redraw, -1}, 
+       {"", NULL, NULL, NULL, modes_op, -1}, 
+       {"", menu_op, search_menu, NULL, NULL, -1}, 
+       {"", menu_op, misc_menu, NULL, NULL, -1}, 
+       {NULL, NULL, NULL, NULL, NULL, -1}
+       };
+
+char *help_text[23];
+char *control_keys[5];
+
+char *emacs_help_text[22];
+char *emacs_control_keys[5];
+
+char *command_strings[5];
+char *commands[32];
+char *init_strings[22];
+
+#define MENU_WARN 1
+
+#define max_alpha_char 36
+
+/*
+ |     Declarations for strings for localization
+ */
+
+char *com_win_message;         /* to be shown in com_win if no info window */
+char *no_file_string;
+char *ascii_code_str;
+char *printer_msg_str;
+char *command_str;
+char *file_write_prompt_str;
+char *file_read_prompt_str;
+char *char_str;
+char *unkn_cmd_str;
+char *non_unique_cmd_msg;
+char *line_num_str;
+char *line_len_str;
+char *current_file_str;
+char *usage0;
+char *usage1;
+char *usage2;
+char *usage3;
+char *usage4;
+char *file_is_dir_msg;
+char *new_file_msg;
+char *cant_open_msg;
+char *open_file_msg;
+char *file_read_fin_msg;
+char *reading_file_msg;
+char *read_only_msg;
+char *file_read_lines_msg;
+char *save_file_name_prompt;
+char *file_not_saved_msg;
+char *changes_made_prompt;
+char *yes_char;
+char *file_exists_prompt;
+char *create_file_fail_msg;
+char *writing_file_msg;
+char *file_written_msg;
+char *searching_msg;
+char *str_not_found_msg;
+char *search_prompt_str;
+char *exec_err_msg;
+char *continue_msg;
+char *menu_cancel_msg;
+char *menu_size_err_msg;
+char *press_any_key_msg;
+char *shell_prompt;
+char *formatting_msg;
+char *shell_echo_msg;
+char *spell_in_prog_msg;
+char *margin_prompt;
+char *restricted_msg;
+char *ON;
+char *OFF;
+char *HELP;
+char *WRITE;
+char *READ;
+char *LINE;
+char *FILE_str;
+char *CHARACTER;
+char *REDRAW;
+char *RESEQUENCE;
+char *AUTHOR;
+char *VERSION;
+char *CASE;
+char *NOCASE;
+char *EXPAND;
+char *NOEXPAND;
+char *Exit_string;
+char *QUIT_string;
+char *INFO;
+char *NOINFO;
+char *MARGINS;
+char *NOMARGINS;
+char *AUTOFORMAT;
+char *NOAUTOFORMAT;
+char *Echo;
+char *PRINTCOMMAND;
+char *RIGHTMARGIN;
+char *HIGHLIGHT;
+char *NOHIGHLIGHT;
+char *EIGHTBIT;
+char *NOEIGHTBIT;
+char *EMACS_string;
+char *NOEMACS_string;
+char *conf_dump_err_msg;
+char *conf_dump_success_msg;
+char *conf_not_saved_msg;
+char *ree_no_file_msg;
+char *cancel_string;
+char *menu_too_lrg_msg;
+char *more_above_str, *more_below_str;
+char *separator = "===============================================================================";
+
+char *chinese_cmd, *nochinese_cmd;
+
+#ifndef __STDC__
+#ifndef HAS_STDLIB
+extern char *malloc();
+extern char *realloc();
+extern char *getenv();
+FILE *fopen();                 /* declaration for open function        */
+#endif /* HAS_STDLIB */
+#endif /* __STDC__ */
+
+int
+main(argc, argv)               /* beginning of main program            */
+int argc;
+char *argv[];
+{
+       int counter;
+
+       for (counter = 1; counter < SIGUNUSED; counter++)
+               signal(counter, SIG_IGN);
+
+       signal(SIGCHLD, SIG_DFL);
+       signal(SIGSEGV, SIG_DFL);
+       signal(SIGINT, edit_abort);
+       d_char = malloc(3);     /* provide a buffer for multi-byte chars */
+       d_word = malloc(150);
+       *d_word = '\0';
+       d_line = NULL;
+       dlt_line = txtalloc();
+       dlt_line->line = d_line;
+       dlt_line->line_length = 0;
+       curr_line = first_line = txtalloc();
+       curr_line->line = point = malloc(10);
+       curr_line->line_length = 1;
+       curr_line->max_length = 10;
+       curr_line->prev_line = NULL;
+       curr_line->next_line = NULL;
+       curr_line->line_number  = 1;
+       srch_str = NULL;
+       u_srch_str = NULL;
+       position = 1;
+       scr_pos =0;
+       scr_vert = 0;
+       scr_horz = 0;
+       absolute_lin = 1;
+       bit_bucket = fopen("/dev/null", "w");
+       edit = TRUE;
+       gold = case_sen = FALSE;
+       shell_fork = TRUE;
+       strings_init();
+       ee_init();
+       if (argc > 0 )
+               get_options(argc, argv);
+       set_up_term();
+       if (right_margin == 0)
+               right_margin = COLS - 1;
+       if (top_of_stack == NULL)
+       {
+               if (restrict_mode())
+               {
+                       wmove(com_win, 0, 0);
+                       werase(com_win);
+                       wprintw(com_win, ree_no_file_msg);
+                       wrefresh(com_win);
+                       edit_abort(0);
+               }
+               wprintw(com_win, no_file_string);
+               wrefresh(com_win);
+       }
+       else
+               check_fp();
+
+       clear_com_win = TRUE;
+
+       counter = 0;
+
+       while(edit) 
+       {
+               /*
+                |  display line and column information
+                */
+               if (info_window)
+               {
+                       if (!nohighlight)
+                               wstandout(info_win);
+                       wmove(info_win, 5, 0);
+                       wprintw(info_win, separator);
+                       wmove(info_win, 5, 5);
+                       wprintw(info_win, "line %d col %d lines from top %d ", 
+                                 curr_line->line_number, scr_horz, absolute_lin);
+                       wstandend(info_win);
+                       wrefresh(info_win);
+               }
+
+               wrefresh(text_win);
+               in = wgetch(text_win);
+               if (in == -1)
+                       exit(0);  /* without this exit ee will go into an 
+                                    infinite loop if the network 
+                                    session detaches */
+
+               resize_check();
+
+               if (clear_com_win)
+               {
+                       clear_com_win = FALSE;
+                       wmove(com_win, 0, 0);
+                       werase(com_win);
+                       if (!info_window)
+                       {
+                               wprintw(com_win, "%s", com_win_message);
+                       }
+                       wrefresh(com_win);
+               }
+
+               if (in > 255)
+                       function_key();
+               else if ((in == '\10') || (in == 127))
+               {
+                       in = 8;         /* make sure key is set to backspace */
+                       delete(TRUE);
+               }
+               else if ((in > 31) || (in == 9))
+                       insert(in);
+               else if ((in >= 0) && (in <= 31))
+               {
+                       if (emacs_keys_mode)
+                               emacs_control();
+                       else
+                               control();
+               }
+       }
+       return(0);
+}
+
+unsigned char *
+resiz_line(factor, rline, rpos)        /* resize the line to length + factor*/
+int factor;            /* resize factor                                */
+struct text *rline;    /* position in line                             */
+int rpos;
+{
+       unsigned char *rpoint;
+       int resiz_var;
+       rline->max_length += factor;
+       rpoint = rline->line = realloc(rline->line, rline->max_length );
+       for (resiz_var = 1 ; (resiz_var < rpos) ; resiz_var++)
+               rpoint++;
+       return(rpoint);
+}
+
+void 
+insert(character)              /* insert character into line           */
+int character;                 /* new character                        */
+{
+       int counter;
+       int value;
+       unsigned char *temp;    /* temporary pointer                    */
+       unsigned char *temp2;   /* temporary pointer                    */
+
+       if ((character == '\011') && (expand_tabs))
+       {
+               counter = len_char('\011', scr_horz);
+               for (; counter > 0; counter--)
+                       insert(' ');
+               if (auto_format)
+                       Auto_Format();
+               return;
+       }
+       text_changes = TRUE;
+       if ((curr_line->max_length - curr_line->line_length) < 5)
+               point = resiz_line(10, curr_line, position);
+       curr_line->line_length++;
+       temp = point;
+       counter = position;
+       while (counter < curr_line->line_length)        /* find end of line */
+       {
+               counter++;
+               temp++;
+       }
+       temp++;                 /* increase length of line by one       */
+       while (point < temp)
+       {
+               temp2=temp - 1;
+               *temp= *temp2;  /* shift characters over by one         */
+               temp--;
+       }
+       *point = character;     /* insert new character                 */
+       wclrtoeol(text_win);
+       if (((character >= 0) && (character < ' ')) || (character >= 127)) /* check for TAB character*/
+       {
+               scr_pos = scr_horz += out_char(text_win, character, scr_horz);
+               point++;
+               position++;
+       }
+       else
+       {
+               waddch(text_win, character);
+               scr_pos = ++scr_horz;
+               point++;
+               position ++;
+       }
+
+       if ((observ_margins) && (right_margin < scr_pos))
+       {
+               counter = position;
+               while (scr_pos > right_margin)
+                       prev_word();
+               if (scr_pos == 0)
+               {
+                       while (position < counter)
+                               right(TRUE);
+               }
+               else
+               {
+                       counter -= position;
+                       insert_line(TRUE);
+                       for (value = 0; value < counter; value++)
+                               right(TRUE);
+               }
+       }
+
+       if ((scr_horz - horiz_offset) > last_col)
+       {
+               horiz_offset += 8;
+               midscreen(scr_vert, point);
+       }
+
+       if ((auto_format) && (character == ' ') && (!formatted))
+               Auto_Format();
+       else if ((character != ' ') && (character != '\t'))
+               formatted = FALSE;
+
+       draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
+}
+
+void 
+delete(disp)                   /* delete character             */
+int disp;
+{
+       unsigned char *tp;
+       unsigned char *temp2;
+       struct text *temp_buff;
+       int temp_vert;
+       int temp_pos;
+       int del_width = 1;
+
+       if (point != curr_line->line)   /* if not at beginning of line  */
+       {
+               text_changes = TRUE;
+               temp2 = tp = point;
+               if ((ee_chinese) && (position >= 2) && (*(point - 2) > 127))
+               {
+                       del_width = 2;
+               }
+               tp -= del_width;
+               point -= del_width;
+               position -= del_width;
+               temp_pos = position;
+               curr_line->line_length -= del_width;
+               if ((*tp < ' ') || (*tp >= 127))        /* check for TAB */
+                       scanline(tp);
+               else
+                       scr_horz -= del_width;
+               scr_pos = scr_horz;
+               if (in == 8)
+               {
+                       if (del_width == 1)
+                               *d_char = *point; /* save deleted character  */
+                       else
+                       {
+                               d_char[0] = *point;
+                               d_char[1] = *(point + 1);
+                       }
+                       d_char[del_width] = '\0';
+               }
+               while (temp_pos <= curr_line->line_length)
+               {
+                       temp_pos++;
+                       *tp = *temp2;
+                       tp++;
+                       temp2++;
+               }
+               if ((scr_horz < horiz_offset) && (horiz_offset > 0))
+               {
+                       horiz_offset -= 8;
+                       midscreen(scr_vert, point);
+               }
+       }
+       else if (curr_line->prev_line != NULL)
+       {
+               text_changes = TRUE;
+               left(disp);                     /* go to previous line  */
+               temp_buff = curr_line->next_line;
+               point = resiz_line(temp_buff->line_length, curr_line, position);
+               if (temp_buff->next_line != NULL)
+                       temp_buff->next_line->prev_line = curr_line;
+               curr_line->next_line = temp_buff->next_line;
+               temp2 = temp_buff->line;
+               if (in == 8)
+               {
+                       d_char[0] = '\n';
+                       d_char[1] = '\0';
+               }
+               tp = point;
+               temp_pos = 1;
+               while (temp_pos < temp_buff->line_length)
+               {
+                       curr_line->line_length++;
+                       temp_pos++;
+                       *tp = *temp2;
+                       tp++;
+                       temp2++;
+               }
+               *tp = '\0';
+               free(temp_buff->line);
+               free(temp_buff);
+               temp_buff = curr_line;
+               temp_vert = scr_vert;
+               scr_pos = scr_horz;
+               if (scr_vert < last_line)
+               {
+                       wmove(text_win, scr_vert + 1, 0);
+                       wdeleteln(text_win);
+               }
+               while ((temp_buff != NULL) && (temp_vert < last_line))
+               {
+                       temp_buff = temp_buff->next_line;
+                       temp_vert++;
+               }
+               if ((temp_vert == last_line) && (temp_buff != NULL))
+               {
+                       tp = temp_buff->line;
+                       wmove(text_win, last_line,0);
+                       wclrtobot(text_win);
+                       draw_line(last_line, 0, tp, 1, temp_buff->line_length);
+                       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               }
+       }
+       draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
+       formatted = FALSE;
+}
+
+void 
+scanline(pos)  /* find the proper horizontal position for the pointer  */
+unsigned char *pos;
+{
+       int temp;
+       unsigned char *ptr;
+
+       ptr = curr_line->line;
+       temp = 0;
+       while (ptr < pos)
+       {
+               if (*ptr <= 8)
+                       temp += 2;
+               else if (*ptr == 9)
+                       temp += tabshift(temp);
+               else if ((*ptr >= 10) && (*ptr <= 31))
+                       temp += 2;
+               else if ((*ptr >= 32) && (*ptr < 127))
+                       temp++;
+               else if (*ptr == 127)
+                       temp += 2;
+               else if (!eightbit)
+                       temp += 5;
+               else
+                       temp++;
+               ptr++;
+       }
+       scr_horz = temp;
+       if ((scr_horz - horiz_offset) > last_col)
+       {
+               horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
+               midscreen(scr_vert, point);
+       }
+       else if (scr_horz < horiz_offset)
+       {
+               horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
+               midscreen(scr_vert, point);
+       }
+}
+
+int 
+tabshift(temp_int)             /* give the number of spaces to shift   */
+int temp_int;
+{
+       int leftover;
+
+       leftover = ((temp_int + 1) % 8);
+       if (leftover == 0)
+               return (1);
+       else
+               return (9 - leftover);
+}
+
+int 
+out_char(window, character, column)    /* output non-printing character */
+WINDOW *window;
+char character;
+int column;
+{
+       int i1, i2;
+       char *string;
+       char string2[8];
+
+       if (character == TAB)
+       {
+               i1 = tabshift(column);
+               for (i2 = 0; 
+                 (i2 < i1) && (((column+i2+1)-horiz_offset) < last_col); i2++)
+               {
+                       waddch(window, ' ');
+               }
+               return(i1);
+       }
+       else if ((character >= '\0') && (character < ' '))
+       {
+               string = table[(int) character];
+       }
+       else if ((character < 0) || (character >= 127))
+       {
+               if (character == 127)
+                       string = "^?";
+               else if (!eightbit)
+               {
+                       sprintf(string2, "<%d>", (character < 0) ? (character + 256) : character);
+                       string = string2;
+               }
+               else
+               {
+                       waddch(window, (char)character );
+                       return(1);
+               }
+       }
+       else
+       {
+               waddch(window, (char)character);
+               return(1);
+       }
+       for (i2 = 0; (string[i2] != '\0') && (((column+i2+1)-horiz_offset) < last_col); i2++)
+               waddch(window, string[i2]);
+       return(strlen(string));
+}
+
+int 
+len_char(character, column)    /* return the length of the character   */
+char character;
+int column;    /* the column must be known to provide spacing for tabs */
+{
+       int length;
+
+       if (character == '\t')
+               length = tabshift(column);
+       else if ((character >= 0) && (character < 32))
+               length = 2;
+       else if ((character >= 32) && (character <= 126))
+               length = 1;
+       else if (character == 127)
+               length = 2;
+       else if (((character > 126) || (character < 0)) && (!eightbit))
+               length = 5;
+       else
+               length = 1;
+
+       return(length);
+}
+
+void 
+draw_line(vertical, horiz, ptr, t_pos, length) /* redraw line from current position */
+int vertical;  /* current vertical position on screen          */
+int horiz;     /* current horizontal position on screen        */
+unsigned char *ptr;    /* pointer to line                              */
+int t_pos;     /* current position (offset in bytes) from bol  */
+int length;    /* length (in bytes) of line                    */
+{
+       int d;          /* partial length of special or tab char to display  */
+       unsigned char *temp;    /* temporary pointer to position in line             */
+       int abs_column; /* offset in screen units from begin of line         */
+       int column;     /* horizontal position on screen                     */
+       int row;        /* vertical position on screen                       */
+       int posit;      /* temporary position indicator within line          */
+
+       abs_column = horiz;
+       column = horiz - horiz_offset;
+       row = vertical;
+       temp = ptr;
+       d = 0;
+       posit = t_pos;
+       if (column < 0)
+       {
+               wmove(text_win, row, 0);
+               wclrtoeol(text_win);
+       }
+       while (column < 0)
+       {
+               d = len_char(*temp, abs_column);
+               abs_column += d;
+               column += d;
+               posit++;
+               temp++;
+       }
+       wmove(text_win, row, column);
+       wclrtoeol(text_win);
+       while ((posit < length) && (column <= last_col))
+       {
+               if ((*temp < 32) || (*temp >= 127))
+               {
+                       column += len_char(*temp, abs_column);
+                       abs_column += out_char(text_win, *temp, abs_column);
+               }
+               else
+               {
+                       abs_column++;
+                       column++;
+                       waddch(text_win, *temp);
+               }
+               posit++;
+               temp++;
+       }
+       if (column < last_col)
+               wclrtoeol(text_win);
+       wmove(text_win, vertical, (horiz - horiz_offset));
+}
+
+void 
+insert_line(disp)                      /* insert new line              */
+int disp;
+{
+       int temp_pos;
+       int temp_pos2;
+       unsigned char *temp;
+       unsigned char *extra;
+       struct text *temp_nod;
+
+       text_changes = TRUE;
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+       wclrtoeol(text_win);
+       temp_nod= txtalloc();
+       temp_nod->line = extra= malloc(10);
+       temp_nod->line_length = 1;
+       temp_nod->max_length = 10;
+       temp_nod->line_number = curr_line->line_number + 1;
+       temp_nod->next_line = curr_line->next_line;
+       if (temp_nod->next_line != NULL)
+               temp_nod->next_line->prev_line = temp_nod;
+       temp_nod->prev_line = curr_line;
+       curr_line->next_line = temp_nod;
+       temp_pos2 = position;
+       temp = point;
+       if (temp_pos2 < curr_line->line_length)
+       {
+               temp_pos = 1;
+               while (temp_pos2 < curr_line->line_length)
+               {
+                       if ((temp_nod->max_length - temp_nod->line_length)< 5)
+                               extra = resiz_line(10, temp_nod, temp_pos);
+                       temp_nod->line_length++;
+                       temp_pos++;
+                       temp_pos2++;
+                       *extra= *temp;
+                       extra++;
+                       temp++;
+               }
+               temp=point;
+               *temp = '\0';
+               temp = resiz_line((1 - temp_nod->line_length), curr_line, position);
+               curr_line->line_length = 1 + temp - curr_line->line;
+       }
+       curr_line->line_length = position;
+       absolute_lin++;
+       curr_line = temp_nod;
+       *extra = '\0';
+       position = 1;
+       point= curr_line->line;
+       if (disp)
+       {
+               if (scr_vert < last_line)
+               {
+                       scr_vert++;
+                       wclrtoeol(text_win);
+                       wmove(text_win, scr_vert, 0);
+                       winsertln(text_win);
+               }
+               else
+               {
+                       wmove(text_win, 0,0);
+                       wdeleteln(text_win);
+                       wmove(text_win, last_line,0);
+                       wclrtobot(text_win);
+               }
+               scr_pos = scr_horz = 0;
+               if (horiz_offset)
+               {
+                       horiz_offset = 0;
+                       midscreen(scr_vert, point);
+               }
+               draw_line(scr_vert, scr_horz, point, position,
+                       curr_line->line_length);
+       }
+}
+
+struct text *txtalloc()                /* allocate space for line structure    */
+{
+       return((struct text *) malloc(sizeof( struct text)));
+}
+
+struct files *name_alloc()     /* allocate space for file name list node */
+{
+       return((struct files *) malloc(sizeof( struct files)));
+}
+
+unsigned char *next_word(string)               /* move to next word in string          */
+unsigned char *string;
+{
+       while ((*string != '\0') && ((*string != 32) && (*string != 9)))
+               string++;
+       while ((*string != '\0') && ((*string == 32) || (*string == 9)))
+               string++;
+       return(string);
+}
+
+void 
+prev_word()    /* move to start of previous word in text       */
+{
+       if (position != 1)
+       {
+               if ((position != 1) && ((point[-1] == ' ') || (point[-1] == '\t')))
+               {       /* if at the start of a word    */
+                       while ((position != 1) && ((*point != ' ') && (*point != '\t')))
+                               left(TRUE);
+               }
+               while ((position != 1) && ((*point == ' ') || (*point == '\t')))
+                       left(TRUE);
+               while ((position != 1) && ((*point != ' ') && (*point != '\t')))
+                       left(TRUE);
+               if ((position != 1) && ((*point == ' ') || (*point == '\t')))
+                       right(TRUE);
+       }
+       else
+               left(TRUE);
+}
+
+void 
+control()                      /* use control for commands             */
+{
+       char *string;
+
+       if (in == 1)            /* control a    */
+       {
+               string = get_string(ascii_code_str, TRUE);
+               if (*string != '\0')
+               {
+                       in = atoi(string);
+                       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+                       insert(in);
+               }
+               free(string);
+       }
+       else if (in == 2)       /* control b    */
+               bottom();
+       else if (in == 3)       /* control c    */
+       {
+               command_prompt();
+       }
+       else if (in == 4)       /* control d    */
+               down();
+       else if (in == 5)       /* control e    */
+               search_prompt();
+       else if (in == 6)       /* control f    */
+               undel_char();
+       else if (in == 7)       /* control g    */
+               bol();
+       else if (in == 8)       /* control h    */
+               delete(TRUE);
+       else if (in == 9)       /* control i    */
+               ;
+       else if (in == 10)      /* control j    */
+               insert_line(TRUE);
+       else if (in == 11)      /* control k    */
+               del_char();
+       else if (in == 12)      /* control l    */
+               left(TRUE);
+       else if (in == 13)      /* control m    */
+               insert_line(TRUE);
+       else if (in == 14)      /* control n    */
+               move_rel('d', max(5, (last_line - 5)));
+       else if (in == 15)      /* control o    */
+               eol();
+       else if (in == 16)      /* control p    */
+               move_rel('u', max(5, (last_line - 5)));
+       else if (in == 17)      /* control q    */
+               ;
+       else if (in == 18)      /* control r    */
+               right(TRUE);
+       else if (in == 19)      /* control s    */
+               ;
+       else if (in == 20)      /* control t    */
+               top();
+       else if (in == 21)      /* control u    */
+               up();
+       else if (in == 22)      /* control v    */
+               undel_word();
+       else if (in == 23)      /* control w    */
+               del_word();
+       else if (in == 24)      /* control x    */
+               search(TRUE);
+       else if (in == 25)      /* control y    */
+               del_line();
+       else if (in == 26)      /* control z    */
+               undel_line();
+       else if (in == 27)      /* control [ (escape)   */
+       {
+               menu_op(main_menu);
+       }       
+}
+
+/*
+ |     Emacs control-key bindings
+ */
+
+void 
+emacs_control()
+{
+       char *string;
+
+       if (in == 1)            /* control a    */
+               bol();
+       else if (in == 2)       /* control b    */
+               left(TRUE);
+       else if (in == 3)       /* control c    */
+       {
+               command_prompt();
+       }
+       else if (in == 4)       /* control d    */
+               del_char();
+       else if (in == 5)       /* control e    */
+               eol();
+       else if (in == 6)       /* control f    */
+               right(TRUE);
+       else if (in == 7)       /* control g    */
+               move_rel('u', max(5, (last_line - 5)));
+       else if (in == 8)       /* control h    */
+               delete(TRUE);
+       else if (in == 9)       /* control i    */
+               ;
+       else if (in == 10)      /* control j    */
+               undel_char();
+       else if (in == 11)      /* control k    */
+               del_line();
+       else if (in == 12)      /* control l    */
+               undel_line();
+       else if (in == 13)      /* control m    */
+               insert_line(TRUE);
+       else if (in == 14)      /* control n    */
+               down();
+       else if (in == 15)      /* control o    */
+       {
+               string = get_string(ascii_code_str, TRUE);
+               if (*string != '\0')
+               {
+                       in = atoi(string);
+                       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+                       insert(in);
+               }
+               free(string);
+       }
+       else if (in == 16)      /* control p    */
+               up();
+       else if (in == 17)      /* control q    */
+               ;
+       else if (in == 18)      /* control r    */
+               undel_word();
+       else if (in == 19)      /* control s    */
+               ;
+       else if (in == 20)      /* control t    */
+               top();
+       else if (in == 21)      /* control u    */
+               bottom();
+       else if (in == 22)      /* control v    */
+               move_rel('d', max(5, (last_line - 5)));
+       else if (in == 23)      /* control w    */
+               del_word();
+       else if (in == 24)      /* control x    */
+               search(TRUE);
+       else if (in == 25)      /* control y    */
+               search_prompt();
+       else if (in == 26)      /* control z    */
+               adv_word();
+       else if (in == 27)      /* control [ (escape)   */
+       {
+               menu_op(main_menu);
+       }       
+}
+
+void 
+bottom()                       /* go to bottom of file                 */
+{
+       while (curr_line->next_line != NULL)
+       {
+               curr_line = curr_line->next_line;
+               absolute_lin++;
+       }
+       point = curr_line->line;
+       if (horiz_offset)
+               horiz_offset = 0;
+       position = 1;
+       midscreen(last_line, point);
+       scr_pos = scr_horz;
+}
+
+void 
+top()                          /* go to top of file                    */
+{
+       while (curr_line->prev_line != NULL)
+       {
+               curr_line = curr_line->prev_line;
+               absolute_lin--;
+       }
+       point = curr_line->line;
+       if (horiz_offset)
+               horiz_offset = 0;
+       position = 1;
+       midscreen(0, point);
+       scr_pos = scr_horz;
+}
+
+void 
+nextline()                     /* move pointers to start of next line  */
+{
+       curr_line = curr_line->next_line;
+       absolute_lin++;
+       point = curr_line->line;
+       position = 1;
+       if (scr_vert == last_line)
+       {
+               wmove(text_win, 0,0);
+               wdeleteln(text_win);
+               wmove(text_win, last_line,0);
+               wclrtobot(text_win);
+               draw_line(last_line,0,point,1,curr_line->line_length);
+       }
+       else
+               scr_vert++;
+}
+
+void 
+prevline()                     /* move pointers to start of previous line*/
+{
+       curr_line = curr_line->prev_line;
+       absolute_lin--;
+       point = curr_line->line;
+       position = 1;
+       if (scr_vert == 0)
+       {
+               winsertln(text_win);
+               draw_line(0,0,point,1,curr_line->line_length);
+       }
+       else
+               scr_vert--;
+       while (position < curr_line->line_length)
+       {
+               position++;
+               point++;
+       }
+}
+
+void 
+left(disp)                             /* move left one character      */
+int disp;
+{
+       if (point != curr_line->line)   /* if not at begin of line      */
+       {
+               if ((ee_chinese) && (position >= 2) && (*(point - 2) > 127))
+               {
+                       point--;
+                       position--;
+               }
+               point--;
+               position--;
+               scanline(point);
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               scr_pos = scr_horz;
+       }
+       else if (curr_line->prev_line != NULL)
+       {
+               if (!disp)
+               {
+                       absolute_lin--;
+                       curr_line = curr_line->prev_line;
+                       point = curr_line->line + curr_line->line_length;
+                       position = curr_line->line_length;
+                       return;
+               }
+               position = 1;
+               prevline();
+               scanline(point);
+               scr_pos = scr_horz;
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+       }
+}
+
+void 
+right(disp)                            /* move right one character     */
+int disp;
+{
+       if (position < curr_line->line_length)
+       {
+               if ((ee_chinese) && (*point > 127) && 
+                   ((curr_line->line_length - position) >= 2))
+               {
+                       point++;
+                       position++;
+               }
+               point++;
+               position++;
+               scanline(point);
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               scr_pos = scr_horz;
+       }
+       else if (curr_line->next_line != NULL)
+       {
+               if (!disp)
+               {
+                       absolute_lin++;
+                       curr_line = curr_line->next_line;
+                       point = curr_line->line;
+                       position = 1;
+                       return;
+               }
+               nextline();
+               scr_pos = scr_horz = 0;
+               if (horiz_offset)
+               {
+                       horiz_offset = 0;
+                       midscreen(scr_vert, point);
+               }
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               position = 1;   
+       }
+}
+
+void 
+find_pos()             /* move to the same column as on other line     */
+{
+       scr_horz = 0;
+       position = 1;
+       while ((scr_horz < scr_pos) && (position < curr_line->line_length))
+       {
+               if (*point == 9)
+                       scr_horz += tabshift(scr_horz);
+               else if (*point < ' ')
+                       scr_horz += 2;
+               else if ((ee_chinese) && (*point > 127) && 
+                   ((curr_line->line_length - position) >= 2))
+               {
+                       scr_horz += 2;
+                       point++;
+                       position++;
+               }
+               else
+                       scr_horz++;
+               position++;
+               point++;
+       }
+       if ((scr_horz - horiz_offset) > last_col)
+       {
+               horiz_offset = (scr_horz - (scr_horz % 8)) - (COLS - 8);
+               midscreen(scr_vert, point);
+       }
+       else if (scr_horz < horiz_offset)
+       {
+               horiz_offset = max(0, (scr_horz - (scr_horz % 8)));
+               midscreen(scr_vert, point);
+       }
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+up()                                   /* move up one line             */
+{
+       if (curr_line->prev_line != NULL)
+       {
+               prevline();
+               point = curr_line->line;
+               find_pos();
+       }
+}
+
+void 
+down()                                 /* move down one line           */
+{
+       if (curr_line->next_line != NULL)
+       {
+               nextline();
+               find_pos();
+       }
+}
+
+void 
+function_key()                         /* process function key         */
+{
+       if (in == KEY_LEFT)
+               left(TRUE);
+       else if (in == KEY_RIGHT)
+               right(TRUE);
+       else if (in == KEY_HOME)
+               bol();
+       else if (in == KEY_END)
+               eol();
+       else if (in == KEY_UP)
+               up();
+       else if (in == KEY_DOWN)
+               down();
+       else if (in == KEY_NPAGE)
+               move_rel('d', max( 5, (last_line - 5)));
+       else if (in == KEY_PPAGE)
+               move_rel('u', max(5, (last_line - 5)));
+       else if (in == KEY_DL)
+               del_line();
+       else if (in == KEY_DC)
+               del_char();
+       else if (in == KEY_BACKSPACE)
+               delete(TRUE);
+       else if (in == KEY_IL)
+       {               /* insert a line before current line    */
+               insert_line(TRUE);
+               left(TRUE);
+       }
+       else if (in == KEY_F(1))
+               gold = !gold;
+       else if (in == KEY_F(2))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       undel_line();
+               }
+               else
+                       undel_char();
+       }
+       else if (in == KEY_F(3))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       undel_word();
+               }
+               else
+                       del_word();
+       }
+       else if (in == KEY_F(4))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       paint_info_win();
+                       midscreen(scr_vert, point);
+               }
+               else
+                       adv_word();
+       }
+       else if (in == KEY_F(5))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       search_prompt();
+               }
+               else
+                       search(TRUE);
+       }
+       else if (in == KEY_F(6))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       bottom();
+               }
+               else
+                       top();
+       }
+       else if (in == KEY_F(7))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       eol();
+               }
+               else
+                       bol();
+       }
+       else if (in == KEY_F(8))
+       {
+               if (gold)
+               {
+                       gold = FALSE;
+                       command_prompt();
+               } 
+               else
+                       adv_line();
+       }
+}
+
+void 
+print_buffer()
+{
+       char buffer[256];
+
+       sprintf(buffer, ">!%s", print_command);
+       wmove(com_win, 0, 0);
+       wclrtoeol(com_win);
+       wprintw(com_win, printer_msg_str, print_command);
+       wrefresh(com_win);
+       command(buffer);
+}
+
+void 
+command_prompt()
+{
+       char *cmd_str;
+       int result;
+
+       info_type = COMMANDS;
+       paint_info_win();
+       cmd_str = get_string(command_str, TRUE);
+       if ((result = unique_test(cmd_str, commands)) != 1)
+       {
+               werase(com_win);
+               wmove(com_win, 0, 0);
+               if (result == 0)
+                       wprintw(com_win, unkn_cmd_str, cmd_str);
+               else
+                       wprintw(com_win, non_unique_cmd_msg);
+
+               wrefresh(com_win);
+
+               info_type = CONTROL_KEYS;
+               paint_info_win();
+
+               if (cmd_str != NULL)
+                       free(cmd_str);
+               return;
+       }
+       command(cmd_str);
+       wrefresh(com_win);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+       info_type = CONTROL_KEYS;
+       paint_info_win();
+       if (cmd_str != NULL)
+               free(cmd_str);
+}
+
+void 
+command(cmd_str1)              /* process commands from keyboard       */
+char *cmd_str1;
+{
+       char *cmd_str2 = NULL;
+       char *cmd_str = cmd_str1;
+
+       clear_com_win = TRUE;
+       if (compare(cmd_str, HELP, FALSE))
+               help();
+       else if (compare(cmd_str, WRITE, FALSE))
+       {
+               if (restrict_mode())
+               {
+                       return;
+               }
+               cmd_str = next_word(cmd_str);
+               if (*cmd_str == '\0')
+               {
+                       cmd_str = cmd_str2 = get_string(file_write_prompt_str, TRUE);
+               }
+               tmp_file = resolve_name(cmd_str);
+               write_file(tmp_file, 1);
+               if (tmp_file != cmd_str)
+                       free(tmp_file);
+       }
+       else if (compare(cmd_str, READ, FALSE))
+       {
+               if (restrict_mode())
+               {
+                       return;
+               }
+               cmd_str = next_word(cmd_str);
+               if (*cmd_str == '\0')
+               {
+                       cmd_str = cmd_str2 = get_string(file_read_prompt_str, TRUE);
+               }
+               tmp_file = cmd_str;
+               recv_file = TRUE;
+               tmp_file = resolve_name(cmd_str);
+               check_fp();
+               if (tmp_file != cmd_str)
+                       free(tmp_file);
+       }
+       else if (compare(cmd_str, LINE, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, line_num_str, curr_line->line_number);
+               wprintw(com_win, line_len_str, curr_line->line_length);
+       }
+       else if (compare(cmd_str, FILE_str, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               if (in_file_name == NULL)
+                       wprintw(com_win, no_file_string);
+               else
+                       wprintw(com_win, current_file_str, in_file_name);
+       }
+       else if ((*cmd_str >= '0') && (*cmd_str <= '9'))
+               goto_line(cmd_str);
+       else if (compare(cmd_str, CHARACTER, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, char_str, *point);
+       }
+       else if (compare(cmd_str, REDRAW, FALSE))
+               redraw();
+       else if (compare(cmd_str, RESEQUENCE, FALSE))
+       {
+               tmp_line = first_line->next_line;
+               while (tmp_line != NULL)
+               {
+               tmp_line->line_number = tmp_line->prev_line->line_number + 1;
+                       tmp_line = tmp_line->next_line;
+               }
+       }
+       else if (compare(cmd_str, AUTHOR, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, "written by Hugh Mahon");
+       }
+       else if (compare(cmd_str, VERSION, FALSE))
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, "%s", version);
+       }
+       else if (compare(cmd_str, CASE, FALSE))
+               case_sen = TRUE;
+       else if (compare(cmd_str, NOCASE, FALSE))
+               case_sen = FALSE;
+       else if (compare(cmd_str, EXPAND, FALSE))
+               expand_tabs = TRUE;
+       else if (compare(cmd_str, NOEXPAND, FALSE))
+               expand_tabs = FALSE;
+       else if (compare(cmd_str, Exit_string, FALSE))
+               finish();
+       else if (compare(cmd_str, chinese_cmd, FALSE))
+       {
+               ee_chinese = TRUE;
+#ifdef NCURSE
+               nc_setattrib(A_NC_BIG5);
+#endif /* NCURSE */
+       }
+       else if (compare(cmd_str, nochinese_cmd, FALSE))
+       {
+               ee_chinese = FALSE;
+#ifdef NCURSE
+               nc_clearattrib(A_NC_BIG5);
+#endif /* NCURSE */
+       }
+       else if (compare(cmd_str, QUIT_string, FALSE))
+               quit(0);
+       else if (*cmd_str == '!')
+       {
+               cmd_str++;
+               if ((*cmd_str == ' ') || (*cmd_str == 9))
+                       cmd_str = next_word(cmd_str);
+               sh_command(cmd_str);
+       }
+       else if ((*cmd_str == '<') && (!in_pipe))
+       {
+               in_pipe = TRUE;
+               shell_fork = FALSE;
+               cmd_str++;
+               if ((*cmd_str == ' ') || (*cmd_str == '\t'))
+                       cmd_str = next_word(cmd_str);
+               command(cmd_str);
+               in_pipe = FALSE;
+               shell_fork = TRUE;
+       }
+       else if ((*cmd_str == '>') && (!out_pipe))
+       {
+               out_pipe = TRUE;
+               cmd_str++;
+               if ((*cmd_str == ' ') || (*cmd_str == '\t'))
+                       cmd_str = next_word(cmd_str);
+               command(cmd_str);
+               out_pipe = FALSE;
+       }
+       else
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, unkn_cmd_str, cmd_str);
+       }
+       if (cmd_str2 != NULL)
+               free(cmd_str2);
+}
+
+int 
+scan(line, offset, column)     /* determine horizontal position for get_string */
+char *line;
+int offset;
+int column;
+{
+       char *stemp;
+       int i;
+       int j;
+
+       stemp = line;
+       i = 0;
+       j = column;
+       while (i < offset)
+       {
+               i++;
+               j += len_char(*stemp, j);
+               stemp++;
+       }
+       return(j);
+}
+
+char *
+get_string(prompt, advance)    /* read string from input on command line */
+char *prompt;          /* string containing user prompt message        */
+int advance;           /* if true, skip leading spaces and tabs        */
+{
+       char *string;
+       char *tmp_string;
+       char *nam_str;
+       char *g_point;
+       int tmp_int;
+       int g_horz, g_position, g_pos;
+       int esc_flag;
+
+       g_point = tmp_string = malloc(512);
+       wmove(com_win,0,0);
+       wclrtoeol(com_win);
+       waddstr(com_win, prompt);
+       wrefresh(com_win);
+       nam_str = tmp_string;
+       clear_com_win = TRUE;
+       g_horz = g_position = scan(prompt, strlen(prompt), 0);
+       g_pos = 0;
+       do
+       {
+               esc_flag = FALSE;
+               in = wgetch(com_win);
+               if (in == -1)
+                       exit(0);
+               if (((in == 8) || (in == 127) || (in == KEY_BACKSPACE)) && (g_pos > 0))
+               {
+                       tmp_int = g_horz;
+                       g_pos--;
+                       g_horz = scan(g_point, g_pos, g_position);
+                       tmp_int = tmp_int - g_horz;
+                       for (; 0 < tmp_int; tmp_int--)
+                       {
+                               if ((g_horz+tmp_int) < (last_col - 1))
+                               {
+                                       waddch(com_win, '\010');
+                                       waddch(com_win, ' ');
+                                       waddch(com_win, '\010');
+                               }
+                       }
+                       nam_str--;
+               }
+               else if ((in != 8) && (in != 127) && (in != '\n') && (in != '\r') && (in < 256))
+               {
+                       if (in == '\026')       /* control-v, accept next character verbatim    */
+                       {                       /* allows entry of ^m, ^j, and ^h       */
+                               esc_flag = TRUE;
+                               in = wgetch(com_win);
+                               if (in == -1)
+                                       exit(0);
+                       }
+                       *nam_str = in;
+                       g_pos++;
+                       if (((in < ' ') || (in > 126)) && (g_horz < (last_col - 1)))
+                               g_horz += out_char(com_win, in, g_horz);
+                       else
+                       {
+                               g_horz++;
+                               if (g_horz < (last_col - 1))
+                                       waddch(com_win, in);
+                       }
+                       nam_str++;
+               }
+               wrefresh(com_win);
+               if (esc_flag)
+                       in = '\0';
+       } while ((in != '\n') && (in != '\r'));
+       *nam_str = '\0';
+       nam_str = tmp_string;
+       if (((*nam_str == ' ') || (*nam_str == 9)) && (advance))
+               nam_str = next_word(nam_str);
+       string = malloc(strlen(nam_str) + 1);
+       strcpy(string, nam_str);
+       free(tmp_string);
+       wrefresh(com_win);
+       return(string);
+}
+
+int 
+compare(string1, string2, sensitive)   /* compare two strings  */
+char *string1;
+char *string2;
+int sensitive;
+{
+       char *strng1;
+       char *strng2;
+       int tmp;
+       int equal;
+
+       strng1 = string1;
+       strng2 = string2;
+       tmp = 0;
+       if ((strng1 == NULL) || (strng2 == NULL) || (*strng1 == '\0') || (*strng2 == '\0'))
+               return(FALSE);
+       equal = TRUE;
+       while (equal)
+       {
+               if (sensitive)
+               {
+                       if (*strng1 != *strng2)
+                               equal = FALSE;
+               }
+               else
+               {
+                       if (toupper(*strng1) != toupper(*strng2))
+                               equal = FALSE;
+               }
+               strng1++;
+               strng2++;
+               if ((*strng1 == '\0') || (*strng2 == '\0') || (*strng1 == ' ') || (*strng2 == ' '))
+                       break;
+               tmp++;
+       }
+       return(equal);
+}
+
+void 
+goto_line(cmd_str)
+char *cmd_str;
+{
+       int number;
+       int i;
+       char *ptr;
+       char direction = '\0';
+       struct text *t_line;
+
+       ptr = cmd_str;
+       i= 0;
+       while ((*ptr >='0') && (*ptr <= '9'))
+       {
+               i= i * 10 + (*ptr - '0');
+               ptr++;
+       }
+       number = i;
+       i = 0;
+       t_line = curr_line;
+       while ((t_line->line_number > number) && (t_line->prev_line != NULL))
+       {
+               i++;
+               t_line = t_line->prev_line;
+               direction = 'u';
+       }
+       while ((t_line->line_number < number) && (t_line->next_line != NULL))
+       {
+               i++;
+               direction = 'd';
+               t_line = t_line->next_line;
+       }
+       if ((i < 30) && (i > 0))
+       {
+               move_rel(direction, i);
+       }
+       else
+       {
+               if (direction != 'd')
+               {
+                       absolute_lin += i;
+               }
+               else
+               {
+                       absolute_lin -= i;
+               }
+               curr_line = t_line;
+               point = curr_line->line;
+               position = 1;
+               midscreen((last_line / 2), point);
+               scr_pos = scr_horz;
+       }
+       wmove(com_win, 0, 0);
+       wclrtoeol(com_win);
+       wprintw(com_win, line_num_str, curr_line->line_number);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+midscreen(line, pnt)   /* put current line in middle of screen */
+int line;
+unsigned char *pnt;
+{
+       struct text *mid_line;
+       int i;
+
+       line = min(line, last_line);
+       mid_line = curr_line;
+       for (i = 0; ((i < line) && (curr_line->prev_line != NULL)); i++)
+               curr_line = curr_line->prev_line;
+       scr_vert = scr_horz = 0;
+       wmove(text_win, 0, 0);
+       draw_screen();
+       scr_vert = i;
+       curr_line = mid_line;
+       scanline(pnt);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+get_options(numargs, arguments)        /* get arguments from command line      */
+int numargs;
+char *arguments[];
+{
+       char *buff;
+       int count;
+       struct files *temp_names = NULL;
+       char *name;
+       char *ptr;
+       int no_more_opts = FALSE;
+
+       /*
+        |      see if editor was invoked as 'ree' (restricted mode)
+        */
+
+       if (!(name = strrchr(arguments[0], '/')))
+               name = arguments[0];
+       else
+               name++;
+       if (!strcmp(name, "ree"))
+               restricted = TRUE;
+
+       top_of_stack = NULL;
+       input_file = FALSE;
+       recv_file = FALSE;
+       count = 1;
+       while ((count < numargs)&& (!no_more_opts))
+       {
+               buff = arguments[count];
+               if (!strcmp("-i", buff))
+               {
+                       info_window = FALSE;
+               }
+               else if (!strcmp("-e", buff))
+               {
+                       expand_tabs = FALSE;
+               }
+               else if (!strcmp("-h", buff))
+               {
+                       nohighlight = TRUE;
+               }
+               else if (!strcmp("-?", buff))
+               {
+                       fprintf(stderr, usage0, arguments[0]);
+                       fprintf(stderr, usage1);
+                       fprintf(stderr, usage2);
+                       fprintf(stderr, usage3);
+                       fprintf(stderr, usage4);
+                       exit(1);
+               }
+               else if ((*buff == '+') && (start_at_line == NULL))
+               {
+                       buff++;
+                       start_at_line = buff;
+               }
+               else if (!(strcmp("--", buff)))
+                       no_more_opts = TRUE;
+               else
+               {
+                       count--;
+                       no_more_opts = TRUE;
+               }
+               count++;
+       }
+       while (count < numargs)
+       {
+               buff = arguments[count];
+               if (top_of_stack == NULL)
+               {
+                       temp_names = top_of_stack = name_alloc();
+               }
+               else
+               {
+                       temp_names->next_name = name_alloc();
+                       temp_names = temp_names->next_name;
+               }
+               ptr = temp_names->name = malloc(strlen(buff) + 1);
+               while (*buff != '\0')
+               {
+                       *ptr = *buff;
+                       buff++;
+                       ptr++;
+               }
+               *ptr = '\0';
+               temp_names->next_name = NULL;
+               input_file = TRUE;
+               recv_file = TRUE;
+               count++;
+       }
+}
+
+void 
+check_fp()             /* open or close files according to flags */
+{
+       int line_num;
+       int temp;
+       struct stat buf;
+
+       clear_com_win = TRUE;
+       tmp_vert = scr_vert;
+       tmp_horz = scr_horz;
+       tmp_line = curr_line;
+       if (input_file)
+       {
+               in_file_name = tmp_file = top_of_stack->name;
+               top_of_stack = top_of_stack->next_name;
+       }
+       temp = stat(tmp_file, &buf);
+       buf.st_mode &= ~07777;
+       if ((temp != -1) && (buf.st_mode != 0100000) && (buf.st_mode != 0))
+       {
+               wprintw(com_win, file_is_dir_msg, tmp_file);
+               wrefresh(com_win);
+               if (input_file)
+               {
+                       quit(0);
+                       return;
+               }
+               else
+                       return;
+       }
+       if ((get_fd = open(tmp_file, O_RDONLY)) == -1)
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               if (input_file)
+                       wprintw(com_win, new_file_msg, tmp_file);
+               else
+                       wprintw(com_win, cant_open_msg, tmp_file);
+               wrefresh(com_win);
+               wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+               wrefresh(text_win);
+               recv_file = FALSE;
+               input_file = FALSE;
+               return;
+       }
+       else
+               get_file(tmp_file);
+
+       recv_file = FALSE;
+       line_num = curr_line->line_number;
+       scr_vert = tmp_vert;
+       scr_horz = tmp_horz;
+       if (input_file)
+               curr_line= first_line;
+       else
+               curr_line = tmp_line;
+       point = curr_line->line;
+       draw_screen();
+       if (input_file)
+       {
+               input_file = FALSE;
+               if (start_at_line != NULL)
+               {
+                       line_num = atoi(start_at_line) - 1;
+                       move_rel('d', line_num);
+                       line_num = 0;
+                       start_at_line = NULL;
+               }
+       }
+       else
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               text_changes = TRUE;
+               if ((tmp_file != NULL) && (*tmp_file != '\0'))
+                       wprintw(com_win, file_read_fin_msg, tmp_file);
+       }
+       wrefresh(com_win);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+       wrefresh(text_win);
+}
+
+void 
+get_file(file_name)    /* read specified file into current buffer      */
+char *file_name;
+{
+       int can_read;           /* file has at least one character      */
+       int length;             /* length of line read by read          */
+       int append;             /* should text be appended to current line */
+       struct text *temp_line;
+       char ro_flag = FALSE;
+
+       if (recv_file)          /* if reading a file                    */
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, reading_file_msg, file_name);
+               if (access(file_name, 2))       /* check permission to write */
+               {
+                       if ((errno == ENOTDIR) || (errno == EACCES) || (errno == EROFS) || (errno == ETXTBSY) || (errno == EFAULT))
+                       {
+                               wprintw(com_win, read_only_msg);
+                               ro_flag = TRUE;
+                       }
+               }
+               wrefresh(com_win);
+       }
+       if (curr_line->line_length > 1) /* if current line is not blank */
+       {
+               insert_line(FALSE);
+               left(FALSE);
+               append = FALSE;
+       }
+       else
+               append = TRUE;
+       can_read = FALSE;               /* test if file has any characters  */
+       while (((length = read(get_fd, in_string, 512)) != 0) && (length != -1))
+       {
+               can_read = TRUE;  /* if set file has at least 1 character   */
+               get_line(length, in_string, &append);
+       }
+       if ((can_read) && (curr_line->line_length == 1))
+       {
+               temp_line = curr_line->prev_line;
+               temp_line->next_line = curr_line->next_line;
+               if (temp_line->next_line != NULL)
+                       temp_line->next_line->prev_line = temp_line;
+               if (curr_line->line != NULL)
+                       free(curr_line->line);
+               free(curr_line);
+               curr_line = temp_line;
+       }
+       if (input_file) /* if this is the file to be edited display number of lines     */
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, file_read_lines_msg, in_file_name, curr_line->line_number);
+               if (ro_flag)
+                       wprintw(com_win, read_only_msg);
+               wrefresh(com_win);
+       }
+       else if (can_read)      /* not input_file and file is non-zero size */
+               text_changes = TRUE;
+
+       if (recv_file)          /* if reading a file                    */
+       {
+               in = EOF;
+       }
+}
+
+void 
+get_line(length, in_string, append)    /* read string and split into lines */
+int length;            /* length of string read by read                */
+unsigned char *in_string;      /* string read by read                          */
+int *append;   /* TRUE if must append more text to end of current line */
+{
+       unsigned char *str1;
+       unsigned char *str2;
+       int num;                /* offset from start of string          */
+       int char_count;         /* length of new line (or added portion */
+       int temp_counter;       /* temporary counter value              */
+       struct text *tline;     /* temporary pointer to new line        */
+       int first_time;         /* if TRUE, the first time through the loop */
+
+       str2 = in_string;
+       num = 0;
+       first_time = TRUE;
+       while (num < length)
+       {
+               if (!first_time)
+               {
+                       if (num < length)
+                       {
+                               str2++;
+                               num++;
+                       }
+               }
+               else
+                       first_time = FALSE;
+               str1 = str2;
+               char_count = 1;
+               /* find end of line     */
+               while ((*str2 != '\n') && (num < length))
+               {
+                       str2++;
+                       num++;
+                       char_count++;
+               }
+               if (!(*append)) /* if not append to current line, insert new one */
+               {
+                       tline = txtalloc();     /* allocate data structure for next line */
+                       tline->line_number = curr_line->line_number + 1;
+                       tline->next_line = curr_line->next_line;
+                       tline->prev_line = curr_line;
+                       curr_line->next_line = tline;
+                       if (tline->next_line != NULL)
+                               tline->next_line->prev_line = tline;
+                       curr_line = tline;
+                       curr_line->line = point = (unsigned char *) malloc(char_count);
+                       curr_line->line_length = char_count;
+                       curr_line->max_length = char_count;
+               }
+               else
+               {
+                       point = resiz_line(char_count, curr_line, curr_line->line_length); 
+                       curr_line->line_length += (char_count - 1);
+               }
+               for (temp_counter = 1; temp_counter < char_count; temp_counter++)
+               {
+                       *point = *str1;
+                       point++;
+                       str1++;
+               }
+               *point = '\0';
+               *append = FALSE;
+               if ((num == length) && (*str2 != '\n'))
+                       *append = TRUE;
+       }
+}
+
+void 
+draw_screen()          /* redraw the screen from current postion       */
+{
+       struct text *temp_line;
+       unsigned char *line_out;
+       int temp_vert;
+
+       temp_line = curr_line;
+       temp_vert = scr_vert;
+       wclrtobot(text_win);
+       while ((temp_line != NULL) && (temp_vert <= last_line))
+       {
+               line_out = temp_line->line;
+               draw_line(temp_vert, 0, line_out, 1, temp_line->line_length);
+               temp_vert++;
+               temp_line = temp_line->next_line;
+       }
+       wmove(text_win, temp_vert, 0);
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+finish()       /* prepare to exit edit session */
+{
+       char *file_name = in_file_name;
+
+       /*
+        |      changes made here should be reflected in the 'save' 
+        |      portion of file_op()
+        */
+
+       if ((file_name == NULL) || (*file_name == '\0'))
+               file_name = get_string(save_file_name_prompt, TRUE);
+
+       if ((file_name == NULL) || (*file_name == '\0'))
+       {
+               wmove(com_win, 0, 0);
+               wprintw(com_win, file_not_saved_msg);
+               wclrtoeol(com_win);
+               wrefresh(com_win);
+               clear_com_win = TRUE;
+               return;
+       }
+
+       tmp_file = resolve_name(file_name);
+       if (tmp_file != file_name)
+       {
+               free(file_name);
+               file_name = tmp_file;
+       }
+
+       if (write_file(file_name, 1))
+       {
+               text_changes = FALSE;
+               quit(0);
+       }
+}
+
+int 
+quit(noverify)         /* exit editor                  */
+int noverify;
+{
+       char *ans;
+
+       touchwin(text_win);
+       wrefresh(text_win);
+       if ((text_changes) && (!noverify))
+       {
+               ans = get_string(changes_made_prompt, TRUE);
+               if (toupper(*ans) == toupper(*yes_char))
+                       text_changes = FALSE;
+               else
+                       return(0);
+               free(ans);
+       }
+       if (top_of_stack == NULL)
+       {
+               if (info_window)
+                       wrefresh(info_win);
+               wrefresh(com_win);
+               resetty();
+               endwin();
+               putchar('\n');
+               exit(0);
+       }
+       else
+       {
+               delete_text();
+               recv_file = TRUE;
+               input_file = TRUE;
+               check_fp();
+       }
+       return(0);
+}
+
+void 
+edit_abort(arg)
+int arg;
+{
+       wrefresh(com_win);
+       resetty();
+       endwin();
+       putchar('\n');
+       exit(1);
+}
+
+void 
+delete_text()
+{
+       while (curr_line->next_line != NULL)
+               curr_line = curr_line->next_line;
+       while (curr_line != first_line)
+       {
+               free(curr_line->line);
+               curr_line = curr_line->prev_line;
+               absolute_lin--;
+               free(curr_line->next_line);
+       }
+       curr_line->next_line = NULL;
+       *curr_line->line = '\0';
+       curr_line->line_length = 1;
+       curr_line->line_number = 1;
+       point = curr_line->line;
+       scr_pos = scr_vert = scr_horz = 0;
+       position = 1;
+}
+
+int 
+write_file(file_name, warn_if_exists)
+char *file_name;
+int warn_if_exists;
+{
+       char cr;
+       char *tmp_point;
+       struct text *out_line;
+       int lines, charac;
+       int temp_pos;
+       int write_flag = TRUE;
+
+       charac = lines = 0;
+       if (warn_if_exists &&
+           ((in_file_name == NULL) || strcmp(in_file_name, file_name)))
+       {
+               if ((temp_fp = fopen(file_name, "r")))
+               {
+                       tmp_point = get_string(file_exists_prompt, TRUE);
+                       if (toupper(*tmp_point) == toupper(*yes_char))
+                               write_flag = TRUE;
+                       else 
+                               write_flag = FALSE;
+                       fclose(temp_fp);
+                       free(tmp_point);
+               }
+       }
+
+       clear_com_win = TRUE;
+
+       if (write_flag)
+       {
+               if ((temp_fp = fopen(file_name, "w")) == NULL)
+               {
+                       clear_com_win = TRUE;
+                       wmove(com_win,0,0);
+                       wclrtoeol(com_win);
+                       wprintw(com_win, create_file_fail_msg, file_name);
+                       wrefresh(com_win);
+                       return(FALSE);
+               }
+               else
+               {
+                       wmove(com_win,0,0);
+                       wclrtoeol(com_win);
+                       wprintw(com_win, writing_file_msg, file_name);
+                       wrefresh(com_win);
+                       cr = '\n';
+                       out_line = first_line;
+                       while (out_line != NULL)
+                       {
+                               temp_pos = 1;
+                               tmp_point= out_line->line;
+                               while (temp_pos < out_line->line_length)
+                               {
+                                       putc(*tmp_point, temp_fp);
+                                       tmp_point++;
+                                       temp_pos++;
+                               }
+                               charac += out_line->line_length;
+                               out_line = out_line->next_line;
+                               putc(cr, temp_fp);
+                               lines++;
+                       }
+                       fclose(temp_fp);
+                       wmove(com_win,0,0);
+                       wclrtoeol(com_win);
+                       wprintw(com_win, file_written_msg, file_name, lines, charac);
+                       wrefresh(com_win);
+                       return(TRUE);
+               }
+       }
+       else
+               return(FALSE);
+}
+
+int 
+search(display_message)                /* search for string in srch_str        */
+int display_message;
+{
+       int lines_moved;
+       int iter;
+       int found;
+
+       if ((srch_str == NULL) || (*srch_str == '\0'))
+               return(FALSE);
+       if (display_message)
+       {
+               wmove(com_win, 0, 0);
+               wclrtoeol(com_win);
+               wprintw(com_win, searching_msg);
+               wrefresh(com_win);
+               clear_com_win = TRUE;
+       }
+       lines_moved = 0;
+       found = FALSE;
+       srch_line = curr_line;
+       srch_1 = point;
+       if (position < curr_line->line_length)
+               srch_1++;
+       iter = position + 1;
+       while ((!found) && (srch_line != NULL))
+       {
+               while ((iter < srch_line->line_length) && (!found))
+               {
+                       srch_2 = srch_1;
+                       if (case_sen)   /* if case sensitive            */
+                       {
+                               srch_3 = srch_str;
+                       while ((*srch_2 == *srch_3) && (*srch_3 != '\0'))
+                               {
+                                       found = TRUE;
+                                       srch_2++;
+                                       srch_3++;
+                               }       /* end while    */
+                       }
+                       else            /* if not case sensitive        */
+                       {
+                               srch_3 = u_srch_str;
+                       while ((toupper(*srch_2) == *srch_3) && (*srch_3 != '\0'))
+                               {
+                                       found = TRUE;
+                                       srch_2++;
+                                       srch_3++;
+                               }
+                       }       /* end else     */
+                       if (!((*srch_3 == '\0') && (found)))
+                       {
+                               found = FALSE;
+                               if (iter < srch_line->line_length)
+                                       srch_1++;
+                               iter++;
+                       }
+               }
+               if (!found)
+               {
+                       srch_line = srch_line->next_line;
+                       if (srch_line != NULL)
+                               srch_1 = srch_line->line;
+                       iter = 1;
+                       lines_moved++;
+               }
+       }
+       if (found)
+       {
+               if (display_message)
+               {
+                       wmove(com_win, 0, 0);
+                       wclrtoeol(com_win);
+                       wrefresh(com_win);
+               }
+               if (lines_moved == 0)
+               {
+                       while (position < iter)
+                               right(TRUE);
+               }
+               else
+               {
+                       if (lines_moved < 30)
+                       {
+                               move_rel('d', lines_moved);
+                               while (position < iter)
+                                       right(TRUE);
+                       }
+                       else 
+                       {
+                               absolute_lin += lines_moved;
+                               curr_line = srch_line;
+                               point = srch_1;
+                               position = iter;
+                               scanline(point);
+                               scr_pos = scr_horz;
+                               midscreen((last_line / 2), point);
+                       }
+               }
+       }
+       else
+       {
+               if (display_message)
+               {
+                       wmove(com_win, 0, 0);
+                       wclrtoeol(com_win);
+                       wprintw(com_win, str_not_found_msg, srch_str);
+                       wrefresh(com_win);
+               }
+               wmove(text_win, scr_vert,(scr_horz - horiz_offset));
+       }
+       return(found);
+}
+
+void 
+search_prompt()                /* prompt and read search string (srch_str)     */
+{
+       if (srch_str != NULL)
+               free(srch_str);
+       if ((u_srch_str != NULL) && (*u_srch_str != '\0'))
+               free(u_srch_str);
+       srch_str = get_string(search_prompt_str, FALSE);
+       gold = FALSE;
+       srch_3 = srch_str;
+       srch_1 = u_srch_str = malloc(strlen(srch_str) + 1);
+       while (*srch_3 != '\0')
+       {
+               *srch_1 = toupper(*srch_3);
+               srch_1++;
+               srch_3++;
+       }
+       *srch_1 = '\0';
+       search(TRUE);
+}
+
+void 
+del_char()                     /* delete current character     */
+{
+       in = 8;  /* backspace */
+       if (position < curr_line->line_length)  /* if not end of line   */
+       {
+               if ((ee_chinese) && (*point > 127) && 
+                   ((curr_line->line_length - position) >= 2))
+               {
+                       point++;
+                       position++;
+               }
+               position++;
+               point++;
+               scanline(point);
+               delete(TRUE);
+       }
+       else
+       {
+               right(TRUE);
+               delete(TRUE);
+       }
+}
+
+void 
+undel_char()                   /* undelete last deleted character      */
+{
+       if (d_char[0] == '\n')  /* insert line if last del_char deleted eol */
+               insert_line(TRUE);
+       else
+       {
+               in = d_char[0];
+               insert(in);
+               if (d_char[1] != '\0')
+               {
+                       in = d_char[1];
+                       insert(in);
+               }
+       }
+}
+
+void 
+del_word()                     /* delete word in front of cursor       */
+{
+       int tposit;
+       int difference;
+       unsigned char *d_word2;
+       unsigned char *d_word3;
+       unsigned char tmp_char[3];
+
+       if (d_word != NULL)
+               free(d_word);
+       d_word = malloc(curr_line->line_length);
+       tmp_char[0] = d_char[0];
+       tmp_char[1] = d_char[1];
+       tmp_char[2] = d_char[2];
+       d_word3 = point;
+       d_word2 = d_word;
+       tposit = position;
+       while ((tposit < curr_line->line_length) && 
+                               ((*d_word3 != ' ') && (*d_word3 != '\t')))
+       {
+               tposit++;
+               *d_word2 = *d_word3;
+               d_word2++;
+               d_word3++;
+       }
+       while ((tposit < curr_line->line_length) && 
+                               ((*d_word3 == ' ') || (*d_word3 == '\t')))
+       {
+               tposit++;
+               *d_word2 = *d_word3;
+               d_word2++;
+               d_word3++;
+       }
+       *d_word2 = '\0';
+       d_wrd_len = difference = d_word2 - d_word;
+       d_word2 = point;
+       while (tposit < curr_line->line_length)
+       {
+               tposit++;
+               *d_word2 = *d_word3;
+               d_word2++;
+               d_word3++;
+       }
+       curr_line->line_length -= difference;
+       *d_word2 = '\0';
+       draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
+       d_char[0] = tmp_char[0];
+       d_char[1] = tmp_char[1];
+       d_char[2] = tmp_char[2];
+       text_changes = TRUE;
+       formatted = FALSE;
+}
+
+void 
+undel_word()           /* undelete last deleted word           */
+{
+       int temp;
+       int tposit;
+       unsigned char *tmp_old_ptr;
+       unsigned char *tmp_space;
+       unsigned char *tmp_ptr;
+       unsigned char *d_word_ptr;
+
+       /*
+        |      resize line to handle undeleted word
+        */
+       if ((curr_line->max_length - (curr_line->line_length + d_wrd_len)) < 5)
+               point = resiz_line(d_wrd_len, curr_line, position);
+       tmp_ptr = tmp_space = malloc(curr_line->line_length + d_wrd_len);
+       d_word_ptr = d_word;
+       temp = 1;
+       /*
+        |      copy d_word contents into temp space
+        */
+       while (temp <= d_wrd_len)
+       {
+               temp++;
+               *tmp_ptr = *d_word_ptr;
+               tmp_ptr++;
+               d_word_ptr++;
+       }
+       tmp_old_ptr = point;
+       tposit = position;
+       /*
+        |      copy contents of line from curent position to eol into 
+        |      temp space
+        */
+       while (tposit < curr_line->line_length)
+       {
+               temp++;
+               tposit++;
+               *tmp_ptr = *tmp_old_ptr;
+               tmp_ptr++;
+               tmp_old_ptr++;
+       }
+       curr_line->line_length += d_wrd_len;
+       tmp_old_ptr = point;
+       *tmp_ptr = '\0';
+       tmp_ptr = tmp_space;
+       tposit = 1;
+       /*
+        |      now copy contents from temp space back to original line
+        */
+       while (tposit < temp)
+       {
+               tposit++;
+               *tmp_old_ptr = *tmp_ptr;
+               tmp_ptr++;
+               tmp_old_ptr++;
+       }
+       *tmp_old_ptr = '\0';
+       free(tmp_space);
+       draw_line(scr_vert, scr_horz, point, position, curr_line->line_length);
+}
+
+void 
+del_line()                     /* delete from cursor to end of line    */
+{
+       unsigned char *dl1;
+       unsigned char *dl2;
+       int tposit;
+
+       if (d_line != NULL)
+               free(d_line);
+       d_line = malloc(curr_line->line_length);
+       dl1 = d_line;
+       dl2 = point;
+       tposit = position;
+       while (tposit < curr_line->line_length)
+       {
+               *dl1 = *dl2;
+               dl1++;
+               dl2++;
+               tposit++;
+       }
+       dlt_line->line_length = 1 + tposit - position;
+       *dl1 = '\0';
+       *point = '\0';
+       curr_line->line_length = position;
+       wclrtoeol(text_win);
+       if (curr_line->next_line != NULL)
+       {
+               right(FALSE);
+               delete(FALSE);
+       }
+       text_changes = TRUE;
+}
+
+void 
+undel_line()                   /* undelete last deleted line           */
+{
+       unsigned char *ud1;
+       unsigned char *ud2;
+       int tposit;
+
+       if (dlt_line->line_length == 0)
+               return;
+
+       insert_line(TRUE);
+       left(TRUE);
+       point = resiz_line(dlt_line->line_length, curr_line, position);
+       curr_line->line_length += dlt_line->line_length - 1;
+       ud1 = point;
+       ud2 = d_line;
+       tposit = 1;
+       while (tposit < dlt_line->line_length)
+       {
+               tposit++;
+               *ud1 = *ud2;
+               ud1++;
+               ud2++;
+       }
+       *ud1 = '\0';
+       draw_line(scr_vert, scr_horz,point,position,curr_line->line_length);
+}
+
+void 
+adv_word()                     /* advance to next word         */
+{
+while ((position < curr_line->line_length) && ((*point != 32) && (*point != 9)))
+               right(TRUE);
+while ((position < curr_line->line_length) && ((*point == 32) || (*point == 9)))
+               right(TRUE);
+}
+
+void 
+move_rel(direction, lines)     /* move relative to current line        */
+char direction;
+int lines;
+{
+       int i;
+       char *tmp;
+
+       if (direction == 'u')
+       {
+               scr_pos = 0;
+               while (position > 1)
+                       left(TRUE);
+               for (i = 0; i < lines; i++)
+               {
+                       up();
+               }
+               if ((last_line > 5) && ( scr_vert < 4))
+               {
+                       tmp = point;
+                       tmp_line = curr_line;
+                       for (i= 0;(i<5)&&(curr_line->prev_line != NULL); i++)
+                       {
+                               up();
+                       }
+                       scr_vert = scr_vert + i;
+                       curr_line = tmp_line;
+                       absolute_lin += i;
+                       point = tmp;
+                       scanline(point);
+               }
+       }
+       else
+       {
+               if ((position != 1) && (curr_line->next_line != NULL))
+               {
+                       nextline();
+                       scr_pos = scr_horz = 0;
+                       if (horiz_offset)
+                       {
+                               horiz_offset = 0;
+                               midscreen(scr_vert, point);
+                       }
+               }
+               else
+                       adv_line();
+               for (i = 1; i < lines; i++)
+               {
+                       down();
+               }
+               if ((last_line > 10) && (scr_vert > (last_line - 5)))
+               {
+                       tmp = point;
+                       tmp_line = curr_line;
+                       for (i=0; (i<5) && (curr_line->next_line != NULL); i++)
+                       {
+                               down();
+                       }
+                       absolute_lin -= i;
+                       scr_vert = scr_vert - i;
+                       curr_line = tmp_line;
+                       point = tmp;
+                       scanline(point);
+               }
+       }
+       wmove(text_win, scr_vert, (scr_horz - horiz_offset));
+}
+
+void 
+eol()                          /* go to end of line                    */
+{
+       if (position < curr_line->line_length)
+       {
+               while (position < curr_line->line_length)
+                       right(TRUE);
+       }
+       else if (curr_line->next_line != NULL)
+       {
+               right(TRUE);
+               while (position < curr_line->line_length)
+                       right(TRUE);
+       }
+}
+
+void 
+bol()                          /* move to beginning of line    */
+{
+       if (point != curr_line->line)
+       {
+               while (point != curr_line->line)
+                       left(TRUE);
+       }
+       else if (curr_line->prev_line != NULL)
+       {
+               scr_pos = 0;
+               up();
+       }
+}
+
+void 
+adv_line()     /* advance to beginning of next line    */
+{
+       if ((point != curr_line->line) || (scr_pos > 0))
+       {
+               while (position < curr_line->line_length)
+                       right(TRUE);
+               right(TRUE);
+       }
+       else if (curr_line->next_line != NULL)
+       {
+               scr_pos = 0;
+               down();
+       }
+}
+
+void 
+from_top()
+{
+       struct text *tmpline = first_line;
+       int x = 1;
+
+       while ((tmpline != NULL) && (tmpline != curr_line))
+       {
+               x++;
+               tmpline = tmpline->next_line;
+       }
+       absolute_lin = x;
+}
+
+void 
+sh_command(string)     /* execute shell command                        */
+char *string;          /* string containing user command               */
+{
+       char *temp_point;
+       char *last_slash;
+       char *path;             /* directory path to executable         */
+       int parent;             /* zero if child, child's pid if parent */
+       int value;
+       int return_val;
+       struct text *line_holder;
+
+       if (restrict_mode())
+       {
+               return;
+       }
+
+       if (!(path = getenv("SHELL")))
+               path = "/bin/sh";
+       last_slash = temp_point = path;
+       while (*temp_point != '\0')
+       {
+               if (*temp_point == '/')
+                       last_slash = ++temp_point;
+               else
+                       temp_point++;
+       }
+
+       /*
+        |      if in_pipe is true, then output of the shell operation will be 
+        |      read by the editor, and curses doesn't need to be turned off
+        */
+
+       if (!in_pipe)
+       {
+               keypad(com_win, FALSE);
+               keypad(text_win, FALSE);
+               echo();
+               nl();
+               noraw();
+               resetty();
+
+#ifndef NCURSE
+               endwin();
+#endif
+       }
+
+       if (in_pipe)
+       {
+               pipe(pipe_in);          /* create a pipe        */
+               parent = fork();
+               if (!parent)            /* if the child         */
+               {
+/*
+ |  child process which will fork and exec shell command (if shell output is
+ |  to be read by editor)
+ */
+                       in_pipe = FALSE;
+/*
+ |  redirect stdout to pipe
+ */
+                       temp_stdout = dup(1);
+                       close(1);
+                       dup(pipe_in[1]);
+/*
+ |  redirect stderr to pipe
+ */
+                       temp_stderr = dup(2);
+                       close(2);
+                       dup(pipe_in[1]);
+                       close(pipe_in[1]);
+                       /*
+                        |      child will now continue down 'if (!in_pipe)' 
+                        |      path below
+                        */
+               }
+               else  /* if the parent  */
+               {
+/*
+ |  prepare editor to read from the pipe
+ */
+                       signal(SIGCHLD, SIG_IGN);
+                       line_holder = curr_line;
+                       tmp_vert = scr_vert;
+                       close(pipe_in[1]);
+                       get_fd = pipe_in[0];
+                       get_file("");
+                       close(pipe_in[0]);
+                       scr_vert = tmp_vert;
+                       scr_horz = scr_pos = 0;
+                       position = 1;
+                       curr_line = line_holder;
+                       from_top();
+                       point = curr_line->line;
+                       out_pipe = FALSE;
+                       signal(SIGCHLD, SIG_DFL);
+/*
+ |  since flag "in_pipe" is still TRUE, the path which waits for the child 
+ |  process to die will be avoided.
+ |  (the pipe is closed, no more output can be expected)
+ */
+               }
+       }
+       if (!in_pipe)
+       {
+               signal(SIGINT, SIG_IGN);
+               if (out_pipe)
+               {
+                       pipe(pipe_out);
+               }
+/*
+ |  fork process which will exec command
+ */
+               parent = fork();   
+               if (!parent)            /* if the child */
+               {
+                       if (shell_fork)
+                               putchar('\n');
+                       if (out_pipe)
+                       {
+/*
+ |  prepare the child process (soon to exec a shell command) to read from the 
+ |  pipe (which will be output from the editor's buffer)
+ */
+                               close(0);
+                               dup(pipe_out[0]);
+                               close(pipe_out[0]);
+                               close(pipe_out[1]);
+                       }
+                       for (value = 1; value < 24; value++)
+                               signal(value, SIG_DFL);
+                       execl(path, last_slash, "-c", string, NULL);
+                       fprintf(stderr, exec_err_msg, path);
+                       exit(-1);
+               }
+               else    /* if the parent        */
+               {
+                       if (out_pipe)
+                       {
+/*
+ |  output the contents of the buffer to the pipe (to be read by the 
+ |  process forked and exec'd above as stdin)
+ */
+                               close(pipe_out[0]);
+                               line_holder = first_line;
+                               while (line_holder != NULL)
+                               {
+                                       write(pipe_out[1], line_holder->line, (line_holder->line_length-1));
+                                       write(pipe_out[1], "\n", 1);
+                                       line_holder = line_holder->next_line;
+                               }
+                               close(pipe_out[1]);
+                               out_pipe = FALSE;
+                       }
+                       do
+                       {
+                               return_val = wait((int *) 0);
+                       }
+                       while ((return_val != parent) && (return_val != -1));
+/*
+ |  if this process is actually the child of the editor, exit.  Here's how it 
+ |  works:
+ |  The editor forks a process.  If output must be sent to the command to be 
+ |  exec'd another process is forked, and that process (the child's child) 
+ |  will exec the command.  In this case, "shell_fork" will be FALSE.  If no 
+ |  output is to be performed to the shell command, "shell_fork" will be TRUE.
+ |  If this is the editor process, shell_fork will be true, otherwise this is 
+ |  the child of the edit process.
+ */
+                       if (!shell_fork)
+                               exit(0);
+               }
+               signal(SIGINT, edit_abort);
+       }
+       if (shell_fork)
+       {
+               printf(continue_msg);
+               fflush(stdout);
+               while ((in = getchar()) != '\n')
+                       ;
+       }
+
+       if (!in_pipe)
+       {
+               fixterm();
+               noecho();
+               nonl();
+               raw();
+               keypad(text_win, TRUE);
+               keypad(com_win, TRUE);
+               if (info_window)
+                       clearok(info_win, TRUE);
+       }
+
+       redraw();
+}
+
+void 
+set_up_term()          /* set up the terminal for operating with ae    */
+{
+       if (!curses_initialized)
+       {
+               initscr();
+               savetty();
+               noecho();
+               raw();
+               nonl();
+               curses_initialized = TRUE;
+       }
+
+       if (((LINES > 15) && (COLS >= 80)) && info_window)
+               last_line = LINES - 8;
+       else
+       {
+               info_window = FALSE;
+               last_line = LINES - 2;
+       }
+
+       idlok(stdscr, TRUE);
+       com_win = newwin(1, COLS, (LINES - 1), 0);
+       keypad(com_win, TRUE);
+       idlok(com_win, TRUE);
+       wrefresh(com_win);
+       if (!info_window)
+               text_win = newwin((LINES - 1), COLS, 0, 0);
+       else
+               text_win = newwin((LINES - 7), COLS, 6, 0);
+       keypad(text_win, TRUE);
+       idlok(text_win, TRUE);
+       wrefresh(text_win);
+       help_win = newwin((LINES - 1), COLS, 0, 0);
+       keypad(help_win, TRUE);
+       idlok(help_win, TRUE);
+       if (info_window)
+       {
+               info_type = CONTROL_KEYS;
+               info_win = newwin(6, COLS, 0, 0);
+               werase(info_win);
+               paint_info_win();
+       }
+
+       last_col = COLS - 1;
+       local_LINES = LINES;
+       local_COLS = COLS;
+
+#ifdef NCURSE
+       if (ee_chinese)
+               nc_setattrib(A_NC_BIG5);
+#endif /* NCURSE */
+
+}
+
+void 
+resize_check()
+{
+       if ((LINES == local_LINES) && (COLS == local_COLS))
+               return;
+
+       if (info_window)
+               delwin(info_win);
+       delwin(text_win);
+       delwin(com_win);
+       delwin(help_win);
+       set_up_term();
+       redraw();
+       wrefresh(text_win);
+}
+
+static char item_alpha[] = "abcdefghijklmnopqrstuvwxyz0123456789 ";
+
+int 
+menu_op(menu_list)
+struct menu_entries menu_list[];
+{
+       WINDOW *temp_win;
+       int max_width, max_height;
+       int x_off, y_off;
+       int counter;
+       int length;
+       int input;
+       int temp;
+       int list_size;
+       int top_offset;         /* offset from top where menu items start */
+       int vert_pos;           /* vertical position                      */
+       int vert_size;          /* vertical size for menu list item display */
+       int off_start = 1;      /* offset from start of menu items to start display */
+
+
+       /*
+        |      determine number and width of menu items
+        */
+
+       list_size = 1;
+       while (menu_list[list_size + 1].item_string != NULL)
+               list_size++;
+       max_width = 0;
+       for (counter = 0; counter <= list_size; counter++)
+       {
+               if ((length = strlen(menu_list[counter].item_string)) > max_width)
+                       max_width = length;
+       }
+       max_width += 3;
+       max_width = max(max_width, strlen(menu_cancel_msg));
+       max_width = max(max_width, max(strlen(more_above_str), strlen(more_below_str)));
+       max_width += 6;
+
+       /*
+        |      make sure that window is large enough to handle menu
+        |      if not, print error message and return to calling function
+        */
+
+       if (max_width > COLS)
+       {
+               wmove(com_win, 0, 0);
+               werase(com_win);
+               wprintw(com_win, menu_too_lrg_msg);
+               wrefresh(com_win);
+               clear_com_win = TRUE;
+               return(0);
+       }
+
+       top_offset = 0;
+
+       if (list_size > LINES)
+       {
+               max_height = LINES;
+               if (max_height > 11)
+                       vert_size = max_height - 8;
+               else
+                       vert_size = max_height;
+       }
+       else
+       {
+               vert_size = list_size;
+               max_height = list_size;
+       }
+
+       if (LINES >= (vert_size + 8))
+       {
+               if (menu_list[0].argument != MENU_WARN)
+                       max_height = vert_size + 8;
+               else
+                       max_height = vert_size + 7;
+               top_offset = 4;
+       }
+       x_off = (COLS - max_width) / 2;
+       y_off = (LINES - max_height - 1) / 2;
+       temp_win = newwin(max_height, max_width, y_off, x_off);
+       keypad(temp_win, TRUE);
+
+       paint_menu(menu_list, max_width, max_height, list_size, top_offset, temp_win, off_start, vert_size);
+
+       counter = 1;
+       vert_pos = 0;
+       do
+       {
+               if (off_start > 2)
+                       wmove(temp_win, (1 + counter + top_offset - off_start), 3);
+               else
+                       wmove(temp_win, (counter + top_offset - off_start), 3);
+
+               wrefresh(temp_win);
+               in = wgetch(temp_win);
+               input = in;
+               if (input == -1)
+                       exit(0);
+
+               if (((tolower(input) >= 'a') && (tolower(input) <= 'z')) || 
+                   ((input >= '0') && (input <= '9')))
+               {
+                       if ((tolower(input) >= 'a') && (tolower(input) <= 'z'))
+                       {
+                               temp = 1 + tolower(input) - 'a';
+                       }
+                       else if ((input >= '0') && (input <= '9'))
+                       {
+                               temp = (2 + 'z' - 'a') + (input - '0');
+                       }
+
+                       if (temp <= list_size)
+                       {
+                               input = '\n';
+                               counter = temp;
+                       }
+               }
+               else
+               {               
+                       switch (input)
+                       {
+                               case ' ':       /* space        */
+                               case '\004':    /* ^d, down     */
+                               case KEY_RIGHT:
+                               case KEY_DOWN:
+                                       counter++;
+                                       if (counter > list_size)
+                                               counter = 1;
+                                       break;
+                               case '\010':    /* ^h, backspace*/
+                               case '\025':    /* ^u, up       */
+                               case 127:       /* ^?, delete   */
+                               case KEY_BACKSPACE:
+                               case KEY_LEFT:
+                               case KEY_UP:
+                                       counter--;
+                                       if (counter == 0)
+                                               counter = list_size;
+                                       break;
+                               case '\033':    /* escape key   */
+                                       if (menu_list[0].argument != MENU_WARN)
+                                               counter = 0;
+                                       break;
+                               case '\014':    /* ^l           */
+                               case '\022':    /* ^r, redraw   */
+                                       paint_menu(menu_list, max_width, max_height, 
+                                               list_size, top_offset, temp_win, 
+                                               off_start, vert_size);
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+       
+               if (((list_size - off_start) >= (vert_size - 1)) && 
+                       (counter > (off_start + vert_size - 3)) && 
+                               (off_start > 1))
+               {
+                       if (counter == list_size)
+                               off_start = (list_size - vert_size) + 2;
+                       else
+                               off_start++;
+
+                       paint_menu(menu_list, max_width, max_height, 
+                                  list_size, top_offset, temp_win, off_start, 
+                                  vert_size);
+               }
+               else if ((list_size != vert_size) && 
+                               (counter > (off_start + vert_size - 2)))
+               {
+                       if (counter == list_size)
+                               off_start = 2 + (list_size - vert_size);
+                       else if (off_start == 1)
+                               off_start = 3;
+                       else
+                               off_start++;
+
+                       paint_menu(menu_list, max_width, max_height, 
+                                  list_size, top_offset, temp_win, off_start, 
+                                  vert_size);
+               }
+               else if (counter < off_start)
+               {
+                       if (counter <= 2)
+                               off_start = 1;
+                       else
+                               off_start = counter;
+
+                       paint_menu(menu_list, max_width, max_height, 
+                                  list_size, top_offset, temp_win, off_start, 
+                                  vert_size);
+               }
+       }
+       while ((input != '\r') && (input != '\n') && (counter != 0));
+
+       werase(temp_win);
+       wrefresh(temp_win);
+       delwin(temp_win);
+
+       if ((menu_list[counter].procedure != NULL) || 
+           (menu_list[counter].iprocedure != NULL) || 
+           (menu_list[counter].nprocedure != NULL))
+       {
+               if (menu_list[counter].argument != -1)
+                       (*menu_list[counter].iprocedure)(menu_list[counter].argument);
+               else if (menu_list[counter].ptr_argument != NULL)
+                       (*menu_list[counter].procedure)(menu_list[counter].ptr_argument);
+               else
+                       (*menu_list[counter].nprocedure)();
+       }
+
+       if (info_window)
+               paint_info_win();
+       redraw();
+
+       return(counter);
+}
+
+void 
+paint_menu(menu_list, max_width, max_height, list_size, top_offset, menu_win, 
+          off_start, vert_size)
+struct menu_entries menu_list[];
+int max_width, max_height, list_size, top_offset;
+WINDOW *menu_win;
+int off_start, vert_size;
+{
+       int counter, temp_int;
+
+       werase(menu_win);
+
+       /*
+        |      output top and bottom portions of menu box only if window 
+        |      large enough 
+        */
+
+       if (max_height > vert_size)
+       {
+               wmove(menu_win, 1, 1);
+               if (!nohighlight)
+                       wstandout(menu_win);
+               waddch(menu_win, '+');
+               for (counter = 0; counter < (max_width - 4); counter++)
+                       waddch(menu_win, '-');
+               waddch(menu_win, '+');
+
+               wmove(menu_win, (max_height - 2), 1);
+               waddch(menu_win, '+');
+               for (counter = 0; counter < (max_width - 4); counter++)
+                       waddch(menu_win, '-');
+               waddch(menu_win, '+');
+               wstandend(menu_win);
+               wmove(menu_win, 2, 3);
+               waddstr(menu_win, menu_list[0].item_string);
+               wmove(menu_win, (max_height - 3), 3);
+               if (menu_list[0].argument != MENU_WARN)
+                       waddstr(menu_win, menu_cancel_msg);
+       }
+       if (!nohighlight)
+               wstandout(menu_win);
+
+       for (counter = 0; counter < (vert_size + top_offset); counter++)
+       {
+               if (top_offset == 4)
+               {
+                       temp_int = counter + 2;
+               }
+               else
+                       temp_int = counter;
+
+               wmove(menu_win, temp_int, 1);
+               waddch(menu_win, '|');
+               wmove(menu_win, temp_int, (max_width - 2));
+               waddch(menu_win, '|');
+       }
+       wstandend(menu_win);
+
+       if (list_size > vert_size)
+       {
+               if (off_start >= 3)
+               {
+                       temp_int = 1;
+                       wmove(menu_win, top_offset, 3);
+                       waddstr(menu_win, more_above_str);
+               }
+               else
+                       temp_int = 0;
+
+               for (counter = off_start; 
+                       ((temp_int + counter - off_start) < (vert_size - 1));
+                               counter++)
+               {
+                       wmove(menu_win, (top_offset + temp_int + 
+                                               (counter - off_start)), 3);
+                       if (list_size > 1)
+                               wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
+                       waddstr(menu_win, menu_list[counter].item_string);
+               }
+
+               wmove(menu_win, (top_offset + (vert_size - 1)), 3);
+
+               if (counter == list_size)
+               {
+                       if (list_size > 1)
+                               wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
+                       wprintw(menu_win, menu_list[counter].item_string);
+               }
+               else
+                       wprintw(menu_win, more_below_str);
+       }
+       else
+       {
+               for (counter = 1; counter <= list_size; counter++)
+               {
+                       wmove(menu_win, (top_offset + counter - 1), 3);
+                       if (list_size > 1)
+                               wprintw(menu_win, "%c) ", item_alpha[min((counter - 1), max_alpha_char)]);
+                       waddstr(menu_win, menu_list[counter].item_string);
+               }
+       }
+}
+
+void 
+help()
+{
+       int counter;
+
+       werase(help_win);
+       clearok(help_win, TRUE);
+       for (counter = 0; counter < 22; counter++)
+       {
+               wmove(help_win, counter, 0);
+               waddstr(help_win, (emacs_keys_mode) ? 
+                       emacs_help_text[counter] : help_text[counter]);
+       }
+       wrefresh(help_win);
+       werase(com_win);
+       wmove(com_win, 0, 0);
+       wprintw(com_win, press_any_key_msg);
+       wrefresh(com_win);
+       counter = wgetch(com_win);
+       if (counter == -1)
+               exit(0);
+       werase(com_win);
+       wmove(com_win, 0, 0);
+       werase(help_win);
+       wrefresh(help_win);
+       wrefresh(com_win);
+       redraw();
+}
+
+void 
+paint_info_win()
+{
+       int counter;
+
+       if (!info_window)
+               return;
+
+       werase(info_win);
+       for (counter = 0; counter < 5; counter++)
+       {
+               wmove(info_win, counter, 0);
+               wclrtoeol(info_win);
+               if (info_type == CONTROL_KEYS)
+                       waddstr(info_win, (emacs_keys_mode) ? 
+                         emacs_control_keys[counter] : control_keys[counter]);
+               else if (info_type == COMMANDS)
+                       waddstr(info_win, command_strings[counter]);
+       }
+       wmove(info_win, 5, 0);
+       if (!nohighlight)
+               wstandout(info_win);
+       waddstr(info_win, separator);
+       wstandend(info_win);
+       wrefresh(info_win);
+}
+
+void 
+no_info_window()
+{
+       if (!info_window)
+               return;
+       delwin(info_win);
+       delwin(text_win);
+       info_window = FALSE;
+       last_line = LINES - 2;
+       text_win = newwin((LINES - 1), COLS, 0, 0);
+       keypad(text_win, TRUE);
+       idlok(text_win, TRUE);
+       clearok(text_win, TRUE);
+       midscreen(scr_vert, point);
+       wrefresh(text_win);
+       clear_com_win = TRUE;
+}
+
+void 
+create_info_window()
+{
+       if (info_window)
+               return;
+       last_line = LINES - 8;
+       delwin(text_win);
+       text_win = newwin((LINES - 7), COLS, 6, 0);
+       keypad(text_win, TRUE);
+       idlok(text_win, TRUE);
+       werase(text_win);
+       info_window = TRUE;
+       info_win = newwin(6, COLS, 0, 0);
+       werase(info_win);
+       info_type = CONTROL_KEYS;
+       midscreen(min(scr_vert, last_line), point);
+       clearok(info_win, TRUE);
+       paint_info_win();
+       wrefresh(text_win);
+       clear_com_win = TRUE;
+}
+
+int 
+file_op(arg)
+int arg;
+{
+       char *string;
+       int flag;
+
+       if (restrict_mode())
+       {
+               return(0);
+       }
+
+       if (arg == READ_FILE)
+       {
+               string = get_string(file_read_prompt_str, TRUE);
+               recv_file = TRUE;
+               tmp_file = resolve_name(string);
+               check_fp();
+               if (tmp_file != string)
+                       free(tmp_file);
+               free(string);
+       }
+       else if (arg == WRITE_FILE)
+       {
+               string = get_string(file_write_prompt_str, TRUE);
+               tmp_file = resolve_name(string);
+               write_file(tmp_file, 1);
+               if (tmp_file != string)
+                       free(tmp_file);
+               free(string);
+       }
+       else if (arg == SAVE_FILE)
+       {
+       /*
+        |      changes made here should be reflected in finish()
+        */
+
+               if (in_file_name)
+                       flag = TRUE;
+               else
+                       flag = FALSE;
+
+               string = in_file_name;
+               if ((string == NULL) || (*string == '\0'))
+                       string = get_string(save_file_name_prompt, TRUE);
+               if ((string == NULL) || (*string == '\0'))
+               {
+                       wmove(com_win, 0, 0);
+                       wprintw(com_win, file_not_saved_msg);
+                       wclrtoeol(com_win);
+                       wrefresh(com_win);
+                       clear_com_win = TRUE;
+                       return(0);
+               }
+               if (!flag)
+               {
+                       tmp_file = resolve_name(string);
+                       if (tmp_file != string)
+                       {
+                               free(string);
+                               string = tmp_file;
+                       }
+               }
+               if (write_file(string, 1))
+               {
+                       in_file_name = string;
+                       text_changes = FALSE;
+               }
+               else if (!flag)
+                       free(string);
+       }
+       return(0);
+}
+
+void 
+shell_op()
+{
+       char *string;
+
+       if (((string = get_string(shell_prompt, TRUE)) != NULL) && 
+                       (*string != '\0'))
+       {
+               sh_command(string);
+               free(string);
+       }
+}
+
+void 
+leave_op()
+{
+       if (text_changes)
+       {
+               menu_op(leave_menu);
+       }
+       else
+               quit(TRUE);
+}
+
+void 
+redraw()
+{
+       if (info_window)
+        {
+                clearok(info_win, TRUE);
+               paint_info_win();
+        }
+        else
+               clearok(text_win, TRUE);
+       midscreen(scr_vert, point);
+}
+
+/*
+ |     The following routines will "format" a paragraph (as defined by a 
+ |     block of text with blank lines before and after the block).
+ */
+
+int 
+Blank_Line(test_line)  /* test if line has any non-space characters    */
+struct text *test_line;
+{
+       unsigned char *line;
+       int length;
+       
+       if (test_line == NULL)
+               return(TRUE);
+
+       length = 1;
+       line = test_line->line;
+
+       /*
+        |      To handle troff/nroff documents, consider a line with a 
+        |      period ('.') in the first column to be blank.  To handle mail 
+        |      messages with included text, consider a line with a '>' blank.
+        */
+
+       if ((*line == '.') || (*line == '>'))
+               return(TRUE);
+
+       while (((*line == ' ') || (*line == '\t')) && (length < test_line->line_length))
+       {
+               length++;
+               line++;
+       }
+       if (length != test_line->line_length)
+               return(FALSE);
+       else
+               return(TRUE);
+}
+
+void 
+Format()       /* format the paragraph according to set margins        */
+{
+       int string_count;
+       int offset;
+       int temp_case;
+       int status;
+       int tmp_af;
+       int counter;
+       unsigned char *line;
+       unsigned char *tmp_srchstr;
+       unsigned char *temp1, *temp2;
+       unsigned char *temp_dword;
+       unsigned char temp_d_char[3];
+
+       temp_d_char[0] = d_char[0];
+       temp_d_char[1] = d_char[1];
+       temp_d_char[2] = d_char[2];
+
+/*
+ |     if observ_margins is not set, or the current line is blank, 
+ |     do not format the current paragraph
+ */
+
+       if ((!observ_margins) || (Blank_Line(curr_line)))
+               return;
+
+/*
+ |     save the currently set flags, and clear them
+ */
+
+       wmove(com_win, 0, 0);
+       wclrtoeol(com_win);
+       wprintw(com_win, formatting_msg);
+       wrefresh(com_win);
+
+/*
+ |     get current position in paragraph, so after formatting, the cursor 
+ |     will be in the same relative position
+ */
+
+       tmp_af = auto_format;
+       auto_format = FALSE;
+       offset = position;
+       if (position != 1)
+               prev_word();
+       temp_dword = d_word;
+       d_word = NULL;
+       temp_case = case_sen;
+       case_sen = TRUE;
+       tmp_srchstr = srch_str;
+       temp2 = srch_str = (unsigned char *) malloc(1 + curr_line->line_length - position);
+       if ((*point == ' ') || (*point == '\t'))
+               adv_word();
+       offset -= position;
+       counter = position;
+       line = temp1 = point;
+       while ((*temp1 != '\0') && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
+       {
+               *temp2 = *temp1;
+               temp2++;
+               temp1++;
+               counter++;
+       }
+       *temp2 = '\0';
+       if (position != 1)
+               bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+       string_count = 0;
+       status = TRUE;
+       while ((line != point) && (status))
+       {
+               status = search(FALSE);
+               string_count++;
+       }
+
+       wmove(com_win, 0, 0);
+       wclrtoeol(com_win);
+       wprintw(com_win, formatting_msg);
+       wrefresh(com_win);
+
+/*
+ |     now get back to the start of the paragraph to start formatting
+ */
+
+       if (position != 1)
+               bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+
+       observ_margins = FALSE;
+
+/*
+ |     Start going through lines, putting spaces at end of lines if they do 
+ |     not already exist.  Append lines together to get one long line, and 
+ |     eliminate spacing at begin of lines.
+ */
+
+       while (!Blank_Line(curr_line->next_line))
+       {
+               eol();
+               left(TRUE);
+               if (*point != ' ')
+               {
+                       right(TRUE);
+                       insert(' ');
+               }
+               else
+                       right(TRUE);
+               del_char();
+               if ((*point == ' ') || (*point == '\t'))
+                       del_word();
+       }
+
+/*
+ |     Now there is one long line.  Eliminate extra spaces within the line
+ |     after the first word (so as not to blow away any indenting the user 
+ |     may have put in).
+ */
+
+       bol();
+       adv_word();
+       while (position < curr_line->line_length)
+       {
+               if ((*point == ' ') && (*(point + 1) == ' '))
+                       del_char();
+               else
+                       right(TRUE);
+       }
+
+/*
+ |     Now make sure there are two spaces after a '.'.
+ */
+
+       bol();
+       while (position < curr_line->line_length)
+       {
+               if ((*point == '.') && (*(point + 1) == ' '))
+               {
+                       right(TRUE);
+                       insert(' ');
+                       insert(' ');
+                       while (*point == ' ')
+                               del_char();
+               }
+               right(TRUE);
+       }
+
+       observ_margins = TRUE;
+       bol();
+
+       wmove(com_win, 0, 0);
+       wclrtoeol(com_win);
+       wprintw(com_win, formatting_msg);
+       wrefresh(com_win);
+
+/*
+ |     create lines between margins
+ */
+
+       while (position < curr_line->line_length)
+       {
+               while ((scr_pos < right_margin) && (position < curr_line->line_length))
+                       right(TRUE);
+               if (position < curr_line->line_length)
+               {
+                       prev_word();
+                       if (position == 1)
+                               adv_word();
+                       insert_line(TRUE);
+               }
+       }
+
+/*
+ |     go back to begin of paragraph, put cursor back to original position
+ */
+
+       bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+
+/*
+ |     find word cursor was in
+ */
+
+       while ((status) && (string_count > 0))
+       {
+               search(FALSE);
+               string_count--;
+       }
+
+/*
+ |     offset the cursor to where it was before from the start of the word
+ */
+
+       while (offset > 0)
+       {
+               offset--;
+               right(TRUE);
+       }
+
+/*
+ |     reset flags and strings to what they were before formatting
+ */
+
+       if (d_word != NULL)
+               free(d_word);
+       d_word = temp_dword;
+       case_sen = temp_case;
+       free(srch_str);
+       srch_str = tmp_srchstr;
+       d_char[0] = temp_d_char[0];
+       d_char[1] = temp_d_char[1];
+       d_char[2] = temp_d_char[2];
+       auto_format = tmp_af;
+
+       midscreen(scr_vert, point);
+       werase(com_win);
+       wrefresh(com_win);
+}
+
+unsigned char *init_name[3] = {
+       "/usr/local/lib/init.ee", 
+       NULL, 
+       ".init.ee"
+       };
+
+void 
+ee_init()      /* check for init file and read it if it exists */
+{
+       FILE *init_file;
+       unsigned char *string;
+       unsigned char *str1;
+       unsigned char *str2;
+       char *home;
+       int counter;
+       int temp_int;
+
+       string = getenv("HOME");
+       if (string == NULL)
+               string = "/tmp";
+       str1 = home = malloc(strlen(string)+10);
+       strcpy(home, string);
+       strcat(home, "/.init.ee");
+       init_name[1] = home;
+       string = malloc(512);
+
+       for (counter = 0; counter < 3; counter++)
+       {
+               if (!(access(init_name[counter], 4)))
+               {
+                       init_file = fopen(init_name[counter], "r");
+                       while ((str2 = fgets(string, 512, init_file)) != NULL)
+                       {
+                               str1 = str2 = string;
+                               while (*str2 != '\n')
+                                       str2++;
+                               *str2 = '\0';
+
+                               if (unique_test(string, init_strings) != 1)
+                                       continue;
+
+                               if (compare(str1, CASE, FALSE))
+                                       case_sen = TRUE;
+                               else if (compare(str1, NOCASE, FALSE))
+                                       case_sen = FALSE;
+                               else if (compare(str1, EXPAND, FALSE))
+                                       expand_tabs = TRUE;
+                               else if (compare(str1, NOEXPAND, FALSE))
+                                       expand_tabs = FALSE;
+                               else if (compare(str1, INFO, FALSE))
+                                       info_window = TRUE;
+                               else if (compare(str1, NOINFO, FALSE))
+                                       info_window = FALSE;   
+                               else if (compare(str1, MARGINS, FALSE))
+                                       observ_margins = TRUE;
+                               else if (compare(str1, NOMARGINS, FALSE))
+                                       observ_margins = FALSE;
+                               else if (compare(str1, AUTOFORMAT, FALSE))
+                               {
+                                       auto_format = TRUE;
+                                       observ_margins = TRUE;
+                               }
+                               else if (compare(str1, NOAUTOFORMAT, FALSE))
+                                       auto_format = FALSE;
+                               else if (compare(str1, Echo, FALSE))
+                               {
+                                       str1 = next_word(str1);
+                                       if (*str1 != '\0')
+                                               echo_string(str1);
+                               }
+                               else if (compare(str1, PRINTCOMMAND, FALSE))
+                               {
+                                       str1 = next_word(str1);
+                                       print_command = malloc(strlen(str1)+1);
+                                       strcpy(print_command, str1);
+                               }
+                               else if (compare(str1, RIGHTMARGIN, FALSE))
+                               {
+                                       str1 = next_word(str1);
+                                       if ((*str1 >= '0') && (*str1 <= '9'))
+                                       {
+                                               temp_int = atoi(str1);
+                                               if (temp_int > 0)
+                                                       right_margin = temp_int;
+                                       }
+                               }
+                               else if (compare(str1, HIGHLIGHT, FALSE))
+                                       nohighlight = FALSE;
+                               else if (compare(str1, NOHIGHLIGHT, FALSE))
+                                       nohighlight = TRUE;
+                               else if (compare(str1, EIGHTBIT, FALSE))
+                                       eightbit = TRUE;
+                               else if (compare(str1, NOEIGHTBIT, FALSE))
+                               {
+                                       eightbit = FALSE;
+                                       ee_chinese = FALSE;
+                               }
+                               else if (compare(str1, EMACS_string, FALSE))
+                                       emacs_keys_mode = TRUE;
+                               else if (compare(str1, NOEMACS_string, FALSE))
+                                       emacs_keys_mode = FALSE;
+                               else if (compare(str1, chinese_cmd, FALSE))
+                               {
+                                       ee_chinese = TRUE;
+                                       eightbit = TRUE;
+                               }
+                               else if (compare(str1, nochinese_cmd, FALSE))
+                                       ee_chinese = FALSE;
+                       }
+                       fclose(init_file);
+               }
+       }
+       free(string);
+       free(home);
+
+       string = getenv("LANG");
+       if (string != NULL)
+       {
+               if (strcmp(string, "zh_TW.big5") == 0)
+               {
+                       ee_chinese = TRUE;
+                       eightbit = TRUE;
+               }
+       }
+}
+
+/*
+ |     Save current configuration to .init.ee file in the current directory.
+ */
+
+void 
+dump_ee_conf() 
+{
+       FILE *init_file;
+       FILE *old_init_file = NULL;
+       char *file_name = ".init.ee";
+       char *home_dir =  "~/.init.ee";
+       char buffer[512];
+       struct stat buf;
+       char *string;
+       int length;
+       int option = 0;
+
+       if (restrict_mode())
+       {
+               return;
+       }
+
+       option = menu_op(config_dump_menu);
+
+       werase(com_win);
+       wmove(com_win, 0, 0);
+
+       if (option == 0)
+       {
+               wprintw(com_win, conf_not_saved_msg);
+               wrefresh(com_win);
+               return;
+       }
+       else if (option == 2)
+               file_name = resolve_name(home_dir);
+
+       /*
+        |      If a .init.ee file exists, move it to .init.ee.old.
+        */
+
+       if (stat(file_name, &buf) != -1)
+       {
+               sprintf(buffer, "%s.old", file_name);
+               unlink(buffer);
+               link(file_name, buffer);
+               unlink(file_name);
+               old_init_file = fopen(buffer, "r");
+       }
+
+       init_file = fopen(file_name, "w");
+       if (init_file == NULL)
+       {
+               wprintw(com_win, conf_dump_err_msg);
+               wrefresh(com_win);
+               return;
+       }
+
+       if (old_init_file != NULL)
+       {
+               /*
+                |      Copy non-configuration info into new .init.ee file.
+                */
+               while ((string = fgets(buffer, 512, old_init_file)) != NULL)
+               {
+                       length = strlen(string);
+                       string[length - 1] = '\0';
+
+                       if (unique_test(string, init_strings) == 1)
+                       {
+                               if (compare(string, Echo, FALSE))
+                               {
+                                       fprintf(init_file, "%s\n", string);
+                               }
+                       }
+                       else
+                               fprintf(init_file, "%s\n", string);
+               }
+
+               fclose(old_init_file);
+       }
+
+       fprintf(init_file, "%s\n", case_sen ? CASE : NOCASE);
+       fprintf(init_file, "%s\n", expand_tabs ? EXPAND : NOEXPAND);
+       fprintf(init_file, "%s\n", info_window ? INFO : NOINFO );
+       fprintf(init_file, "%s\n", observ_margins ? MARGINS : NOMARGINS );
+       fprintf(init_file, "%s\n", auto_format ? AUTOFORMAT : NOAUTOFORMAT );
+       fprintf(init_file, "%s %s\n", PRINTCOMMAND, print_command);
+       fprintf(init_file, "%s %d\n", RIGHTMARGIN, right_margin);
+       fprintf(init_file, "%s\n", nohighlight ? NOHIGHLIGHT : HIGHLIGHT );
+       fprintf(init_file, "%s\n", eightbit ? EIGHTBIT : NOEIGHTBIT );
+       fprintf(init_file, "%s\n", emacs_keys_mode ? EMACS_string : NOEMACS_string );
+       fprintf(init_file, "%s\n", ee_chinese ? chinese_cmd : nochinese_cmd );
+
+       fclose(init_file);
+
+       wprintw(com_win, conf_dump_success_msg, file_name);
+       wrefresh(com_win);
+
+       if ((option == 2) && (file_name != home_dir))
+       {
+               free(file_name);
+       }
+}
+
+void 
+echo_string(string)    /* echo the given string        */
+char *string;
+{
+       char *temp;
+       int Counter;
+
+               temp = string;
+               while (*temp != '\0')
+               {
+                       if (*temp == '\\')
+                       {
+                               temp++;
+                               if (*temp == 'n')
+                                       putchar('\n');
+                               else if (*temp == 't')
+                                       putchar('\t');
+                               else if (*temp == 'b')
+                                       putchar('\b');
+                               else if (*temp == 'r')
+                                       putchar('\r');
+                               else if (*temp == 'f')
+                                       putchar('\f');
+                               else if ((*temp == 'e') || (*temp == 'E'))
+                                       putchar('\033');        /* escape */
+                               else if (*temp == '\\')
+                                       putchar('\\');
+                               else if (*temp == '\'')
+                                       putchar('\'');
+                               else if ((*temp >= '0') && (*temp <= '9'))
+                               {
+                                       Counter = 0;
+                                       while ((*temp >= '0') && (*temp <= '9'))
+                                       {
+                                               Counter = (8 * Counter) + (*temp - '0');
+                                               temp++;
+                                       }
+                                       putchar(Counter);
+                                       temp--;
+                               }
+                               temp++;
+                       }
+                       else
+                       {
+                               putchar(*temp);
+                               temp++;
+                       }
+               }
+
+       fflush(stdout);
+}
+
+void 
+spell_op()     /* check spelling of words in the editor        */
+{
+       if (restrict_mode())
+       {
+               return;
+       }
+       top();                  /* go to top of file            */
+       insert_line(FALSE);     /* create two blank lines       */
+       insert_line(FALSE);
+       top();
+       command(shell_echo_msg);
+       adv_line();
+       wmove(com_win, 0, 0);
+       wprintw(com_win, spell_in_prog_msg);
+       wrefresh(com_win);
+       command("<>!spell");    /* send contents of buffer to command 'spell' 
+                                  and read the results back into the editor */
+}
+
+void 
+ispell_op()
+{
+       char template[128], *name;
+       char string[256];
+       int fd;
+
+       if (restrict_mode())
+       {
+               return;
+       }
+       (void)sprintf(template, "/tmp/ee.XXXXXXXX");
+       fd = mkstemp(template);
+       if (fd < 0) {
+               wmove(com_win, 0, 0);
+               wprintw(com_win, create_file_fail_msg, name);
+               wrefresh(com_win);
+               return;
+       }
+       close(fd);
+       if (write_file(name, 0))
+       {
+               sprintf(string, "ispell %s", name);
+               sh_command(string);
+               delete_text();
+               tmp_file = name;
+               recv_file = TRUE;
+               check_fp();
+               unlink(name);
+       }
+}
+
+int
+first_word_len(test_line)
+struct text *test_line;
+{
+       int counter;
+       unsigned char *pnt;
+
+       if (test_line == NULL)
+               return(0);
+
+       pnt = test_line->line;
+       if ((pnt == NULL) || (*pnt == '\0') || 
+           (*pnt == '.') || (*pnt == '>'))
+               return(0);
+
+       if ((*pnt == ' ') || (*pnt == '\t'))
+       {
+               pnt = next_word(pnt);
+       }
+
+       if (*pnt == '\0')
+               return(0);
+
+       counter = 0;
+       while ((*pnt != '\0') && ((*pnt != ' ') && (*pnt != '\t')))
+       {
+               pnt++;
+               counter++;
+       }
+       while ((*pnt != '\0') && ((*pnt == ' ') || (*pnt == '\t')))
+       {
+               pnt++;
+               counter++;
+       }
+       return(counter);
+}
+
+void 
+Auto_Format()  /* format the paragraph according to set margins        */
+{
+       int string_count;
+       int offset;
+       int temp_case;
+       int word_len;
+       int temp_dwl;
+       int tmp_d_line_length;
+       int leave_loop = FALSE;
+       int status;
+       int counter;
+       char not_blank;
+       unsigned char *line;
+       unsigned char *tmp_srchstr;
+       unsigned char *temp1, *temp2;
+       unsigned char *temp_dword;
+       unsigned char temp_d_char[3];
+       unsigned char *tmp_d_line;
+
+
+       temp_d_char[0] = d_char[0];
+       temp_d_char[1] = d_char[1];
+       temp_d_char[2] = d_char[2];
+
+/*
+ |     if observ_margins is not set, or the current line is blank, 
+ |     do not format the current paragraph
+ */
+
+       if ((!observ_margins) || (Blank_Line(curr_line)))
+               return;
+
+/*
+ |     get current position in paragraph, so after formatting, the cursor 
+ |     will be in the same relative position
+ */
+
+       tmp_d_line = d_line;
+       tmp_d_line_length = dlt_line->line_length;
+       d_line = NULL;
+       auto_format = FALSE;
+       offset = position;
+       if ((position != 1) && ((*point == ' ') || (*point == '\t') || (position == curr_line->line_length) || (*point == '\0')))
+               prev_word();
+       temp_dword = d_word;
+       temp_dwl = d_wrd_len;
+       d_wrd_len = 0;
+       d_word = NULL;
+       temp_case = case_sen;
+       case_sen = TRUE;
+       tmp_srchstr = srch_str;
+       temp2 = srch_str = (unsigned char *) malloc(1 + curr_line->line_length - position);
+       if ((*point == ' ') || (*point == '\t'))
+               adv_word();
+       offset -= position;
+       counter = position;
+       line = temp1 = point;
+       while ((*temp1 != '\0') && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length))
+       {
+               *temp2 = *temp1;
+               temp2++;
+               temp1++;
+               counter++;
+       }
+       *temp2 = '\0';
+       if (position != 1)
+               bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+       string_count = 0;
+       status = TRUE;
+       while ((line != point) && (status))
+       {
+               status = search(FALSE);
+               string_count++;
+       }
+
+/*
+ |     now get back to the start of the paragraph to start checking
+ */
+
+       if (position != 1)
+               bol();
+       while (!Blank_Line(curr_line->prev_line))
+               bol();
+
+/*
+ |     Start going through lines, putting spaces at end of lines if they do 
+ |     not already exist.  Check line length, and move words to the next line 
+ |     if they cross the margin.  Then get words from the next line if they 
+ |     will fit in before the margin.  
+ */
+
+       counter = 0;
+
+       while (!leave_loop)
+       {
+               if (position != curr_line->line_length)
+                       eol();
+               left(TRUE);
+               if (*point != ' ')
+               {
+                       right(TRUE);
+                       insert(' ');
+               }
+               else
+                       right(TRUE);
+
+               not_blank = FALSE;
+
+               /*
+                |      fill line if first word on next line will fit 
+                |      in the line without crossing the margin
+                */
+
+               while ((curr_line->next_line != NULL) && 
+                      ((word_len = first_word_len(curr_line->next_line)) > 0) 
+                       && ((scr_pos + word_len) < right_margin))
+               {
+                       adv_line();
+                       if ((*point == ' ') || (*point == '\t'))
+                               adv_word();
+                       del_word();
+                       if (position != 1)
+                               bol();
+
+                       /*
+                        |      We know this line was not blank before, so 
+                        |      make sure that it doesn't have one of the 
+                        |      leading characters that indicate the line 
+                        |      should not be modified.
+                        |
+                        |      We also know that this character should not 
+                        |      be left as the first character of this line.
+                        */
+
+                       if ((Blank_Line(curr_line)) && 
+                           (curr_line->line[0] != '.') && 
+                           (curr_line->line[0] != '>'))
+                       {
+                               del_line();
+                               not_blank = FALSE;
+                       }
+                       else
+                               not_blank = TRUE;
+
+                       /*
+                        |   go to end of previous line
+                        */
+                       left(TRUE);
+                       undel_word();
+                       eol();
+                       /*
+                        |   make sure there's a space at the end of the line
+                        */
+                       left(TRUE);
+                       if (*point != ' ')
+                       {
+                               right(TRUE);
+                               insert(' ');
+                       }
+                       else
+                               right(TRUE);
+               }
+
+               /*
+                |      make sure line does not cross right margin
+                */
+
+               while (right_margin <= scr_pos)
+               {
+                       prev_word();
+                       if (position != 1)
+                       {
+                               del_word();
+                               if (Blank_Line(curr_line->next_line))
+                                       insert_line(TRUE);
+                               else
+                                       adv_line();
+                               if ((*point == ' ') || (*point == '\t'))
+                                       adv_word();
+                               undel_word();
+                               not_blank = TRUE;
+                               if (position != 1)
+                                       bol();
+                               left(TRUE);
+                       }
+               }
+
+               if ((!Blank_Line(curr_line->next_line)) || (not_blank))
+               {
+                       adv_line();
+                       counter++;
+               }
+               else
+                       leave_loop = TRUE;
+       }
+
+/*
+ |     go back to begin of paragraph, put cursor back to original position
+ */
+
+       if (position != 1)
+               bol();
+       while ((counter-- > 0) || (!Blank_Line(curr_line->prev_line)))
+               bol();
+
+/*
+ |     find word cursor was in
+ */
+
+       status = TRUE;
+       while ((status) && (string_count > 0))
+       {
+               status = search(FALSE);
+               string_count--;
+       }
+
+/*
+ |     offset the cursor to where it was before from the start of the word
+ */
+
+       while (offset > 0)
+       {
+               offset--;
+               right(TRUE);
+       }
+
+       if ((string_count > 0) && (offset < 0))
+       {
+               while (offset < 0)
+               {
+                       offset++;
+                       left(TRUE);
+               }
+       }
+
+/*
+ |     reset flags and strings to what they were before formatting
+ */
+
+       if (d_word != NULL)
+               free(d_word);
+       d_word = temp_dword;
+       d_wrd_len = temp_dwl;
+       case_sen = temp_case;
+       free(srch_str);
+       srch_str = tmp_srchstr;
+       d_char[0] = temp_d_char[0];
+       d_char[1] = temp_d_char[1];
+       d_char[2] = temp_d_char[2];
+       auto_format = TRUE;
+       dlt_line->line_length = tmp_d_line_length;
+       d_line = tmp_d_line;
+
+       formatted = TRUE;
+       midscreen(scr_vert, point);
+}
+
+void 
+modes_op()
+{
+       int ret_value;
+       int counter;
+       char *string;
+
+       do
+       {
+               sprintf(modes_menu[1].item_string, "%s %s", mode_strings[1], 
+                                       (expand_tabs ? ON : OFF));
+               sprintf(modes_menu[2].item_string, "%s %s", mode_strings[2], 
+                                       (case_sen ? ON : OFF));
+               sprintf(modes_menu[3].item_string, "%s %s", mode_strings[3], 
+                                       (observ_margins ? ON : OFF));
+               sprintf(modes_menu[4].item_string, "%s %s", mode_strings[4], 
+                                       (auto_format ? ON : OFF));
+               sprintf(modes_menu[5].item_string, "%s %s", mode_strings[5], 
+                                       (eightbit ? ON : OFF));
+               sprintf(modes_menu[6].item_string, "%s %s", mode_strings[6], 
+                                       (info_window ? ON : OFF));
+               sprintf(modes_menu[7].item_string, "%s %s", mode_strings[7], 
+                                       (emacs_keys_mode ? ON : OFF));
+               sprintf(modes_menu[8].item_string, "%s %d", mode_strings[8], 
+                                       right_margin);
+               sprintf(modes_menu[9].item_string, "%s %s", mode_strings[9], 
+                                       (ee_chinese ? ON : OFF));
+
+               ret_value = menu_op(modes_menu);
+
+               switch (ret_value) 
+               {
+                       case 1:
+                               expand_tabs = !expand_tabs;
+                               break;
+                       case 2:
+                               case_sen = !case_sen;
+                               break;
+                       case 3:
+                               observ_margins = !observ_margins;
+                               break;
+                       case 4:
+                               auto_format = !auto_format;
+                               if (auto_format)
+                                       observ_margins = TRUE;
+                               break;
+                       case 5:
+                               eightbit = !eightbit;
+                               if (!eightbit)
+                                       ee_chinese = FALSE;
+#ifdef NCURSE
+                               if (ee_chinese)
+                                       nc_setattrib(A_NC_BIG5);
+                               else
+                                       nc_clearattrib(A_NC_BIG5);
+#endif /* NCURSE */
+
+                               redraw();
+                               wnoutrefresh(text_win);
+                               break;
+                       case 6:
+                               if (info_window)
+                                       no_info_window();
+                               else
+                                       create_info_window();
+                               break;
+                       case 7:
+                               emacs_keys_mode = !emacs_keys_mode;
+                               if (info_window)
+                                       paint_info_win();
+                               break;
+                       case 8:
+                               string = get_string(margin_prompt, TRUE);
+                               if (string != NULL)
+                               {
+                                       counter = atoi(string);
+                                       if (counter > 0)
+                                               right_margin = counter;
+                                       free(string);
+                               }
+                               break;
+                       case 9:
+                               ee_chinese = !ee_chinese;
+                               if (ee_chinese != FALSE)
+                                       eightbit = TRUE;
+#ifdef NCURSE
+                               if (ee_chinese)
+                                       nc_setattrib(A_NC_BIG5);
+                               else
+                                       nc_clearattrib(A_NC_BIG5);
+#endif /* NCURSE */
+                               redraw();
+                               break;
+                       default:
+                               break;
+               }
+       }
+       while (ret_value != 0);
+}
+
+char *
+is_in_string(string, substring)        /* a strchr() look-alike for systems without
+                                  strchr() */
+char * string, *substring;
+{
+       char *full, *sub;
+
+       for (sub = substring; (sub != NULL) && (*sub != '\0'); sub++)
+       {
+               for (full = string; (full != NULL) && (*full != '\0'); 
+                               full++)
+               {
+                       if (*sub == *full)
+                               return(full);
+               }
+       }
+       return(NULL);
+}
+
+/*
+ |     handle names of the form "~/file", "~user/file", 
+ |     "$HOME/foo", "~/$FOO", etc.
+ */
+
+char *
+resolve_name(name)
+char *name;
+{
+       char long_buffer[1024];
+       char short_buffer[128];
+       char *buffer;
+       char *slash;
+       char *tmp;
+       char *start_of_var;
+       int offset;
+       int index;
+       int counter;
+       struct passwd *user;
+
+       if (name[0] == '~') 
+       {
+               if (name[1] == '/')
+               {
+                       index = getuid();
+                       user = (struct passwd *) getpwuid(index);
+                       slash = name + 1;
+               }
+               else
+               {
+                       slash = strchr(name, '/');
+                       if (slash == NULL) 
+                               return(name);
+                       *slash = '\0';
+                       user = (struct passwd *) getpwnam((name + 1));
+                       *slash = '/';
+               }
+               if (user == NULL) 
+               {
+                       return(name);
+               }
+               buffer = malloc(strlen(user->pw_dir) + strlen(slash) + 1);
+               strcpy(buffer, user->pw_dir);
+               strcat(buffer, slash);
+       }
+       else
+               buffer = name;
+
+       if (is_in_string(buffer, "$"))
+       {
+               tmp = buffer;
+               index = 0;
+               
+               while ((*tmp != '\0') && (index < 1024))
+               {
+
+                       while ((*tmp != '\0') && (*tmp != '$') && 
+                               (index < 1024))
+                       {
+                               long_buffer[index] = *tmp;
+                               tmp++;
+                               index++;
+                       }
+
+                       if ((*tmp == '$') && (index < 1024))
+                       {
+                               counter = 0;
+                               start_of_var = tmp;
+                               tmp++;
+                               if (*tmp == '{') /* } */        /* bracketed variable name */
+                               {
+                                       tmp++;                          /* { */
+                                       while ((*tmp != '\0') && 
+                                               (*tmp != '}') && 
+                                               (counter < 128))
+                                       {
+                                               short_buffer[counter] = *tmp;
+                                               counter++;
+                                               tmp++;
+                                       }                       /* { */
+                                       if (*tmp == '}')
+                                               tmp++;
+                               }
+                               else
+                               {
+                                       while ((*tmp != '\0') && 
+                                              (*tmp != '/') && 
+                                              (*tmp != '$') && 
+                                              (counter < 128))
+                                       {
+                                               short_buffer[counter] = *tmp;
+                                               counter++;
+                                               tmp++;
+                                       }
+                               }
+                               short_buffer[counter] = '\0';
+                               if ((slash = getenv(short_buffer)) != NULL)
+                               {
+                                       offset = strlen(slash);
+                                       if ((offset + index) < 1024)
+                                               strcpy(&long_buffer[index], slash);
+                                       index += offset;
+                               }
+                               else
+                               {
+                                       while ((start_of_var != tmp) && (index < 1024))
+                                       {
+                                               long_buffer[index] = *start_of_var;
+                                               start_of_var++;
+                                               index++;
+                                       }
+                               }
+                       }
+               }
+
+               if (index == 1024)
+                       return(buffer);
+               else
+                       long_buffer[index] = '\0';
+
+               if (name != buffer)
+                       free(buffer);
+               buffer = malloc(index + 1);
+               strcpy(buffer, long_buffer);
+       }
+
+       return(buffer);
+}
+
+int
+restrict_mode()
+{
+       if (!restricted)
+               return(FALSE);
+
+       wmove(com_win, 0, 0);
+       wprintw(com_win, restricted_msg);
+       wclrtoeol(com_win);
+       wrefresh(com_win);
+       clear_com_win = TRUE;
+       return(TRUE);
+}
+
+/*
+ |     The following routine tests the input string against the list of 
+ |     strings, to determine if the string is a unique match with one of the 
+ |     valid values.
+ */
+
+int 
+unique_test(string, list)
+char *string;
+char *list[];
+{
+       int counter;
+       int num_match;
+       int result;
+
+       num_match = 0;
+       counter = 0;
+       while (list[counter] != NULL)
+       {
+               result = compare(string, list[counter], FALSE);
+               if (result)
+                       num_match++;
+               counter++;
+       }
+       return(num_match);
+}
+
+#ifndef NO_CATGETS
+/*
+ |     Get the catalog entry, and if it got it from the catalog, 
+ |     make a copy, since the buffer will be overwritten by the 
+ |     next call to catgets().
+ */
+
+char *
+catgetlocal(number, string)
+int number;
+char *string;
+{
+       char *temp1;
+       char *temp2;
+
+       temp1 = catgets(catalog, 1, number, string);
+       if (temp1 != string)
+       {
+               temp2 = malloc(strlen(temp1) + 1);
+               strcpy(temp2, temp1);
+               temp1 = temp2;
+       }
+       return(temp1);
+}
+#endif /* NO_CATGETS */
+
+/*
+ |     The following is to allow for using message catalogs which allow 
+ |     the software to be 'localized', that is, to use different languages 
+ |     all with the same binary.  For more information, see your system 
+ |     documentation, or the X/Open Internationalization Guide.
+ */
+
+void 
+strings_init()
+{
+       int counter;
+
+#ifndef NO_CATGETS
+       setlocale(LC_ALL, "");
+       catalog = catopen("ee", 0);
+#endif /* NO_CATGETS */
+
+       modes_menu[0].item_string = catgetlocal( 1, "modes menu");
+       mode_strings[1]  = catgetlocal( 2, "tabs to spaces       "); 
+       mode_strings[2]  = catgetlocal( 3, "case sensitive search"); 
+       mode_strings[3]  = catgetlocal( 4, "margins observed     "); 
+       mode_strings[4]  = catgetlocal( 5, "auto-paragraph format"); 
+       mode_strings[5]  = catgetlocal( 6, "eightbit characters  "); 
+       mode_strings[6]  = catgetlocal( 7, "info window          "); 
+       mode_strings[8]  = catgetlocal( 8, "right margin         ");
+       leave_menu[0].item_string  = catgetlocal( 9, "leave menu");
+       leave_menu[1].item_string  = catgetlocal( 10, "save changes");
+       leave_menu[2].item_string  = catgetlocal( 11, "no save");
+       file_menu[0].item_string  = catgetlocal( 12, "file menu");
+       file_menu[1].item_string  = catgetlocal( 13, "read a file");
+       file_menu[2].item_string  = catgetlocal( 14, "write a file");
+       file_menu[3].item_string  = catgetlocal( 15, "save file");
+       file_menu[4].item_string  = catgetlocal( 16, "print editor contents");
+       search_menu[0].item_string = catgetlocal( 17, "search menu");
+       search_menu[1].item_string = catgetlocal( 18, "search for ...");
+       search_menu[2].item_string = catgetlocal( 19, "search");
+       spell_menu[0].item_string = catgetlocal( 20, "spell menu");
+       spell_menu[1].item_string = catgetlocal( 21, "use 'spell'");
+       spell_menu[2].item_string = catgetlocal( 22, "use 'ispell'");
+       misc_menu[0].item_string = catgetlocal( 23, "miscellaneous menu");
+       misc_menu[1].item_string = catgetlocal( 24, "format paragraph");
+       misc_menu[2].item_string = catgetlocal( 25, "shell command");
+       misc_menu[3].item_string = catgetlocal( 26, "check spelling");
+       main_menu[0].item_string  = catgetlocal( 27, "main menu");
+       main_menu[1].item_string  = catgetlocal( 28, "leave editor");
+       main_menu[2].item_string  = catgetlocal( 29, "help");
+       main_menu[3].item_string  = catgetlocal( 30, "file operations");
+       main_menu[4].item_string  = catgetlocal( 31, "redraw screen");
+       main_menu[5].item_string  = catgetlocal( 32, "settings");
+       main_menu[6].item_string  = catgetlocal( 33, "search");
+       main_menu[7].item_string  = catgetlocal( 34, "miscellaneous");
+       help_text[0] = catgetlocal( 35, "Control keys:                                                              "); 
+       help_text[1] = catgetlocal( 36, "^a ascii code           ^i tab                  ^r right                   ");
+       help_text[2] = catgetlocal( 37, "^b bottom of text       ^j newline              ^t top of text             ");
+       help_text[3] = catgetlocal( 38, "^c command              ^k delete char          ^u up                      ");
+       help_text[4] = catgetlocal( 39, "^d down                 ^l left                 ^v undelete word           ");
+       help_text[5] = catgetlocal( 40, "^e search prompt        ^m newline              ^w delete word             ");
+       help_text[6] = catgetlocal( 41, "^f undelete char        ^n next page            ^x search                  ");
+       help_text[7] = catgetlocal( 42, "^g begin of line        ^o end of line          ^y delete line             ");
+       help_text[8] = catgetlocal( 43, "^h backspace            ^p prev page            ^z undelete line           ");
+       help_text[9] = catgetlocal( 44, "^[ (escape) menu        ESC-Enter: exit ee                                 ");
+       help_text[10] = catgetlocal( 45, "                                                                           ");
+       help_text[11] = catgetlocal( 46, "Commands:                                                                  ");
+       help_text[12] = catgetlocal( 47, "help    : get this info                 file    : print file name          ");
+       help_text[13] = catgetlocal( 48, "read    : read a file                   char    : ascii code of char       ");
+       help_text[14] = catgetlocal( 49, "write   : write a file                  case    : case sensitive search    ");
+       help_text[15] = catgetlocal( 50, "exit    : leave and save                nocase  : case insensitive search  ");
+       help_text[16] = catgetlocal( 51, "quit    : leave, no save                !cmd    : execute \"cmd\" in shell   ");
+       help_text[17] = catgetlocal( 52, "line    : display line #                0-9     : go to line \"#\"           ");
+       help_text[18] = catgetlocal( 53, "expand  : expand tabs                   noexpand: do not expand tabs         ");
+       help_text[19] = catgetlocal( 54, "                                                                             ");
+       help_text[20] = catgetlocal( 55, "  ee [+#] [-i] [-e] [-h] [file(s)]                                            ");
+       help_text[21] = catgetlocal( 56, "+# :go to line #  -i :no info window  -e : don't expand tabs  -h :no highlight");
+       control_keys[0] = catgetlocal( 57, "^[ (escape) menu  ^e search prompt  ^y delete line    ^u up     ^p prev page  ");
+       control_keys[1] = catgetlocal( 58, "^a ascii code     ^x search         ^z undelete line  ^d down   ^n next page  ");
+       control_keys[2] = catgetlocal( 59, "^b bottom of text ^g begin of line  ^w delete word    ^l left                 ");
+       control_keys[3] = catgetlocal( 60, "^t top of text    ^o end of line    ^v undelete word  ^r right                ");
+       control_keys[4] = catgetlocal( 61, "^c command        ^k delete char    ^f undelete char      ESC-Enter: exit ee  ");
+       command_strings[0] = catgetlocal( 62, "help : get help info  |file  : print file name         |line : print line # ");
+       command_strings[1] = catgetlocal( 63, "read : read a file    |char  : ascii code of char      |0-9 : go to line \"#\"");
+       command_strings[2] = catgetlocal( 64, "write: write a file   |case  : case sensitive search   |exit : leave and save ");
+       command_strings[3] = catgetlocal( 65, "!cmd : shell \"cmd\"    |nocase: ignore case in search   |quit : leave, no save");
+       command_strings[4] = catgetlocal( 66, "expand: expand tabs   |noexpand: do not expand tabs                           ");
+       com_win_message = catgetlocal( 67, "    press Escape (^[) for menu");
+       no_file_string = catgetlocal( 68, "no file");
+       ascii_code_str = catgetlocal( 69, "ascii code: ");
+       printer_msg_str = catgetlocal( 70, "sending contents of buffer to \"%s\" ");
+       command_str = catgetlocal( 71, "command: ");
+       file_write_prompt_str = catgetlocal( 72, "name of file to write: ");
+       file_read_prompt_str = catgetlocal( 73, "name of file to read: ");
+       char_str = catgetlocal( 74, "character = %d");
+       unkn_cmd_str = catgetlocal( 75, "unknown command \"%s\"");
+       non_unique_cmd_msg = catgetlocal( 76, "entered command is not unique");
+       line_num_str = catgetlocal( 77, "line %d  ");
+       line_len_str = catgetlocal( 78, "length = %d");
+       current_file_str = catgetlocal( 79, "current file is \"%s\" ");
+       usage0 = catgetlocal( 80, "usage: %s [-i] [-e] [-h] [+line_number] [file(s)]\n");
+       usage1 = catgetlocal( 81, "       -i   turn off info window\n");
+       usage2 = catgetlocal( 82, "       -e   do not convert tabs to spaces\n");
+       usage3 = catgetlocal( 83, "       -h   do not use highlighting\n");
+       file_is_dir_msg = catgetlocal( 84, "file \"%s\" is a directory");
+       new_file_msg = catgetlocal( 85, "new file \"%s\"");
+       cant_open_msg = catgetlocal( 86, "can't open \"%s\"");
+       open_file_msg = catgetlocal( 87, "file \"%s\", %d lines");
+       file_read_fin_msg = catgetlocal( 88, "finished reading file \"%s\"");
+       reading_file_msg = catgetlocal( 89, "reading file \"%s\"");
+       read_only_msg = catgetlocal( 90, ", read only");
+       file_read_lines_msg = catgetlocal( 91, "file \"%s\", %d lines");
+       save_file_name_prompt = catgetlocal( 92, "enter name of file: ");
+       file_not_saved_msg = catgetlocal( 93, "no filename entered: file not saved");
+       changes_made_prompt = catgetlocal( 94, "changes have been made, are you sure? (y/n [n]) ");
+       yes_char = catgetlocal( 95, "y");
+       file_exists_prompt = catgetlocal( 96, "file already exists, overwrite? (y/n) [n] ");
+       create_file_fail_msg = catgetlocal( 97, "unable to create file \"%s\"");
+       writing_file_msg = catgetlocal( 98, "writing file \"%s\"");
+       file_written_msg = catgetlocal( 99, "\"%s\" %d lines, %d characters");
+       searching_msg = catgetlocal( 100, "           ...searching");
+       str_not_found_msg = catgetlocal( 101, "string \"%s\" not found");
+       search_prompt_str = catgetlocal( 102, "search for: ");
+       exec_err_msg = catgetlocal( 103, "could not exec %s\n");
+       continue_msg = catgetlocal( 104, "press return to continue ");
+       menu_cancel_msg = catgetlocal( 105, "press Esc to cancel");
+       menu_size_err_msg = catgetlocal( 106, "menu too large for window");
+       press_any_key_msg = catgetlocal( 107, "press any key to continue ");
+       shell_prompt = catgetlocal( 108, "shell command: ");
+       formatting_msg = catgetlocal( 109, "...formatting paragraph...");
+       shell_echo_msg = catgetlocal( 110, "<!echo 'list of unrecognized words'; echo -=-=-=-=-=-");
+       spell_in_prog_msg = catgetlocal( 111, "sending contents of edit buffer to 'spell'");
+       margin_prompt = catgetlocal( 112, "right margin is: ");
+       restricted_msg = catgetlocal( 113, "restricted mode: unable to perform requested operation");
+       ON = catgetlocal( 114, "ON");
+       OFF = catgetlocal( 115, "OFF");
+       HELP = catgetlocal( 116, "HELP");
+       WRITE = catgetlocal( 117, "WRITE");
+       READ = catgetlocal( 118, "READ");
+       LINE = catgetlocal( 119, "LINE");
+       FILE_str = catgetlocal( 120, "FILE");
+       CHARACTER = catgetlocal( 121, "CHARACTER");
+       REDRAW = catgetlocal( 122, "REDRAW");
+       RESEQUENCE = catgetlocal( 123, "RESEQUENCE");
+       AUTHOR = catgetlocal( 124, "AUTHOR");
+       VERSION = catgetlocal( 125, "VERSION");
+       CASE = catgetlocal( 126, "CASE");
+       NOCASE = catgetlocal( 127, "NOCASE");
+       EXPAND = catgetlocal( 128, "EXPAND");
+       NOEXPAND = catgetlocal( 129, "NOEXPAND");
+       Exit_string = catgetlocal( 130, "EXIT");
+       QUIT_string = catgetlocal( 131, "QUIT");
+       INFO = catgetlocal( 132, "INFO");
+       NOINFO = catgetlocal( 133, "NOINFO");
+       MARGINS = catgetlocal( 134, "MARGINS");
+       NOMARGINS = catgetlocal( 135, "NOMARGINS");
+       AUTOFORMAT = catgetlocal( 136, "AUTOFORMAT");
+       NOAUTOFORMAT = catgetlocal( 137, "NOAUTOFORMAT");
+       Echo = catgetlocal( 138, "ECHO");
+       PRINTCOMMAND = catgetlocal( 139, "PRINTCOMMAND");
+       RIGHTMARGIN = catgetlocal( 140, "RIGHTMARGIN");
+       HIGHLIGHT = catgetlocal( 141, "HIGHLIGHT");
+       NOHIGHLIGHT = catgetlocal( 142, "NOHIGHLIGHT");
+       EIGHTBIT = catgetlocal( 143, "EIGHTBIT");
+       NOEIGHTBIT = catgetlocal( 144, "NOEIGHTBIT");
+       /*
+        |      additions
+        */
+       mode_strings[7] = catgetlocal( 145, "emacs key bindings   ");
+       emacs_help_text[0] = help_text[0];
+       emacs_help_text[1] = catgetlocal( 146, "^a beginning of line    ^i tab                  ^r restore word            ");
+       emacs_help_text[2] = catgetlocal( 147, "^b back 1 char          ^j undel char           ^t top of text             ");
+       emacs_help_text[3] = catgetlocal( 148, "^c command              ^k delete line          ^u bottom of text          ");
+       emacs_help_text[4] = catgetlocal( 149, "^d delete char          ^l undelete line        ^v next page               ");
+       emacs_help_text[5] = catgetlocal( 150, "^e end of line          ^m newline              ^w delete word             ");
+       emacs_help_text[6] = catgetlocal( 151, "^f forward 1 char       ^n next line            ^x search                  ");
+       emacs_help_text[7] = catgetlocal( 152, "^g go back 1 page       ^o ascii char insert    ^y search prompt           ");
+       emacs_help_text[8] = catgetlocal( 153, "^h backspace            ^p prev line            ^z next word               ");
+       emacs_help_text[9] = help_text[9];
+       emacs_help_text[10] = help_text[10];
+       emacs_help_text[11] = help_text[11];
+       emacs_help_text[12] = help_text[12];
+       emacs_help_text[13] = help_text[13];
+       emacs_help_text[14] = help_text[14];
+       emacs_help_text[15] = help_text[15];
+       emacs_help_text[16] = help_text[16];
+       emacs_help_text[17] = help_text[17];
+       emacs_help_text[18] = help_text[18];
+       emacs_help_text[19] = help_text[19];
+       emacs_help_text[20] = help_text[20];
+       emacs_help_text[21] = help_text[21];
+       emacs_control_keys[0] = catgetlocal( 154, "^[ (escape) menu ^y search prompt ^k delete line   ^p prev li     ^g prev page");
+       emacs_control_keys[1] = catgetlocal( 155, "^o ascii code    ^x search        ^l undelete line ^n next li     ^v next page");
+       emacs_control_keys[2] = catgetlocal( 156, "^u end of file   ^a begin of line ^w delete word   ^b back 1 char ^z next word");
+       emacs_control_keys[3] = catgetlocal( 157, "^t top of text   ^e end of line   ^r restore word  ^f forward char            ");
+       emacs_control_keys[4] = catgetlocal( 158, "^c command       ^d delete char   ^j undelete char              ESC-Enter: exit");
+       EMACS_string = catgetlocal( 159, "EMACS");
+       NOEMACS_string = catgetlocal( 160, "NOEMACS");
+       usage4 = catgetlocal( 161, "       +#   put cursor at line #\n");
+       conf_dump_err_msg = catgetlocal( 162, "unable to open .init.ee for writing, no configuration saved!");
+       conf_dump_success_msg = catgetlocal( 163, "ee configuration saved in file %s");
+       modes_menu[10].item_string = catgetlocal( 164, "save editor configuration");
+       config_dump_menu[0].item_string = catgetlocal( 165, "save ee configuration");
+       config_dump_menu[1].item_string = catgetlocal( 166, "save in current directory");
+       config_dump_menu[2].item_string = catgetlocal( 167, "save in home directory");
+       conf_not_saved_msg = catgetlocal( 168, "ee configuration not saved");
+       ree_no_file_msg = catgetlocal( 169, "must specify a file when invoking ree");
+       menu_too_lrg_msg = catgetlocal( 180, "menu too large for window");
+       more_above_str = catgetlocal( 181, "^^more^^");
+       more_below_str = catgetlocal( 182, "VVmoreVV");
+       mode_strings[9] = catgetlocal( 183, "16 bit characters    ");
+       chinese_cmd = catgetlocal( 184, "16BIT");
+       nochinese_cmd = catgetlocal( 185, "NO16BIT");
+
+       commands[0] = HELP;
+       commands[1] = WRITE;
+       commands[2] = READ;
+       commands[3] = LINE;
+       commands[4] = FILE_str;
+       commands[5] = REDRAW;
+       commands[6] = RESEQUENCE;
+       commands[7] = AUTHOR;
+       commands[8] = VERSION;
+       commands[9] = CASE;
+       commands[10] = NOCASE;
+       commands[11] = EXPAND;
+       commands[12] = NOEXPAND;
+       commands[13] = Exit_string;
+       commands[14] = QUIT_string;
+       commands[15] = "<";
+       commands[16] = ">";
+       commands[17] = "!";
+       commands[18] = "0";
+       commands[19] = "1";
+       commands[20] = "2";
+       commands[21] = "3";
+       commands[22] = "4";
+       commands[23] = "5";
+       commands[24] = "6";
+       commands[25] = "7";
+       commands[26] = "8";
+       commands[27] = "9";
+       commands[28] = CHARACTER;
+       commands[29] = chinese_cmd;
+       commands[30] = nochinese_cmd;
+       commands[31] = NULL;
+       init_strings[0] = CASE;
+       init_strings[1] = NOCASE;
+       init_strings[2] = EXPAND;
+       init_strings[3] = NOEXPAND;
+       init_strings[4] = INFO;
+       init_strings[5] = NOINFO;
+       init_strings[6] = MARGINS;
+       init_strings[7] = NOMARGINS;
+       init_strings[8] = AUTOFORMAT;
+       init_strings[9] = NOAUTOFORMAT;
+       init_strings[10] = Echo;
+       init_strings[11] = PRINTCOMMAND;
+       init_strings[12] = RIGHTMARGIN;
+       init_strings[13] = HIGHLIGHT;
+       init_strings[14] = NOHIGHLIGHT;
+       init_strings[15] = EIGHTBIT;
+       init_strings[16] = NOEIGHTBIT;
+       init_strings[17] = EMACS_string;
+       init_strings[18] = NOEMACS_string;
+       init_strings[19] = chinese_cmd;
+       init_strings[20] = nochinese_cmd;
+       init_strings[21] = NULL;
+
+       /*
+        |      allocate space for strings here for settings menu
+        */
+
+       for (counter = 1; counter < NUM_MODES_ITEMS; counter++)
+       {
+               modes_menu[counter].item_string = malloc(80);
+       }
+
+#ifndef NO_CATGETS
+       catclose(catalog);
+#endif /* NO_CATGETS */
+}
+
diff --git a/contrib/ee/ee.i18n.guide b/contrib/ee/ee.i18n.guide
new file mode 100644 (file)
index 0000000..eef836a
--- /dev/null
@@ -0,0 +1,158 @@
+Easy Editor ("ee") provides the ability to translate the messages 
+displayed to the user and the commands entered.  This is done via message 
+catalogs, following X/Open standards.  ee supports eight bit characters, 
+as well as 16-bit characters.  The Chinese Big 5 code set is the 16-bit 
+code set that ee was modified to handle, as it is relatively easy to 
+support since two byte characters also take up two columns on the screen, 
+thereby simplifying the screen position calculations.  Other multibyte 
+code sets may function, but have not been tested. 
+
+(The name ee.i18n.guide is for "ee internationalization guide".  The i18n 
+abbreviation is used because there are 18 characters between the first 
+letter ("i") and last ("n") of "internationalization".) 
+
+All of the messages, warnings, information, and commands, are contained 
+in the message catalog.  Each numbered entry represents an individual 
+string used by ee.  Some strings contain formatting information for 
+formatted print statements, which are of the form "%s", or "%d", these 
+must be preserved in the translation, or the correct information will not 
+be displayed.  For those strings containing multiple formatting codes, 
+the order of each item must be preserved as well. 
+
+Message                content 
+1              title for modes, or settings menu
+2 - 8          entries for modes menu, each line should be the same length 
+                (padded with spaces)
+9 - 34         other menu titles and entries
+35 - 56        help screen 
+57 - 61        actions assigned to control keys 
+62 - 66        commands information 
+67             message displayed when info window turned off
+68             indication that no file name was entered when invoking ee
+69             prompt for decimal value of character to be entered
+70             message displaying the print command being invoked
+71             prompt for command 
+72             prompt for name of file to be written 
+73             prompt for name of file to be read 
+74             string used to display the decimal value of the character 
+                the cursor is on 
+75             string displaying an unrecognized command 
+76             string indicating that the command entered is not a unique 
+                substring of a valid command
+77             string indicating the current line number 
+78             string for displaying the length of the line 
+79             string for displaying the name of the file 
+80 - 83                strings showing how to invoke ee, and its options
+84             message indicating that the file entered is a directory, not a 
+                text file
+85             message informing that the entered file does not yet exist 
+86             message informing that the file can't be opened (because of 
+                permission problems)
+87             message after file has been read with the file name and number 
+                of lines read
+88             message indicating that the file has been read
+89             message indicating that the file is being read
+90             message indicating that permissions only allow the file to be 
+                read, not written
+91             message after file has been read with the file name and number 
+                of lines read
+92             prompt for name of file to be saved (used when no name was 
+                entered for a file to edit)
+93             message indicating that the file was not written, since no 
+                name was entered at the prompt
+94             prompt asking user if changes should not be saved ("yes_char" 
+                will be expected for affirmative response)
+95             "yes" character, single character expected to confirm action 
+                (can be upper or lower case, will be converted to upper-case 
+                during test)
+96             prompt
+97             error message
+98             message indicating that the named file is being written
+99             message indicating the name of the file written, the number of 
+                lines, and the number of characters (order of items must be 
+                maintained)
+100            search in progress message
+101            message that the string was not found
+102            prompt for search
+103            message that string could not be executed
+104            self-explanatory
+105            message for menus, indicating that the Escape character will 
+                allow the user to exit the menu
+106            error message indicating the menu won't fit on the screen
+107            self-explanatory
+108            prompt for shell command
+109            message displayed while formatting a paragraph
+110            string which places message for spell checking at top of 
+                buffer (the portions 'list of unrecognized words' and 
+                '-=-=-=-=-=-' may be replaced, but the rest must remain the 
+                same)
+111            message informing that spell checking is in progress
+112            prompt for right margin
+113            error informing user that operation is not permitted in ree
+114            string indicating mode is turned 'on' in modes menu
+115            string indicating mode is turned 'off' in modes menu
+116 - 131      strings used for commands (some also used for initialization)
+132 - 144      strings used for initialization
+145            entry for settings menu for emacs key bindings settings
+146 - 153      help screen entries for emacs key bindings info
+154 - 158      info window entries for emacs key bindings info
+159            string for turning on emacs key bindings in the init file
+160            string for turning off emacs key bindings in the init file
+161            fifth line of usage statement
+162            error message when unable to save configuration file
+163            positive feedback about saving the configuration file
+164 - 167      menu items for saving editor configuration
+168            error message when unable to save configuration file
+169            error message for ree when not specifying the file
+180            self-explanatory
+181 - 182      indicators of more information in menu (for when scrolling 
+                menus because menu contents won't fit vertically on screen)
+183            menu entry for modes menu for 16 bit characters
+184 - 185      strings for initialization to turn on or off 16 bit 
+               character handling
+
+Care should be taken when translating commands and initialization keywords 
+because the algorithm used for detecting uniqueness of entered commands 
+will not be able to distinguish words that are not unique before the end 
+of the shorter word, for example, it would not be able to distinguish the 
+command 'abcd' from 'abcde'.
+
+After translating the messages, use the 'gencat' command to create the compiled 
+catalog used when running the software.  The standard syntax would be:
+
+       gencat ee.cat ee.msg
+
+Where ee.msg is the file containing the translations, and ee.cat is the 
+compiled catalog.  If the file ee.cat does not exist, it will be created.  
+Check the documentation for your system for proper syntax.  
+
+Message catalog placement varies from system to system.  A common location 
+for message catalogs is in /usr/lib/nls.  In this directory are 
+directories with the names of other languages.  The default language is 
+'C'.  There is also an environment variable, named NLSPATH used to 
+determine where message catalogs can be found.  This variable is similar 
+to the PATH variable used for commands, but with some differences.  The 
+NLSPATH variable must have the ability to handle different names for 
+languages and the catalog files, so it has field descriptors for these.  A 
+typical setting for NLSPATH could be:
+
+       NLSPATH=/usr/lib/nls/%L/%N.cat:/usr/local/lib/nls/%L/%N.cat
+
+Where "%L" is the field descriptor for the language (obtained from the 
+LANG environment variable) and "%N" is the name of the file (with the 
+".cat" appended by the path variable, it is not passed from the requesting 
+program).  The colon (:) is used to separate paths, so in the above 
+example there are two paths possible for message catalogs.  You may wish 
+to maintain catalogs for applications that are not supported by your 
+system vendor in a location unique for you, and this is facilitated by the 
+NLSPATH variable.  Remember to set and export both the LANG and NLSPATH 
+variables for each user that expects to use localization either in a 
+system-wide profile or in each user's profile.  See your system 
+documentation for more information.
+
+The message catalog supplied with ee also uses the '$quote' directive to 
+specify a quote around strings to ensure proper padding.  This directive 
+may not be supported on all systems, and lead to quotes being included in 
+the string used in ee, which will cause incorrect behavior.  If the 
+'$quote' directive is not supported by your system's gencat command, edit 
+the msg file to remove the leading and trailing quotation marks.
diff --git a/contrib/ee/ee.msg b/contrib/ee/ee.msg
new file mode 100644 (file)
index 0000000..f7c209c
--- /dev/null
@@ -0,0 +1,185 @@
+$ This file contains the messages for ee ("easy editor").  See the file 
+$ ee.i18n.guide for more information
+$ 
+$ For ee patchlevel 3
+$ 
+$ $Header: /home/hugh/sources/old_ae/RCS/ee.msg,v 1.8 1996/11/30 03:23:40 hugh Exp $
+$ 
+$ 
+$set 1
+$quote "
+1 "modes menu"
+2 "tabs to spaces       " 
+3 "case sensitive search" 
+4 "margins observed     " 
+5 "auto-paragraph format" 
+6 "eightbit characters  " 
+7 "info window          " 
+8 "right margin         "
+9 "leave menu"
+10 "save changes"
+11 "no save"
+12 "file menu"
+13 "read a file"
+14 "write a file"
+15 "save file"
+16 "print editor contents"
+17 "search menu"
+18 "search for ..."
+19 "search"
+20 "spell menu"
+21 "use 'spell'"
+22 "use 'ispell'"
+23 "miscellaneous menu"
+24 "format paragraph"
+25 "shell command"
+26 "check spelling"
+27 "main menu"
+28 "leave editor"
+29 "help"
+30 "file operations"
+31 "redraw screen"
+32 "settings"
+33 "search"
+34 "miscellaneous"
+35 "Control keys:                                                              " 
+36 "^a ascii code           ^i tab                  ^r right                   "
+37 "^b bottom of text       ^j newline              ^t top of text             "
+38 "^c command              ^k delete char          ^u up                      "
+39 "^d down                 ^l left                 ^v undelete word           "
+40 "^e search prompt        ^m newline              ^w delete word             "
+41 "^f undelete char        ^n next page            ^x search                  "
+42 "^g begin of line        ^o end of line          ^y delete line             "
+43 "^h backspace            ^p prev page            ^z undelete line           "
+44 "^[ (escape) menu                                                           "
+45 "                                                                           "
+46 "Commands:                                                                  "
+47 "help    : get this info                 file    : print file name          "
+48 "read    : read a file                   char    : ascii code of char       "
+49 "write   : write a file                  case    : case sensitive search    "
+50 "exit    : leave and save                nocase  : case insensitive search  "
+51 "quit    : leave, no save                !cmd    : execute \"cmd\" in shell   "
+52 "line    : display line #                0-9     : go to line \"#\"           "
+53 "expand  : expand tabs                   noexpand: do not expand tabs         "
+54 "                                                                             "
+55 "  ee [+#] [-i] [-e] [-h] [file(s)]                                            "
+56 "+# :go to line #  -i :no info window  -e : don't expand tabs  -h :no highlight"
+57 "^[ (escape) menu  ^e search prompt  ^y delete line    ^u up     ^p prev page  "
+58 "^a ascii code     ^x search         ^z undelete line  ^d down   ^n next page  "
+59 "^b bottom of text ^g begin of line  ^w delete word    ^l left                 "
+60 "^t top of text    ^o end of line    ^v undelete word  ^r right                "
+61 "^c command        ^k delete char    ^f undelete char                          "
+62 "help : get help info  |file  : print file name         |line : print line # "
+63 "read : read a file    |char  : ascii code of char      |0-9 : go to line \"#\""
+64 "write: write a file   |case  : case sensitive search   |exit : leave and save "
+65 "!cmd : shell \"cmd\"    |nocase: ignore case in search   |quit : leave, no save"
+66 "expand: expand tabs   |noexpand: do not expand tabs                           "
+67 "    press Escape (^[) for menu"
+68 "no file"
+69 "ascii code: "
+70 "sending contents of buffer to \"%s\" "
+71 "command: "
+72 "name of file to write: "
+73 "name of file to read: "
+74 "character = %d"
+75 "unknown command \"%s\""
+76 "entered command is not unique"
+77 "line %d  "
+78 "length = %d"
+79 "current file is \"%s\" "
+80 "usage: %s [-i] [-e] [-h] [+line_number] [file(s)]\n"
+81 "       -i   turn off info window\n"
+82 "       -e   do not convert tabs to spaces\n"
+83 "       -h   do not use highlighting\n"
+84 "file \"%s\" is a directory"
+85 "new file \"%s\""
+86 "can't open \"%s\""
+87 "file \"%s\", %d lines"
+88 "finished reading file \"%s\""
+89 "reading file \"%s\""
+90 ", read only"
+91 "file \"%s\", %d lines"
+92 "enter name of file: "
+93 "no filename entered: file not saved"
+94 "changes have been made, are you sure? (y/n [n]) "
+95 "y"
+96 "file already exists, overwrite? (y/n) [n] "
+97 "unable to create file \"%s\""
+98 "writing file \"%s\""
+99 "\"%s\" %d lines, %d characters"
+100 "           ...searching"
+101 "string \"%s\" not found"
+102 "search for: "
+103 "could not exec %s\n"
+104 "press return to continue "
+105 "press Esc to cancel"
+106 "menu too large for window"
+107 "press any key to continue "
+108 "shell command: "
+109 "...formatting paragraph..."
+110 "<!echo 'list of unrecognized words'; echo -=-=-=-=-=-"
+111 "sending contents of edit buffer to 'spell'"
+112 "right margin is: "
+113 "restricted mode: unable to perform requested operation"
+114 "ON"
+115 "OFF"
+116 "HELP"
+117 "WRITE"
+118 "READ"
+119 "LINE"
+120 "FILE"
+121 "CHARACTER"
+122 "REDRAW"
+123 "RESEQUENCE"
+124 "AUTHOR"
+125 "VERSION"
+126 "CASE"
+127 "NOCASE"
+128 "EXPAND"
+129 "NOEXPAND"
+130 "EXIT"
+131 "QUIT"
+132 "INFO"
+133 "NOINFO"
+134 "MARGINS"
+135 "NOMARGINS"
+136 "AUTOFORMAT"
+137 "NOAUTOFORMAT"
+138 "ECHO"
+139 "PRINTCOMMAND"
+140 "RIGHTMARGIN"
+141 "HIGHLIGHT"
+142 "NOHIGHLIGHT"
+143 "EIGHTBIT"
+144 "NOEIGHTBIT"
+145 "emacs key bindings   "
+146 "^a beginning of line    ^i tab                  ^r restore word            "
+147 "^b back 1 char          ^j undel char           ^t top of text             "
+148 "^c command              ^k delete line          ^u bottom of text          "
+149 "^d delete char          ^l undelete line        ^v next page               "
+150 "^e end of line          ^m newline              ^w delete word             "
+151 "^f forward 1 char       ^n next line            ^x search                  "
+152 "^g go back 1 page       ^o ascii char insert    ^y search prompt           "
+153 "^h backspace            ^p prev line            ^z next word               "
+154 "^[ (escape) menu  ^y search prompt  ^k delete line   ^p prev li   ^g prev page"
+155 "^o ascii code     ^x search         ^l undelete line ^n next li   ^v next page"
+156 "^u end of file    ^a begin of line  ^w delete word   ^b back 1 char           "
+157 "^t top of text    ^e end of line    ^r restore word  ^f forward 1 char        "
+158 "^c command        ^d delete char    ^j undelete char ^z next word              "
+159 "EMACS"
+160 "NOEMACS"
+161 "       +#   put cursor at line #\n"
+162 "unable to open .init.ee for writing, no configuration saved!"
+163 "ee configuration saved in file %s"
+164 "save editor configuration"
+165 "save ee configuration"
+166 "save in current directory"
+167 "save in home directory"
+168 "ee configuration not saved"
+169 "must specify a file when invoking ree"
+180 "menu too large for window"
+181 "^^more^^"
+182 "VVmoreVV"
+183 "16 bit characters    "
+184 "16BIT"
+185 "NO16BIT"
diff --git a/contrib/ee/ee_version.h b/contrib/ee/ee_version.h
new file mode 100644 (file)
index 0000000..c2db839
--- /dev/null
@@ -0,0 +1,6 @@
+/*
+ |     provide a version number for ee
+ */
+
+#define EE_VERSION "1.5.2"
+#define DATE_STRING "$Date: 2010/06/04 02:35:35 $"
diff --git a/contrib/ee/genstr b/contrib/ee/genstr
new file mode 100755 (executable)
index 0000000..429f960
--- /dev/null
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+set -x
+
+if [ $# -lt 2 ]
+then
+       echo usage $0 source_file dest_file 
+       exit 1
+fi
+
+trap 'rm -f /tmp/$$.out; exit 0' 0           # set up traps to clean up
+trap 'rm -f /tmp/$$.out; exit 1' 1 2 3 15    # on errors AND normal exit
+
+if [ -f $2 ]
+then
+       rm $2
+fi
+
+cat $1 | grep 'catgetlocal.*\"*\"' | 
+       sed -e 's/^.*catgetlocal(//' | 
+       sed -e 's/^[    ]*//'   |
+       sed -e 's/, \"/ \"/'    |
+       sed -e 's/);//' > /tmp/$$.out
+
+cat > $2 <<EOF
+\$ 
+\$ 
+\$set 1
+\$quote "
+EOF
+
+sort -n < /tmp/$$.out >> $2
diff --git a/contrib/ee/make.default b/contrib/ee/make.default
new file mode 100644 (file)
index 0000000..32ff05d
--- /dev/null
@@ -0,0 +1,57 @@
+# This is the make file for ee, the "easy editor".
+#
+# If building ee using curses, type "make curses", otherwise new_curse (a 
+# subset of curses that supports ee) will be built and ee will use new_curse 
+# instead of curses.
+#
+# The "install" target ("make install") will copy the ee binary to 
+# the /usr/local/bin directory on the local system.  The man page (ee.1) 
+# will be copied into the /usr/local/man/man1 directory.
+#
+# The "clean" target ("make clean") will remove the ee and new_curse.o 
+# object files, and the ee binary.
+#
+# If the system does not have localization routines, use the -DNO_CATGETS
+# define.  If the system supports setlocale(), catopen(), and catgets() and 
+# localization is desired, do not use -DNO_CATGETS.
+#
+# DEFINES is used for new_curse.c, and CFLAGS is used for ee.c.
+#
+
+# for System V, using new_curse with terminfo
+DEFINES =      -DSYS5 -DNCURSE 
+
+# for BSD, using new_curse with termcap
+#DEFINES =     -DCAP -DNCURSE 
+
+# for BSD systems with select(), using new_curse with termcap, use:
+#DEFINES =      -DCAP -DNCURSE -DBSD_SELECT 
+
+# flags for compilation
+CFLAGS = -s -DNO_CATGETS
+
+# For Sun systems, remove the '#' from the front of the next two lines:
+#DEFINES = -DSYS5 -DNCURSE 
+#CFLAGS  = -I/usr/5include -L/usr/5lib -DNO_CATGETS -s
+
+all :  ee
+
+curses :       ee.c
+       cc ee.c -o ee $(CFLAGS) -lcurses 
+
+ee :   ee.o new_curse.o
+       cc -o ee ee.o new_curse.o $(CFLAGS) 
+
+ee.o : ee.c new_curse.h
+       cc -c ee.c $(DEFINES) $(CFLAGS) 
+
+new_curse.o :  new_curse.c new_curse.h
+       cc new_curse.c -c $(DEFINES) $(CFLAGS)
+
+install :
+       cp ee /usr/local/bin/ee
+       cp ee.1 /usr/local/man/man1/ee.1
+
+clean :
+       rm -f ee.o new_curse.o ee 
+
diff --git a/contrib/ee/new_curse.c b/contrib/ee/new_curse.c
new file mode 100644 (file)
index 0000000..5ceec24
--- /dev/null
@@ -0,0 +1,3819 @@
+/*
+ |     new_curse.c
+ |
+ |     A subset of curses developed for use with ae.
+ |
+ |     written by Hugh Mahon
+ |
+ |      Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995, 2009 Hugh Mahon
+ |      All rights reserved.
+ |      
+ |      Redistribution and use in source and binary forms, with or without
+ |      modification, are permitted provided that the following conditions
+ |      are met:
+ |      
+ |          * Redistributions of source code must retain the above copyright
+ |            notice, this list of conditions and the following disclaimer.
+ |          * Redistributions in binary form must reproduce the above
+ |            copyright notice, this list of conditions and the following
+ |            disclaimer in the documentation and/or other materials provided
+ |            with the distribution.
+ |      
+ |      THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ |      "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ |      LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ |      FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ |      COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ |      INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ |      BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ |      LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ |      CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ |      LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ |      ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ |      POSSIBILITY OF SUCH DAMAGE.
+ |
+ |     
+ |     All are rights reserved.
+ |
+ |     $Header: /home/hugh/sources/old_ae/RCS/new_curse.c,v 1.54 2002/09/21 00:47:14 hugh Exp $
+ |
+ */
+
+char *copyright_message[] = { "Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995, 2009 Hugh Mahon",
+                               "All rights are reserved."};
+
+char * new_curse_name= "@(#) new_curse.c $Revision: 1.54 $";
+
+#include "new_curse.h"
+#include <signal.h>
+#include <fcntl.h>
+
+#ifdef SYS5
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+#ifdef BSD_SELECT
+#include <sys/types.h>
+#include <sys/time.h>
+
+#ifdef SLCT_HDR
+#include <sys/select.h>  /* on AIX */
+#endif /* SLCT_HDR */
+
+#endif /* BSD_SELECT */
+
+#ifdef HAS_STDLIB
+#include <stdlib.h>
+#endif
+
+#if defined(__STDC__)
+#include <stdarg.h>
+#else
+#include <varargs.h>
+#endif
+
+#ifdef HAS_UNISTD
+#include <unistd.h>
+#endif
+
+#ifdef HAS_SYS_IOCTL
+#include <sys/ioctl.h>
+#endif
+
+
+WINDOW *curscr;
+static WINDOW *virtual_scr;
+WINDOW *stdscr;
+WINDOW *last_window_refreshed;
+
+#ifdef TIOCGWINSZ
+       struct winsize ws;
+#endif
+
+#define min(a, b)      (a < b ? a : b)
+#define highbitset(a)  ((a) & 0x80)
+
+#ifndef CAP
+#define String_Out(table, stack, place) Info_Out(table, stack, place)
+#else
+#define String_Out(table, stack, place) Cap_Out(table, stack, place)
+#endif
+
+#define bw__ 0 /* booleans     */
+#define am__ 1
+#define xb__ 2
+#define xs__ 3 /* hp glitch (standout not erased by overwrite) */
+#define xn__ 4
+#define eo__ 5
+#define gn__ 6 /* generic type terminal        */
+#define hc__ 7 /* hardcopy terminal            */
+#define km__ 8
+#define hs__ 9
+#define in__ 10
+#define da__ 11
+#define db__ 12
+#define mi__ 13        /* safe to move during insert mode      */
+#define ms__ 14        /* safe to move during standout mode    */
+#define os__ 15
+#define es__ 16
+#define xt__ 17
+#define hz__ 18        /* hazeltine glitch     */
+#define ul__ 19
+#define xo__ 20
+#define chts__ 21
+#define nxon__ 22
+#define nrrmc__ 23
+#define npc__ 24
+#define mc5i__ 25
+
+#define co__ 0 /* number of columns    */      /* numbers              */
+#define it__ 1 /* spaces per tab       */
+#define li__ 2 /* number of lines      */
+#define lm__ 3
+#define sg__ 4 /* magic cookie glitch  */
+#define pb__ 5
+#define vt__ 6
+#define ws__ 7
+
+#define cols__ 0
+#define lines__ 2
+#define xmc__ 4
+#define vt__ 6
+#define wsl__ 7
+#define nlab__ 8
+#define lh__ 9
+#define lw__ 10
+
+#define bt__ 0 /* back tab             */      /* strings      */
+#define bl__ 1 /* bell                 */
+#define cr__ 2 /* carriage return      */
+#define cs__ 3 /* change scroll region */
+#define ct__ 4 /* clear all tab stops  */
+#define cl__ 5 /* clear screen and home cursor */
+#define ce__ 6 /* clear to end of line */
+#define cd__ 7 /* clear to end of display      */
+#define ch__ 8 /* set cursor column    */
+#define CC__ 9 /* term, settable cmd char in   */
+#define cm__ 10        /* screen rel cursor motion, row, column        */
+#define do__ 11        /* down one line        */
+#define ho__ 12        /* home cursor  */
+#define vi__ 13        /* make cursor invisible        */
+#define le__ 14        /* move cursor left one space   */
+#define CM__ 15        /* memory rel cursor addressing */
+#define ve__ 16        /* make cursor appear normal    */
+#define nd__ 17        /* non-destructive space (cursor right) */
+#define ll__ 18        /* last line, first col */
+#define up__ 19        /* cursor up            */
+#define vs__ 20
+#define dc__ 21        /* delete character     */
+#define dl__ 22        /* delete line          */
+#define ds__ 23
+#define hd__ 24
+#define as__ 25
+#define mb__ 26
+#define md__ 27        /* turn on bold         */
+#define ti__ 28
+#define dm__ 29        /* turn on delete mode  */
+#define mh__ 30        /* half bright mode     */
+#define im__ 31        /* insert mode          */
+#define mk__ 32
+#define mp__ 33
+#define mr__ 34
+#define so__ 35        /* enter standout mode  */
+#define us__ 36
+#define ec__ 37
+#define ae__ 38
+#define me__ 39
+#define te__ 40
+#define ed__ 41
+#define ei__ 42        /* exit insert mode     */
+#define se__ 43        /* exit standout mode   */
+#define ue__ 44
+#define vb__ 45
+#define ff__ 46
+#define fs__ 47
+#define i1__ 48
+#define i2__ 49
+#define i3__ 50
+#define if__ 51
+#define ic__ 52
+#define al__ 53
+#define ip__ 54
+#define kb__ 55                /* backspace key        */
+#define ka__ 56
+#define kC__ 57
+#define kt__ 58
+#define kD__ 59
+#define kL__ 60
+#define kd__ 61
+#define kM__ 62
+#define kE__ 63
+#define kS__ 64
+#define k0__ 65
+#define k1__ 66
+#define kf10__ 67
+#define k2__ 68
+#define k3__ 69
+#define k4__ 70
+#define k5__ 71
+#define k6__ 72
+#define k7__ 73
+#define k8__ 74
+#define k9__ 75
+#define kh__ 76
+#define kI__ 77
+#define kA__ 78
+#define kl__ 79
+#define kH__ 80
+#define kN__ 81
+#define kP__ 82
+#define kr__ 83
+#define kF__ 84
+#define kR__ 85
+#define kT__ 86
+#define ku__ 87        /* key up       */
+#define ke__ 88
+#define ks__ 89
+#define l0__ 90
+#define l1__ 91
+#define la__ 92
+#define l2__ 93
+#define l3__ 94
+#define l4__ 95
+#define l5__ 96
+#define l6__ 97
+#define l7__ 98
+#define l8__ 99
+#define l9__ 100
+#define mo__ 101
+#define mm__ 102
+#define nw__ 103
+#define pc__ 104
+#define DC__ 105
+#define DL__ 106
+#define DO__ 107
+#define IC__ 118
+#define SF__ 109
+#define AL__ 110
+#define LE__ 111
+#define RI__ 112
+#define SR__ 113
+#define UP__ 114
+#define pk__ 115
+#define pl__ 116
+#define px__ 117
+#define ps__ 118
+#define pf__ 119
+#define po__ 120
+#define rp__ 121
+#define r1__ 122
+#define r2__ 123
+#define r3__ 124
+#define rf__ 125
+#define rc__ 126
+#define cv__ 127
+#define sc__ 128
+#define sf__ 129
+#define sr__ 130
+#define sa__ 131       /* sgr  */
+#define st__ 132
+#define wi__ 133
+#define ta__ 134
+#define ts__ 135
+#define uc__ 136
+#define hu__ 137
+#define iP__ 138
+#define K1__ 139
+#define K2__ 140
+#define K3__ 141
+#define K4__ 142
+#define K5__ 143
+#define pO__ 144
+#define ml__ 145
+#define mu__ 146
+#define rmp__ 145
+#define acsc__ 146
+#define pln__ 147
+#define kcbt__ 148
+#define smxon__ 149
+#define rmxon__ 150
+#define smam__ 151
+#define rmam__ 152
+#define xonc__ 153
+#define xoffc__ 154
+#define enacs__ 155
+#define smln__ 156
+#define rmln__ 157
+#define kbeg__ 158
+#define kcan__ 159
+#define kclo__ 160
+#define kcmd__ 161
+#define kcpy__ 162
+#define kcrt__ 163
+#define kend__ 164
+#define kent__ 165
+#define kext__ 166
+#define kfnd__ 167
+#define khlp__ 168
+#define kmrk__ 169
+#define kmsg__ 170
+#define kmov__ 171
+#define knxt__ 172
+#define kopn__ 173
+#define kopt__ 174
+#define kprv__ 175
+#define kprt__ 176
+#define krdo__ 177
+#define kref__ 178
+#define krfr__ 179
+#define krpl__ 180
+#define krst__ 181
+#define kres__ 182
+#define ksav__ 183
+#define kspd__ 184
+#define kund__ 185
+#define kBEG__ 186
+#define kCAN__ 187
+#define kCMD__ 188
+#define kCPY__ 189
+#define kCRT__ 190
+#define kDC__ 191
+#define kDL__ 192
+#define kslt__ 193
+#define kEND__ 194
+#define kEOL__ 195
+#define kEXT__ 196
+#define kFND__ 197
+#define kHLP__ 198
+#define kHOM__ 199
+#define kIC__ 200
+#define kLFT__ 201
+#define kMSG__ 202
+#define kMOV__ 203
+#define kNXT__ 204
+#define kOPT__ 205
+#define kPRV__ 206
+#define kPRT__ 207
+#define kRDO__ 208
+#define kRPL__ 209
+#define kRIT__ 210
+#define kRES__ 211
+#define kSAV__ 212
+#define kSPD__ 213
+#define kUND__ 214
+#define rfi__ 215
+#define kf11__ 216
+#define kf12__ 217
+#define kf13__ 218
+#define kf14__ 219
+#define kf15__ 220
+#define kf16__ 221
+#define kf17__ 222
+#define kf18__ 223
+#define kf19__ 224
+#define kf20__ 225
+#define kf21__ 226
+#define kf22__ 227
+#define kf23__ 228
+#define kf24__ 229
+#define kf25__ 230
+#define kf26__ 231
+#define kf27__ 232
+#define kf28__ 233
+#define kf29__ 234
+#define kf30__ 235
+#define kf31__ 236
+#define kf32__ 237
+#define kf33__ 238
+#define kf34__ 239
+#define kf35__ 240
+#define kf36__ 241
+#define kf37__ 242
+#define kf38__ 243
+#define kf39__ 244
+#define kf40__ 245
+#define kf41__ 246
+#define kf42__ 247
+#define kf43__ 248
+#define kf44__ 249
+#define kf45__ 250
+#define kf46__ 251
+#define kf47__ 252
+#define kf48__ 253
+#define kf49__ 254
+#define kf50__ 255
+#define kf51__ 256
+#define kf52__ 257
+#define kf53__ 258
+#define kf54__ 259
+#define kf55__ 260
+#define kf56__ 261
+#define kf57__ 262
+#define kf58__ 263
+#define kf59__ 264
+#define kf60__ 265
+#define kf61__ 266
+#define kf62__ 267
+#define kf63__ 268
+#define el1__ 269
+#define mgc__ 270
+#define smgl__ 271
+#define smgr__ 272
+
+#ifdef CAP
+char *Boolean_names[] = {
+"bw", "am", "xb", "xs", "xn", "eo", "gn", "hc", "km", "hs", "in", "da", "db", 
+"mi", "ms", "os", "es", "xt", "hz", "ul", "xo", "HC", "nx", "NR", "NP", "5i"
+}; 
+
+char *Number_names[] = { 
+"co#", "it#", "li#", "lm#", "sg#", "pb#", "vt#", "ws#", "Nl#", "lh#", "lw#"
+};
+
+char *String_names[] = {
+"bt=", "bl=", "cr=", "cs=", "ct=", "cl=", "ce=", "cd=", "ch=", "CC=", "cm=", 
+"do=", "ho=", "vi=", "le=", "CM=", "ve=", "nd=", "ll=", "up=", "vs=", "dc=", 
+"dl=", "ds=", "hd=", "as=", "mb=", "md=", "ti=", "dm=", "mh=", "im=", "mk=", 
+"mp=", "mr=", "so=", "us=", "ec=", "ae=", "me=", "te=", "ed=", "ei=", "se=", 
+"ue=", "vb=", "ff=", "fs=", "i1=", "i2=", "i3=", "if=", "ic=", "al=", "ip=", 
+"kb=", "ka=", "kC=", "kt=", "kD=", "kL=", "kd=", "kM=", "kE=", "kS=", "k0=", 
+"k1=", "k;=", "k2=", "k3=", "k4=", "k5=", "k6=", "k7=", "k8=", "k9=", "kh=", 
+"kI=", "kA=", "kl=", "kH=", "kN=", "kP=", "kr=", "kF=", "kR=", "kT=", "ku=", 
+"ke=", "ks=", "l0=", "l1=", "la=", "l2=", "l3=", "l4=", "l5=", "l6=", "l7=", 
+"l8=", "l9=", "mo=", "mm=", "nw=", "pc=", "DC=", "DL=", "DO=", "IC=", "SF=", 
+"AL=", "LE=", "RI=", "SR=", "UP=", "pk=", "pl=", "px=", "ps=", "pf=", "po=", 
+"rp=", "r1=", "r2=", "r3=", "rf=", "rc=", "cv=", "sc=", "sf=", "sr=", "sa=", 
+"st=", "wi=", "ta=", "ts=", "uc=", "hu=", "iP=", "K1=", "K3=", "K2=", "K4=", 
+"K5=", "pO=", "rP=", "ac=", "pn=", "kB=", "SX=", "RX=", "SA=", "RA=", "XN=", 
+"XF=", "eA=", "LO=", "LF=", "@1=", "@2=", "@3=", "@4=", "@5=", "@6=", "@7=", 
+"@8=", "@9=", "@0=", "%1=", "%2=", "%3=", "%4=", "%5=", "%6=", "%7=", "%8=", 
+"%9=", "%0=", "&1=", "&2=", "&3=", "&4=", "&5=", "&6=", "&7=", "&8=", "&9=", 
+"&0=", "*1=", "*2=", "*3=", "*4=", "*5=", "*6=", "*7=", "*8=", "*9=", "*0=", 
+"#1=", "#2=", "#3=", "#4=", "%a=", "%b=", "%c=", "%d=", "%e=", "%f=", "%g=", 
+"%h=", "%i=", "%j=", "!1=", "!2=", "!3=", "RF=", "F1=", "F2=", "F3=", "F4=", 
+"F5=", "F6=", "F7=", "F8=", "F9=", "FA=", "FB=", "FC=", "FD=", "FE=", "FF=", 
+"FG=", "FH=", "FI=", "FJ=", "FK=", "FL=", "FM=", "FN=", "FO=", "FP=", "FQ=", 
+"FR=", "FS=", "FT=", "FU=", "FV=", "FW=", "FX=", "FY=", "FZ=", "Fa=", "Fb=", 
+"Fc=", "Fd=", "Fe=", "Ff=", "Fg=", "Fh=", "Fi=", "Fj=", "Fk=", "Fl=", "Fm=", 
+"Fn=", "Fo=", "Fp=", "Fq=", "Fr=", "cb=", "MC=", "ML=", "MR="
+};
+#endif
+
+char *new_curse = "October 1987";
+
+char in_buff[100];     /* buffer for ungetch                   */
+int bufp;              /* next free position in in_buff        */
+
+char *TERMINAL_TYPE = NULL; /* terminal type to be gotten from environment     */
+int CFOUND = FALSE;
+int Data_Line_len = 0;
+int Max_Key_len;       /* max length of a sequence sent by a key       */
+char *Data_Line = NULL;
+char *TERM_PATH = NULL;
+char *TERM_data_ptr = NULL;
+char *Term_File_name = NULL;   /* name of file containing terminal description */
+FILE *TFP;             /* file pointer to file with terminal des.      */
+int Fildes;            /* file descriptor for terminfo file            */
+int STAND = FALSE;     /* is standout mode activated?                  */
+int TERM_INFO = FALSE; /* is terminfo being used (TRUE), or termcap (FALSE) */
+int Time_Out;  /* set when time elapsed while trying to read function key */
+int Curr_x;            /* current x position on screen                 */
+int Curr_y;            /* current y position on the screen             */
+int LINES;
+int COLS;
+int Move_It;           /* flag to move cursor if magic cookie glitch   */
+int initialized = FALSE;       /* tells whether new_curse is initialized       */
+float speed;
+float chars_per_millisecond;
+int Repaint_screen;    /* if an operation to change screen impossible, repaint screen  */
+int Intr;              /* storeage for interrupt character             */
+int Parity;            /* 0 = no parity, 1 = odd parity, 2 = even parity */
+int Noblock;           /* for BSD systems                              */
+int Num_bits;  /* number of bits per character */
+int Flip_Bytes;        /* some systems have byte order reversed        */
+int interrupt_flag = FALSE;    /* set true if SIGWINCH received        */
+
+#ifndef CAP
+char *Strings;
+#endif
+
+#if !defined(TERMCAP)
+#define TERMCAP "/etc/termcap"
+#endif 
+
+struct KEYS {
+       int length;     /* length of string sent by key                 */
+       char *string;   /* string sent by key                           */
+       int value;      /* CURSES value of key (9-bit)                  */
+       };
+
+struct KEY_STACK {
+       struct KEYS *element;
+       struct KEY_STACK *next;
+       };
+
+struct KEY_STACK *KEY_TOS = NULL;
+struct KEY_STACK *KEY_POINT;
+
+/*
+ |
+ |     Not all systems have good terminal information, so we will define 
+ |     keyboard information here for the most widely used terminal type, 
+ |     the VT100.
+ |
+ */
+
+struct KEYS vt100[] = 
+       {
+               { 3, "\033[A", 0403 },  /* key up       */
+               { 3, "\033[C", 0405 },  /* key right    */
+               { 3, "\033[D", 0404 },  /* key left     */
+
+               { 4, "\033[6~", 0522 }, /* key next page        */
+               { 4, "\033[5~", 0523 }, /* key prev page        */
+               { 3, "\033[[", 0550 },  /* key end      */
+               { 3, "\033[@", 0406 },  /* key home     */
+               { 4, "\033[2~", 0513 }, /* key insert char      */
+
+               { 3, "\033[y", 0410 },  /* key F0       */
+               { 3, "\033[P", 0411 },  /* key F1       */
+               { 3, "\033[Q", 0412 },  /* key F2       */
+               { 3, "\033[R", 0413 },  /* key F3       */
+               { 3, "\033[S", 0414 },  /* key F4       */
+               { 3, "\033[t", 0415 },  /* key F5       */
+               { 3, "\033[u", 0416 },  /* key F6       */
+               { 3, "\033[v", 0417 },  /* key F7       */
+               { 3, "\033[l", 0420 },  /* key F8       */
+               { 3, "\033[w", 0421 },  /* key F9       */
+               { 3, "\033[x", 0422 },  /* key F10      */
+
+               { 5, "\033[10~", 0410 },        /* key F0       */
+               { 5, "\033[11~", 0411 },        /* key F1       */
+               { 5, "\033[12~", 0412 },        /* key F2       */
+               { 5, "\033[13~", 0413 },        /* key F3       */
+               { 5, "\033[14~", 0414 },        /* key F4       */
+               { 5, "\033[15~", 0415 },        /* key F5       */
+               { 5, "\033[17~", 0416 },        /* key F6       */
+               { 5, "\033[18~", 0417 },        /* key F7       */
+               { 5, "\033[19~", 0420 },        /* key F8       */
+               { 5, "\033[20~", 0421 },        /* key F9       */
+               { 5, "\033[21~", 0422 },        /* key F10      */
+               { 5, "\033[23~", 0423 },        /* key F11      */
+               { 5, "\033[24~", 0424 },        /* key F12      */
+               { 3, "\033[q", 0534 },  /* ka1 upper-left of keypad     */
+               { 3, "\033[s", 0535 },  /* ka3 upper-right of keypad    */
+               { 3, "\033[r", 0536 },  /* kb2 center of keypad */
+               { 3, "\033[p", 0537 },  /* kc1 lower-left of keypad     */
+               { 3, "\033[n", 0540 },  /* kc3 lower-right of keypad    */
+
+               /*
+                |      The following are the same keys as above, but with 
+                |      a different character following the escape char.
+                */
+
+               { 3, "\033OA", 0403 },  /* key up       */
+               { 3, "\033OC", 0405 },  /* key right    */
+               { 3, "\033OD", 0404 },  /* key left     */
+               { 3, "\033OB", 0402 },  /* key down     */
+               { 4, "\033O6~", 0522 }, /* key next page        */
+               { 4, "\033O5~", 0523 }, /* key prev page        */
+               { 3, "\033O[", 0550 },  /* key end      */
+               { 3, "\033O@", 0406 },  /* key home     */
+               { 4, "\033O2~", 0513 }, /* key insert char      */
+
+               { 3, "\033Oy", 0410 },  /* key F0       */
+               { 3, "\033OP", 0411 },  /* key F1       */
+               { 3, "\033OQ", 0412 },  /* key F2       */
+               { 3, "\033OR", 0413 },  /* key F3       */
+               { 3, "\033OS", 0414 },  /* key F4       */
+               { 3, "\033Ot", 0415 },  /* key F5       */
+               { 3, "\033Ou", 0416 },  /* key F6       */
+               { 3, "\033Ov", 0417 },  /* key F7       */
+               { 3, "\033Ol", 0420 },  /* key F8       */
+               { 3, "\033Ow", 0421 },  /* key F9       */
+               { 3, "\033Ox", 0422 },  /* key F10      */
+
+               { 5, "\033O10~", 0410 },        /* key F0       */
+               { 5, "\033O11~", 0411 },        /* key F1       */
+               { 5, "\033O12~", 0412 },        /* key F2       */
+               { 5, "\033O13~", 0413 },        /* key F3       */
+               { 5, "\033O14~", 0414 },        /* key F4       */
+               { 5, "\033O15~", 0415 },        /* key F5       */
+               { 5, "\033O17~", 0416 },        /* key F6       */
+               { 5, "\033O18~", 0417 },        /* key F7       */
+               { 5, "\033O19~", 0420 },        /* key F8       */
+               { 5, "\033O20~", 0421 },        /* key F9       */
+               { 5, "\033O21~", 0422 },        /* key F10      */
+               { 5, "\033O23~", 0423 },        /* key F11      */
+               { 5, "\033O24~", 0424 },        /* key F12      */
+               { 3, "\033Oq", 0534 },  /* ka1 upper-left of keypad     */
+               { 3, "\033Os", 0535 },  /* ka3 upper-right of keypad    */
+               { 3, "\033Or", 0536 },  /* kb2 center of keypad */
+               { 3, "\033Op", 0537 },  /* kc1 lower-left of keypad     */
+               { 3, "\033On", 0540 },  /* kc3 lower-right of keypad    */
+
+               { 0, "", 0 }    /* end  */
+       };
+
+struct Parameters {
+       int value;
+       struct Parameters *next;
+       };
+
+int Key_vals[] = { 
+       0407, 0526, 0515, 0525, 0512, 0510, 0402, 0514, 0517, 0516, 0410, 0411, 
+       0422, 0412, 0413, 0414, 0415, 0416, 0417, 0420, 0421, 0406, 0513, 0511, 
+       0404, 0533, 0522, 0523, 0405, 0520, 0521, 0524, 0403, 
+       0534, 0535, 0536, 0537, 0540, 0541, 0542, 0543, 0544, 0545, 0546, 0547, 
+       0550, 0527, 0551, 0552, 0553, 0554, 0555, 0556, 0557, 0560, 0561, 0562, 
+       0532, 0563, 0564, 0565, 0566, 0567, 0570, 0571, 0627, 0630, 0572, 0573, 
+       0574, 0575, 0576, 0577, 0600, 0601, 0602, 0603, 0604, 0605, 0606, 0607, 
+       0610, 0611, 0612, 0613, 0614, 0615, 0616, 0617, 0620, 0621, 0622, 0623, 
+       0624, 0625, 0626, 0423, 0424, 0425, 0426, 0427, 0430, 0431, 
+       0432, 0433, 0434, 0435, 0436, 0437, 0440, 0441, 0442, 0443, 0444, 0445, 
+       0446, 0447, 0450, 0451, 0452, 0453, 0454, 0455, 0456, 0457, 0460, 0461, 
+       0462, 0463, 0464, 0465, 0466, 0467, 0470, 0471, 0472, 0473, 0474, 0475, 
+       0476, 0477, 0500, 0501, 0502, 0503, 0504, 0505, 0506, 0507
+};
+
+int attributes_set[9];
+
+static int nc_attributes = 0;  /* global attributes for new_curse to observe */
+
+#ifdef SYS5
+struct termio Terminal;
+struct termio Saved_tty;
+#else
+struct sgttyb Terminal;
+struct sgttyb Saved_tty;
+#endif
+
+char *tc_;
+
+int Booleans[128];     
+int Numbers[128];
+char *String_table[1024];
+
+int *virtual_lines;
+
+static char nc_scrolling_ability = FALSE;
+
+char *terminfo_path[] = {
+        "/usr/lib/terminfo", 
+        "/usr/share/lib/terminfo", 
+        "/usr/share/terminfo", 
+        NULL 
+        };
+
+#ifdef CAP
+
+#if defined(__STDC__) || defined(__cplusplus)
+#define P_(s) s
+#else
+#define P_(s) ()
+#endif /* __STDC__ */
+
+int tc_Get_int P_((int));
+void CAP_PARSE P_((void));
+void Find_term P_((void));
+
+#undef P_
+
+#endif /* CAP */
+
+
+#ifndef __STDC__
+#ifndef HAS_STDLIB
+extern char *fgets();
+extern char *malloc();
+extern char *getenv();
+FILE *fopen();                 /* declaration for open function        */
+#endif /* HAS_STDLIB */
+#endif /* __STDC__ */
+
+#ifdef SIGWINCH
+
+/*
+ |     Copy the contents of one window to another.
+ */
+
+void 
+copy_window(origin, destination)
+WINDOW *origin, *destination;
+{
+       int row, column;
+       struct _line *orig, *dest;
+
+       orig = origin->first_line;
+       dest = destination->first_line;
+
+       for (row = 0; 
+               row < (min(origin->Num_lines, destination->Num_lines)); 
+                       row++)
+       {
+               for (column = 0; 
+                   column < (min(origin->Num_cols, destination->Num_cols)); 
+                       column++)
+               {
+                       dest->row[column] = orig->row[column];
+                       dest->attributes[column] = orig->attributes[column];
+               }
+               dest->changed = orig->changed;
+               dest->scroll = orig->scroll;
+               dest->last_char = min(orig->last_char, destination->Num_cols);
+               orig = orig->next_screen;
+               dest = dest->next_screen;
+       }
+       destination->LX = min((destination->Num_cols - 1), origin->LX);
+       destination->LY = min((destination->Num_lines - 1), origin->LY);
+       destination->Attrib = origin->Attrib;
+       destination->scroll_up = origin->scroll_up;
+       destination->scroll_down = origin->scroll_down;
+       destination->SCROLL_CLEAR = origin->SCROLL_CLEAR;
+}
+
+void 
+reinitscr(foo)
+int foo; 
+{
+       WINDOW *local_virt;
+       WINDOW *local_std;
+       WINDOW *local_cur;
+
+       signal(SIGWINCH, reinitscr);
+#ifdef TIOCGWINSZ
+       if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
+       {
+               if (ws.ws_row == LINES && ws.ws_col == COLS) 
+                       return;
+               if (ws.ws_row > 0) 
+                       LINES = ws.ws_row;
+               if (ws.ws_col > 0) 
+                       COLS = ws.ws_col;
+       }
+#endif /* TIOCGWINSZ */
+       local_virt = newwin(LINES, COLS, 0, 0);
+       local_std = newwin(LINES, COLS, 0, 0);
+       local_cur = newwin(LINES, COLS, 0, 0);
+       copy_window(virtual_scr, local_virt);
+       copy_window(stdscr, local_std);
+       copy_window(curscr, local_cur);
+       delwin(virtual_scr);
+       delwin(stdscr);
+       delwin(curscr);
+       virtual_scr = local_virt;
+       stdscr = local_std;
+       curscr = local_cur;
+       free(virtual_lines);
+       virtual_lines = (int *) malloc(LINES * (sizeof(int)));
+       interrupt_flag = TRUE;
+}
+#endif /* SIGWINCH */
+
+void 
+initscr()              /* initialize terminal for operations   */
+{
+       int value;
+       int counter;
+       char *lines_string;
+       char *columns_string;
+#ifdef CAP
+       char *pointer;
+#endif /* CAP */
+
+#ifdef DIAG
+printf("starting initscr \n");fflush(stdout);
+#endif
+       if (initialized)
+               return;
+#ifdef BSD_SELECT
+       setbuf(stdin, NULL);
+#endif /* BSD_SELECT */
+       Flip_Bytes = FALSE;
+       Parity = 0;
+       Time_Out = FALSE;
+       bufp = 0;
+       Move_It = FALSE;
+       Noblock = FALSE;
+#ifdef SYS5
+       value = ioctl(0, TCGETA, &Terminal);
+       if (Terminal.c_cflag & PARENB)
+       {
+               if (Terminal.c_cflag & PARENB)
+                       Parity = 1;
+               else
+                       Parity = 2;
+       }
+       if ((Terminal.c_cflag & CS8) == CS8)
+       {
+               Num_bits = 8;
+       }
+       else if ((Terminal.c_cflag & CS7) == CS7)
+               Num_bits = 7;
+       else if ((Terminal.c_cflag & CS6) == CS6)
+               Num_bits = 6;
+       else
+               Num_bits = 5;
+       value = Terminal.c_cflag & 037;
+       switch (value) {
+       case 01:        speed = 50.0;
+               break;
+       case 02:        speed = 75.0;
+               break;
+       case 03:        speed = 110.0;
+               break;
+       case 04:        speed = 134.5;
+               break;
+       case 05:        speed = 150.0;
+               break;
+       case 06:        speed = 200.0;
+               break;
+       case 07:        speed = 300.0;
+               break;
+       case 010:       speed = 600.0;
+               break;
+       case 011:       speed = 900.0;
+               break;
+       case 012:       speed = 1200.0;
+               break;
+       case 013:       speed = 1800.0;
+               break;
+       case 014:       speed = 2400.0;
+               break;
+       case 015:       speed = 3600.0;
+               break;
+       case 016:       speed = 4800.0;
+               break;
+       case 017:       speed = 7200.0;
+               break;
+       case 020:       speed = 9600.0;
+               break;
+       case 021:       speed = 19200.0;
+               break;
+       case 022:       speed = 38400.0;
+               break;
+       default:        speed = 0.0;
+       }
+#else
+       value = ioctl(0, TIOCGETP, &Terminal);
+       if (Terminal.sg_flags & EVENP)
+               Parity = 2;
+       else if (Terminal.sg_flags & ODDP)
+               Parity = 1;
+       value = Terminal.sg_ospeed;
+       switch (value) {
+       case 01:        speed = 50.0;
+               break;
+       case 02:        speed = 75.0;
+               break;
+       case 03:        speed = 110.0;
+               break;
+       case 04:        speed = 134.5;
+               break;
+       case 05:        speed = 150.0;
+               break;
+       case 06:        speed = 200.0;
+               break;
+       case 07:        speed = 300.0;
+               break;
+       case 010:       speed = 600.0;
+               break;
+       case 011:       speed = 1200.0;
+               break;
+       case 012:       speed = 1800.0;
+               break;
+       case 013:       speed = 2400.0;
+               break;
+       case 014:       speed = 4800.0;
+               break;
+       case 015:       speed = 9600.0;
+               break;
+       default:        speed = 0.0;
+       }
+#endif
+       chars_per_millisecond = (0.001 * speed) / 8.0;
+       TERMINAL_TYPE = getenv("TERM");
+       if (TERMINAL_TYPE == NULL)
+       {
+               printf("unknown terminal type\n");
+               exit(0);
+       }
+#ifndef CAP
+       Fildes = -1;
+       TERM_PATH = getenv("TERMINFO");
+       if (TERM_PATH != NULL)
+       {
+               Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
+               Term_File_name = malloc(Data_Line_len);
+               sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
+               Fildes = open(Term_File_name, O_RDONLY);
+               if (Fildes == -1)
+               {
+                       sprintf(Term_File_name, "%s/%x/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
+                       Fildes = open(Term_File_name, O_RDONLY);
+               }
+       }
+       counter = 0;
+       while ((Fildes == -1) && (terminfo_path[counter] != NULL))
+       {
+               TERM_PATH = terminfo_path[counter];
+               Data_Line_len = 23 + strlen(TERM_PATH) + strlen(TERMINAL_TYPE);
+               Term_File_name = malloc(Data_Line_len);
+               sprintf(Term_File_name, "%s/%c/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
+               Fildes = open(Term_File_name, O_RDONLY);
+               if (Fildes == -1)
+               {
+                       sprintf(Term_File_name, "%s/%x/%s", TERM_PATH, *TERMINAL_TYPE, TERMINAL_TYPE);
+                       Fildes = open(Term_File_name, O_RDONLY);
+               }
+               counter++;
+       }
+       if (Fildes == -1)
+       {
+               free(Term_File_name);
+               Term_File_name = NULL;
+       }
+       else
+               TERM_INFO = INFO_PARSE();
+#else
+       /*
+        |      termcap information can be in the TERMCAP env variable, if so 
+        |      use that, otherwise check the /etc/termcap file
+        */
+       if ((pointer = Term_File_name = getenv("TERMCAP")) != NULL)
+       {
+               if (*Term_File_name != '/')
+                       Term_File_name = TERMCAP;
+       }
+       else
+       {
+               Term_File_name = TERMCAP;
+       }
+       if ((TFP = fopen(Term_File_name, "r")) == NULL)
+       {
+               printf("unable to open %s file \n", TERMCAP);
+               exit(0);
+       }
+       for (value = 0; value < 1024; value++)  
+               String_table[value] = NULL;
+       for (value = 0; value < 128; value++)   
+               Booleans[value] = 0;
+       for (value = 0; value < 128; value++)   
+               Numbers[value] = 0;
+       Data_Line = malloc(512);
+       if (pointer && *pointer != '/')
+       {
+               TERM_data_ptr = pointer;
+               CAP_PARSE();
+       }
+       else
+       {
+               Find_term();
+               CAP_PARSE();
+       }
+#endif
+       if (String_table[pc__] == NULL) 
+               String_table[pc__] = "\0";
+       if ((String_table[cm__] == NULL) || (Booleans[hc__]))
+       {
+               fprintf(stderr, "sorry, unable to use this terminal type for screen editing\n");
+               exit(0);
+       }
+       Key_Get();
+       keys_vt100();
+       LINES = Numbers[li__];
+       COLS = Numbers[co__];
+       if ((lines_string = getenv("LINES")) != NULL)
+       {
+               value = atoi(lines_string);
+               if (value > 0)
+                       LINES = value;
+       }
+       if ((columns_string = getenv("COLUMNS")) != NULL)
+       {
+               value = atoi(columns_string);
+               if (value > 0)
+                       COLS = value;
+       }
+#ifdef TIOCGWINSZ
+       /*
+        |      get the window size
+        */
+       if (ioctl(0, TIOCGWINSZ, &ws) >= 0)
+       {
+               if (ws.ws_row > 0)
+                       LINES = ws.ws_row;
+               if (ws.ws_col > 0)
+                       COLS = ws.ws_col;
+       }
+#endif
+       virtual_scr = newwin(LINES, COLS, 0, 0);
+       stdscr = newwin(LINES, COLS, 0, 0);
+       curscr = newwin(LINES, COLS, 0, 0);
+       wmove(stdscr, 0, 0);
+       werase(stdscr);
+       Repaint_screen = TRUE;
+       initialized = TRUE;
+       virtual_lines = (int *) malloc(LINES * (sizeof(int)));
+
+#ifdef SIGWINCH
+       /*
+        |      reset size of windows and LINES and COLS if term window 
+        |      changes size
+        */
+       signal(SIGWINCH, reinitscr);
+#endif /* SIGWINCH */
+
+       /*
+        |      check if scrolling is available
+        */
+
+       nc_scrolling_ability = ((String_table[al__] != NULL) && 
+                               (String_table[dl__])) || ((String_table[cs__]) 
+                               && (String_table[sr__]));
+
+}
+
+#ifndef CAP
+int 
+Get_int()              /* get a two-byte integer from the terminfo file */
+{
+       int High_byte;
+       int Low_byte;
+       int temp;
+
+       Low_byte = *((unsigned char *) TERM_data_ptr++);
+       High_byte = *((unsigned char *) TERM_data_ptr++);
+       if (Flip_Bytes)
+       {
+               temp = Low_byte;
+               Low_byte = High_byte;
+               High_byte = temp;
+       }
+       if ((High_byte == 255) && (Low_byte == 255))
+               return (-1);
+       else
+               return(Low_byte + (High_byte * 256));
+}
+
+int 
+INFO_PARSE()           /* parse off the data in the terminfo data file */
+{
+       int offset;
+       int magic_number = 0;
+       int counter = 0;
+       int Num_names = 0;
+       int Num_bools = 0;
+       int Num_ints = 0;
+       int Num_strings = 0;
+       int string_table_len = 0;
+       char *temp_ptr;
+
+       TERM_data_ptr = Data_Line = malloc((10240 * (sizeof(char))));
+       Data_Line_len = read(Fildes, Data_Line, 10240);
+       if ((Data_Line_len >= 10240) || (Data_Line_len < 0))
+               return(0);
+       /*
+        |      get magic number
+        */
+       magic_number = Get_int();
+       /*
+        |      if magic number not right, reverse byte order and check again
+        */
+       if (magic_number != 282)
+       {
+               Flip_Bytes = TRUE;
+               TERM_data_ptr--;
+               TERM_data_ptr--;
+               magic_number = Get_int();
+               if (magic_number != 282)
+                       return(0);
+       }
+       /*
+        |      get the number of each type in the terminfo data file
+        */
+       Num_names = Get_int();
+       Num_bools = Get_int();
+       Num_ints = Get_int();
+       Num_strings = Get_int();
+       string_table_len = Get_int();
+       Strings = malloc(string_table_len);
+       while (Num_names > 0)
+       {
+               TERM_data_ptr++;
+               Num_names--;
+       }
+       counter = 0;
+       while (Num_bools)
+       {
+               Num_bools--;
+               Booleans[counter++] = *TERM_data_ptr++;
+       }
+       if ((unsigned long)TERM_data_ptr & 1)   /* force alignment      */
+               TERM_data_ptr++;
+       counter = 0;
+       while (Num_ints)
+       {
+               Num_ints--;
+               Numbers[counter] = Get_int();
+               counter++;
+       }
+       temp_ptr = TERM_data_ptr + Num_strings + Num_strings;
+       memcpy(Strings, temp_ptr, string_table_len);
+       counter = bt__;
+       while (Num_strings)
+       {
+               Num_strings--;
+               if ((offset=Get_int()) != -1)
+               {
+                       if (String_table[counter] == NULL)
+                               String_table[counter] = Strings + offset;
+               }
+               else
+                       String_table[counter] = NULL;
+               counter++;
+       }
+       close(Fildes);
+       free(Data_Line);
+       return(TRUE);
+}
+#endif         /* ifndef CAP   */
+
+int 
+AtoI()         /* convert ascii text to integers       */
+{
+       int Temp;
+
+       Temp = 0;
+       while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9'))
+       {
+               Temp = (Temp * 10) + (*TERM_data_ptr - '0');
+               TERM_data_ptr++;
+       }
+       return(Temp);
+}
+
+void 
+Key_Get()              /* create linked list with all key sequences obtained from terminal database    */
+{
+       int Counter;
+       int Klen;
+       int key_def;
+       struct KEY_STACK *Spoint;
+
+       Max_Key_len = 0;
+       Counter = 0;
+       key_def = kb__;
+       while (key_def <= kf63__)
+       {
+               if (key_def == ke__)
+                       key_def = K1__;
+               else if (key_def == (K5__ + 1))
+                       key_def = kcbt__;
+               else if (key_def == (kcbt__ + 1))
+                       key_def = kbeg__;
+               else if (key_def == (kUND__ + 1))
+                       key_def = kf11__;
+               if (String_table[key_def] != NULL)
+               {
+                       if (KEY_TOS == NULL)
+                               Spoint = KEY_TOS = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
+                       else
+                       {
+                               Spoint = KEY_TOS;
+                               while (Spoint->next != NULL)
+                                       Spoint = Spoint->next;
+                               Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
+                               Spoint = Spoint->next;
+                       }
+                       Spoint->next = NULL;
+                       Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
+                       Spoint->element->string = String_table[key_def];
+                       Spoint->element->length = strlen(String_table[key_def]);
+                       Spoint->element->value = Key_vals[Counter];
+                       Klen = strlen(Spoint->element->string);
+                       if (Klen > Max_Key_len)
+                               Max_Key_len = Klen;
+                       /*
+                        |  Some terminal types accept keystrokes of the form
+                        |  \E[A and \EOA, substituting '[' for 'O'.  Make a 
+                        |  duplicate of such key strings (since the 
+                        |  database will only have one version) so new_curse 
+                        |  can understand both.
+                        */
+                       if ((Spoint->element->length > 1) && 
+                           ((String_table[key_def][1] == '[') || 
+                            (String_table[key_def][1] == 'O')))
+                       {
+                               Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
+                               Spoint = Spoint->next;
+                               Spoint->next = NULL;
+                               Spoint->element = (struct KEYS *) malloc(sizeof(struct KEYS));
+                               Spoint->element->length = strlen(String_table[key_def]);
+                               Spoint->element->string = malloc(Spoint->element->length + 1);
+                               strcpy(Spoint->element->string, String_table[key_def]);
+                               Spoint->element->value = Key_vals[Counter];
+                               Klen = strlen(Spoint->element->string);
+                               if (Klen > Max_Key_len)
+                                       Max_Key_len = Klen;
+                       
+                               if (String_table[key_def][1] == '[')
+                                       Spoint->element->string[1] = 'O';
+                               else
+                                       Spoint->element->string[1] = '[';
+                       }
+               }
+               key_def++;
+               Counter++;
+       }
+}
+
+/*
+ |     insert information about keys for a vt100 terminal
+ */
+
+void
+keys_vt100()
+{
+       int counter;
+       int Klen;
+       struct KEY_STACK *Spoint;
+
+       Spoint = KEY_TOS;
+       while (Spoint->next != NULL)
+               Spoint = Spoint->next;
+       for (counter = 0; vt100[counter].length != 0; counter++)
+       {
+               Spoint->next = (struct KEY_STACK *) malloc(sizeof(struct KEY_STACK));
+               Spoint = Spoint->next;
+               Spoint->next = NULL;
+               Spoint->element = &vt100[counter];
+               Klen = strlen(Spoint->element->string);
+               if (Klen > Max_Key_len)
+                       Max_Key_len = Klen;
+       }
+}
+
+#ifdef CAP
+char *
+String_Get(param)              /* read the string */
+char *param;
+{
+       char *String;
+       char *Temp;
+       int Counter;
+
+       if (param == NULL)
+       {
+               while (*TERM_data_ptr != '=')
+                       TERM_data_ptr++;
+               Temp = ++TERM_data_ptr;
+               Counter = 1;
+               while ((*Temp != ':') && (*Temp != (char)NULL))
+               {
+                       Counter++;
+                       Temp++;
+               }
+               if (Counter == 1)       /* no data */
+                       return(NULL);
+               String = Temp = malloc(Counter);
+               while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL))
+               {
+                       if (*TERM_data_ptr == '\\')
+                       {
+                               TERM_data_ptr++;
+                               if&nbs