diff options
author | ed <ed@FreeBSD.org> | 2009-05-26 20:13:17 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2009-05-26 20:13:17 +0000 |
commit | fbad22d013baa1ed80ce29fd090be19e99ed314c (patch) | |
tree | 802aed2d76270bc9fee21713d1e79973febde177 /contrib/ee | |
parent | 6cf142b7b439d69ca0ee2ce20e9551f628a65110 (diff) | |
parent | cd2cd8f376f2d165e207cc5b80154f80bffbac4d (diff) | |
download | FreeBSD-src-fbad22d013baa1ed80ce29fd090be19e99ed314c.zip FreeBSD-src-fbad22d013baa1ed80ce29fd090be19e99ed314c.tar.gz |
Copy ee 1.4.2 into the contrib directory.
This allows me to merge our custom changes to ee(1) back on top of
original sources, with correct mergeinfo.
Diffstat (limited to 'contrib/ee')
-rw-r--r-- | contrib/ee/Artistic | 117 | ||||
-rwxr-xr-x | contrib/ee/Makefile | 29 | ||||
-rw-r--r-- | contrib/ee/README.ee | 116 | ||||
-rwxr-xr-x | contrib/ee/create.make | 268 | ||||
-rw-r--r-- | contrib/ee/ee.1 | 539 | ||||
-rwxr-xr-x | contrib/ee/ee.c | 5268 | ||||
-rw-r--r-- | contrib/ee/ee.i18n.guide | 158 | ||||
-rw-r--r-- | contrib/ee/ee.msg | 185 | ||||
-rwxr-xr-x | contrib/ee/genstr | 32 | ||||
-rw-r--r-- | contrib/ee/make.default | 57 | ||||
-rw-r--r-- | contrib/ee/new_curse.c | 3813 | ||||
-rw-r--r-- | contrib/ee/new_curse.h | 260 |
12 files changed, 10842 insertions, 0 deletions
diff --git a/contrib/ee/Artistic b/contrib/ee/Artistic new file mode 100644 index 0000000..fbf7989 --- /dev/null +++ b/contrib/ee/Artistic @@ -0,0 +1,117 @@ + + + + + The "Artistic License" + + Preamble + +The intent of this document is to state the conditions under which a +Package may be copied, such that the Copyright Holder maintains some +semblance of artistic control over the development of the package, +while giving the users of the package the right to use and distribute +the Package in a more-or-less customary fashion, plus the right to make +reasonable modifications. + +Definitions: + + "Package" refers to the collection of files distributed by the + Copyright Holder, and derivatives of that collection of files + created through textual modification. + + "Standard Version" refers to such a Package if it has not been + modified, or has been modified in accordance with the wishes + of the Copyright Holder. + + "Copyright Holder" is whoever is named in the copyright or + copyrights for the package. + + "You" is you, if you're thinking about copying or distributing + this Package. + + "Reasonable copying fee" is whatever you can justify on the + basis of media cost, duplication charges, time of people involved, + and so on. (You will not be required to justify it to the + Copyright Holder, but only to the computing community at large + as a market that must bear the fee.) + + "Freely Available" means that no fee is charged for the item + itself, though there may be fees involved in handling the item. + It also means that recipients of the item may redistribute it + under the same conditions they received it. + +1. You may make and give away verbatim copies of the source form of the +Standard Version of this Package without restriction, provided that you +duplicate all of the original copyright notices and associated disclaimers. + +2. You may apply bug fixes, portability fixes and other modifications +derived from the Public Domain or from the Copyright Holder. A Package +modified in such a way shall still be considered the Standard Version. + +3. You may otherwise modify your copy of this Package in any way, provided +that you insert a prominent notice in each changed file stating how and +when you changed that file, and provided that you do at least ONE of the +following: + + a) place your modifications in the Public Domain or otherwise make them + Freely Available, such as by posting said modifications to Usenet or + an equivalent medium, or placing the modifications on a major archive + site such as uunet.uu.net, or by allowing the Copyright Holder to include + your modifications in the Standard Version of the Package. + + b) use the modified Package only within your corporation or organization. + + c) rename any non-standard executables so the names do not conflict + with standard executables, which must also be provided, and provide + a separate manual page for each non-standard executable that clearly + documents how it differs from the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +4. You may distribute the programs of this Package in object code or +executable form, provided that you do at least ONE of the following: + + a) distribute a Standard Version of the executables and library files, + together with instructions (in the manual page or equivalent) on where + to get the Standard Version. + + b) accompany the distribution with the machine-readable source of + the Package with your modifications. + + c) accompany any non-standard executables with their corresponding + Standard Version executables, giving the non-standard executables + non-standard names, and clearly documenting the differences in manual + pages (or equivalent), together with instructions on where to get + the Standard Version. + + d) make other distribution arrangements with the Copyright Holder. + +5. You may charge a reasonable copying fee for any distribution of this +Package. You may charge any fee you choose for support of this Package. +You may not charge a fee for this Package itself. However, +you may distribute this Package in aggregate with other (possibly +commercial) programs as part of a larger (possibly commercial) software +distribution provided that you do not advertise this Package as a +product of your own. + +6. The scripts and library files supplied as input to or produced as +output from the programs of this Package do not automatically fall +under the copyright of this Package, but belong to whomever generated +them, and may be sold commercially, and may be aggregated with this +Package. + +7. C subroutines supplied by you and linked into this Package in order +to emulate subroutines and variables of the language defined by this +Package shall not be considered part of this Package, but are the +equivalent of input as in Paragraph 6, provided these subroutines do +not change the language in any way that would cause it to fail the +regression tests for the language. + +8. The name of the Copyright Holder may not be used to endorse or promote +products derived from this software without specific prior written permission. + +9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED +WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + The End diff --git a/contrib/ee/Makefile b/contrib/ee/Makefile new file mode 100755 index 0000000..a6525ea --- /dev/null +++ b/contrib/ee/Makefile @@ -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 index 0000000..8850af2 --- /dev/null +++ b/contrib/ee/README.ee @@ -0,0 +1,116 @@ + 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. + + This software may be distributed under the terms of Larry Wall's + Artistic license, a copy of which is included in this distribution. + + This notice must be included with this software and any + derivatives. + + Any modifications to this software by anyone but the original author + must be so noted. + + +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 |___| +h_mahon@fc.hp.com | | + |\ /| + | \/ | + diff --git a/contrib/ee/create.make b/contrib/ee/create.make new file mode 100755 index 0000000..dcf3e38 --- /dev/null +++ b/contrib/ee/create.make @@ -0,0 +1,268 @@ +#!/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.7 2001/01/20 04:57:17 hugh Exp hugh $ +# + +# 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 + termcap_exists="TRUE" +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 [ -n "$CFLAGS" ] +then + if [ -z "`echo $CFLAGS | grep '[-]g'`" ] + then + other_cflags="${CFLAGS} -s" + else + other_cflags="${CFLAGS}" + fi +else + other_cflags="-s" +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" >> 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 index 0000000..be79cbf --- /dev/null +++ b/contrib/ee/ee.1 @@ -0,0 +1,539 @@ +.\" +.\" +.\" To format this reference page, use the command: +.\" +.\" nroff -man ee.1 +.\" +.\" $Header: /home/hugh/sources/old_ae/RCS/ee.1,v 1.19 1995/11/29 04:03:15 hugh Exp hugh $ +.\" +.\" +.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 +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 Hugh Mahon. +.SH "SEE ALSO" +.PP +termcap(4), terminfo(4), environ(5), spell(1), ispell(1), lp(1) + diff --git a/contrib/ee/ee.c b/contrib/ee/ee.c new file mode 100755 index 0000000..9a08dc4 --- /dev/null +++ b/contrib/ee/ee.c @@ -0,0 +1,5268 @@ +/* + | ee (easy editor) + | + | An easy to use, simple screen oriented editor. + | + | written by Hugh Mahon + | + | 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. + | + | This software is not a product of Hewlett-Packard, Co., or any + | other company. No support is implied or offered with this software. + | You've got the source, and you're on your own. + | + | This software may be distributed under the terms of Larry Wall's + | Artistic license, a copy of which is included in this distribution. + | + | This notice must be included with this software and any derivatives. + | + | 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.96 1998/07/14 05:02:30 hugh Exp $ + | + */ + +char *ee_copyright_message = +"Copyright (c) 1986, 1990, 1991, 1992, 1993, 1994, 1995, 1996 Hugh Mahon "; + +char *ee_long_notice[] = { + "This software and documentation contains", + "proprietary information which is protected by", + "copyright. All rights are reserved." + }; + +char *version = "@(#) ee, version 1.4.1 $Revision: 1.96 $"; + +#ifdef NCURSE +#include "new_curse.h" +#else +#include <curses.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 + +#ifdef HAS_CTYPE +#include <ctype.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 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 = "lp"; /* 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 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 *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 < 24; 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 = (char) NULL; + 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; + 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; + + while(edit) + { + wrefresh(text_win); + in = wgetch(text_win); + if (in == -1) + exit(0); + + 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] = (unsigned char) NULL; + } + while (temp_pos <= curr_line->line_length) + { + temp_pos++; + *tp = *temp2; + tp++; + temp2++; + } + if (scr_horz < horiz_offset) + { + 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] = (unsigned char) NULL; + } + tp = point; + temp_pos = 1; + while (temp_pos < temp_buff->line_length) + { + curr_line->line_length++; + temp_pos++; + *tp = *temp2; + tp++; + temp2++; + } + *tp = (char) NULL; + 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; + unsigned 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] != (char) NULL) && (((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 = (char) NULL; + 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; + curr_line = temp_nod; + *extra = (char) NULL; + 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 != (char) NULL) && ((*string != 32) && (*string != 9))) + string++; + while ((*string != (char) NULL) && ((*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 != (char) NULL) + { + 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 != (char) NULL) + { + 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; + 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; + 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; + 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; + 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) + { + 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) + { + 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) + top(); + 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 == (char) NULL) + { + cmd_str = cmd_str2 = get_string(file_write_prompt_str, TRUE); + } + tmp_file = resolve_name(cmd_str); + write_file(tmp_file); + 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 == (char) NULL) + { + 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 = (char) NULL; + } while ((in != '\n') && (in != '\r')); + *nam_str = (char) NULL; + 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 == (char) NULL) || (*strng2 == (char) NULL)) + 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 == (char) NULL) || (*strng2 == (char) NULL) || (*strng1 == ' ') || (*strng2 == ' ')) + break; + tmp++; + } + return(equal); +} + +void +goto_line(cmd_str) +char *cmd_str; +{ + int number; + int i; + char *ptr; + char *direction; + 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 + { + 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; + char *name; + char *ptr; + + /* + | 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) + { + 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 == '+') + { + buff++; + start_at_line = buff; + } + + else + { + 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 != (char) NULL) + { + *ptr = *buff; + buff++; + ptr++; + } + *ptr = (char) NULL; + 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 != (char) NULL)) + 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 = (char) NULL; + *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 == (char) NULL)) + file_name = get_string(save_file_name_prompt, TRUE); + + if ((file_name == NULL) || (*file_name == (char) NULL)) + { + 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)) + { + 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; + free(curr_line->next_line); + } + curr_line->next_line = NULL; + *curr_line->line = (char) NULL; + 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) +char *file_name; +{ + char cr; + char *tmp_point; + struct text *out_line; + int lines, charac; + int temp_pos; + int write_flag = TRUE; + + charac = lines = 0; + if ((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 == (char) NULL)) + 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 != (char) NULL)) + { + 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 != (char) NULL)) + { + found = TRUE; + srch_2++; + srch_3++; + } + } /* end else */ + if (!((*srch_3 == (char) NULL) && (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 + { + 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 != (char) NULL)) + 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 != (char) NULL) + { + *srch_1 = toupper(*srch_3); + srch_1++; + srch_3++; + } + *srch_1 = (char) NULL; + 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(FALSE); + delete(FALSE); + } +} + +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] != (unsigned char) NULL) + { + 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 = (char) NULL; + 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 = (char) NULL; + 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 = (char) NULL; + 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 = (char) NULL; + 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 = (char) NULL; + *point = (char) NULL; + 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 = (char) NULL; + 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; + 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(); + } + 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 +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 != (char) NULL) + { + 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; + 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); + printf(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, "==============================================================================="); + 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); + 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 == (char) NULL)) + string = get_string(save_file_name_prompt, TRUE); + if ((string == NULL) || (*string == (char) NULL)) + { + 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)) + { + 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 != (char) NULL)) + { + 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 != (char) NULL) && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length)) + { + *temp2 = *temp1; + temp2++; + temp1++; + counter++; + } + *temp2 = (char) NULL; + 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"); + 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 = (char) NULL; + + 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 != (char) NULL) + 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] = (char) NULL; + + 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 != (char) NULL) + { + 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 name[128]; + char string[256]; + int pid; + + if (restrict_mode()) + { + return; + } + pid = getpid(); + sprintf(name, "/tmp/ee.%d", pid); + if (write_file(name)) + { + 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 == (char) NULL) || + (*pnt == '.') || (*pnt == '>')) + return(0); + + if ((*pnt == ' ') || (*pnt == '\t')) + { + pnt = next_word(pnt); + } + + if (*pnt == (char) NULL) + return(0); + + counter = 0; + while ((*pnt != (char) NULL) && ((*pnt != ' ') && (*pnt != '\t'))) + { + pnt++; + counter++; + } + while ((*pnt != (char) NULL) && ((*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 == (char) NULL))) + 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 != (char) NULL) && (*temp1 != ' ') && (*temp1 != '\t') && (counter < curr_line->line_length)) + { + *temp2 = *temp1; + temp2++; + temp1++; + counter++; + } + *temp2 = (char) NULL; + 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 != (char)NULL); sub++) + { + for (full = string; (full != NULL) && (*full != (char)NULL); + 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 = (char) NULL; + 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 != (char) NULL) && (index < 1024)) + { + + while ((*tmp != (char) NULL) && (*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 != (char) NULL) && + (*tmp != '}') && + (counter < 128)) + { + short_buffer[counter] = *tmp; + counter++; + tmp++; + } /* { */ + if (*tmp == '}') + tmp++; + } + else + { + while ((*tmp != (char) NULL) && + (*tmp != '/') && + (*tmp != '$') && + (counter < 128)) + { + short_buffer[counter] = *tmp; + counter++; + tmp++; + } + } + short_buffer[counter] = (char) NULL; + 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] = (char) NULL; + + 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 "); + 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 "); + 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 "); + emacs_control_keys[3] = catgetlocal( 157, "^t top of text ^e end of line ^r restore word ^f forward 1 char "); + emacs_control_keys[4] = catgetlocal( 158, "^c command ^d delete char ^j undelete char ^z next word "); + 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 index 0000000..eef836a --- /dev/null +++ b/contrib/ee/ee.i18n.guide @@ -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 index 0000000..f7c209c --- /dev/null +++ b/contrib/ee/ee.msg @@ -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/genstr b/contrib/ee/genstr new file mode 100755 index 0000000..429f960 --- /dev/null +++ b/contrib/ee/genstr @@ -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 index 0000000..32ff05d --- /dev/null +++ b/contrib/ee/make.default @@ -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 index 0000000..9ea8269 --- /dev/null +++ b/contrib/ee/new_curse.c @@ -0,0 +1,3813 @@ +/* + | new_curse.c + | + | A subset of curses developed for use with ae. + | + | written by Hugh Mahon + | + | 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. + | + | This software is not a product of Hewlett-Packard, Co., or any + | other company. No support is implied or offered with this software. + | You've got the source, and you're on your own. + | + | This software may be distributed under the terms of Larry Wall's + | Artistic license, a copy of which is included in this distribution. + | + | This notice must be included with this software and any derivatives. + | + | Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon + | All are rights reserved. + | + | $Header: /home/hugh/sources/old_ae/RCS/new_curse.c,v 1.50 2001/01/19 02:53:40 hugh Exp hugh $ + | + */ + +char *copyright_message[] = { "Copyright (c) 1986, 1987, 1988, 1991, 1992, 1993, 1994, 1995 Hugh Mahon", + "All rights are reserved."}; + +char * new_curse_name= "@(#) new_curse.c $Revision: 1.50 $"; + +#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 + +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; + +#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; + 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) + { + TERM_PATH = "/usr/lib/terminfo"; + 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) + { + TERM_PATH = "/usr/share/lib/terminfo"; + 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) + { + TERM_PATH = "/usr/share/terminfo"; + 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) + { + 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 = "/etc/termcap"; + } + else + { + Term_File_name = "/etc/termcap"; + } + if ((TFP = fopen(Term_File_name, "r")) == NULL) + { + printf("unable to open /etc/termcap file \n"); + 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 int) 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 (*TERM_data_ptr == 'n') + *Temp = '\n'; + else if (*TERM_data_ptr == 't') + *Temp = '\t'; + else if (*TERM_data_ptr == 'b') + *Temp = '\b'; + else if (*TERM_data_ptr == 'r') + *Temp = '\r'; + else if (*TERM_data_ptr == 'f') + *Temp = '\f'; + else if ((*TERM_data_ptr == 'e') || (*TERM_data_ptr == 'E')) + *Temp = '\033'; /* escape */ + else if (*TERM_data_ptr == '\\') + *Temp = '\\'; + else if (*TERM_data_ptr == '\'') + *Temp = '\''; + else if ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9')) + { + Counter = 0; + while ((*TERM_data_ptr >= '0') && (*TERM_data_ptr <= '9')) + { + Counter = (8 * Counter) + (*TERM_data_ptr - '0'); + TERM_data_ptr++; /* ? */ + } + *Temp = Counter; + TERM_data_ptr--; + } + TERM_data_ptr++; + Temp++; + } + else if (*TERM_data_ptr == '^') + { + TERM_data_ptr++; + if ((*TERM_data_ptr >= '@') && (*TERM_data_ptr <= '_')) + *Temp = *TERM_data_ptr - '@'; + else if (*TERM_data_ptr == '?') + *Temp = 127; + TERM_data_ptr++; + Temp++; + } + else + *Temp++ = *TERM_data_ptr++; + } + *Temp = (char)NULL; + param = String; + } + else + { + while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != ':')) + TERM_data_ptr++; + } + return(param); +} + +int +tc_Get_int(param) /* read the integer */ +int param; +{ + int Itemp; + + if (param == 0) + { + while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '#')) + TERM_data_ptr++; + TERM_data_ptr++; + Itemp = AtoI(); + param = Itemp; + } + else + { + while (*TERM_data_ptr != ':') + TERM_data_ptr++; + } + return(param); +} + +void +Find_term() /* find terminal description in termcap file */ +{ + char *Name; + char *Ftemp; + + Ftemp = Name = malloc(strlen(TERMINAL_TYPE + 1) + 1); + strcpy(Name, TERMINAL_TYPE); + while (*Ftemp != (char)NULL) + Ftemp++; + *Ftemp++ = '|'; + *Ftemp = (char)NULL; + CFOUND = FALSE; + Data_Line_len = strlen(TERMINAL_TYPE) + 1; + while ((!CFOUND) && ((TERM_data_ptr=fgets(Data_Line, 512, TFP)) != NULL)) + { + if ((*TERM_data_ptr != ' ') && (*TERM_data_ptr != '\t') && (*TERM_data_ptr != '#')) + { + while ((!CFOUND) && (*TERM_data_ptr != (char)NULL)) + { + CFOUND = !strncmp(TERM_data_ptr, Name, Data_Line_len); + while ((*TERM_data_ptr != (char)NULL) && (*TERM_data_ptr != '|') && (*TERM_data_ptr != '#') && (*TERM_data_ptr != ':')) + TERM_data_ptr++; + if (*TERM_data_ptr == '|') + TERM_data_ptr++; + else if (!CFOUND) + *TERM_data_ptr = (char)NULL; + } + } + } + if (!CFOUND) + { + printf("terminal type %s not found\n", TERMINAL_TYPE); + exit(0); + } +} + +void +CAP_PARSE() /* parse off the data in the termcap data file */ +{ + int offset; + int found; + + do + { + while (*TERM_data_ptr != (char)NULL) + { + for (found = FALSE, offset = 0; (!found) && (offset < 26); offset++) + { + if (!strncmp(TERM_data_ptr, Boolean_names[offset], 2)) + { + found = TRUE; + Booleans[offset] = TRUE; + } + } + if (!found) + { + for (found = FALSE, offset = 0; (!found) && (offset < lw__); offset++) + { + if (!strncmp(TERM_data_ptr, Number_names[offset], 3)) + { + found = TRUE; + Numbers[offset] = tc_Get_int(Numbers[offset]); + } + } + } + if (!found) + { + for (found = FALSE, offset = 0; (!found) && (offset < smgr__); offset++) + { + if (!strncmp(TERM_data_ptr, String_names[offset], 3)) + { + found = TRUE; + String_table[offset] = String_Get(String_table[offset]); + } + } + } + + if (!strncmp(TERM_data_ptr, "tc=", 3)) + tc_ = String_Get(NULL); + while ((*TERM_data_ptr != ':') && (*TERM_data_ptr != (char)NULL)) + TERM_data_ptr++; + if (*TERM_data_ptr == ':') + TERM_data_ptr++; + } + } while (((TERM_data_ptr = fgets(Data_Line, 512, TFP)) != NULL) && ((*TERM_data_ptr == ' ') || (*TERM_data_ptr == '\t'))); + if (tc_ != NULL) + { + TERMINAL_TYPE = tc_; + rewind(TFP); + Find_term(); + tc_ = NULL; + CAP_PARSE(); + } + else + fclose(TFP); +} +#endif /* ifdef CAP */ + +struct _line * +Screenalloc(columns) +int columns; +{ + int i; + struct _line *tmp; + + tmp = (struct _line *) malloc(sizeof (struct _line)); + tmp->row = malloc(columns + 1); + tmp->attributes = malloc(columns + 1); + tmp->prev_screen = NULL; + tmp->next_screen = NULL; + for (i = 0; i < columns; i++) + { + tmp->row[i] = ' '; + tmp->attributes[i] = (char) NULL; + } + tmp->scroll = tmp->changed = FALSE; + tmp->row[0] = (char) NULL; + tmp->attributes[0] = (char) NULL; + tmp->row[columns] = (char) NULL; + tmp->attributes[columns] = (char) NULL; + tmp->last_char = 0; + return(tmp); +} + +WINDOW *newwin(lines, cols, start_l, start_c) +int lines, cols; /* number of lines and columns to be in window */ +int start_l, start_c; /* starting line and column to be inwindow */ +{ + WINDOW *Ntemp; + struct _line *temp_screen; + int i; + + Ntemp = (WINDOW *) malloc(sizeof(WINDOW)); + Ntemp->SR = start_l; + Ntemp->SC = start_c; + Ntemp->Num_lines = lines; + Ntemp->Num_cols = cols; + Ntemp->LX = 0; + Ntemp->LY = 0; + Ntemp->scroll_down = Ntemp->scroll_up = 0; + Ntemp->SCROLL_CLEAR = FALSE; + Ntemp->Attrib = FALSE; + Ntemp->first_line = temp_screen = Screenalloc(cols); + Ntemp->first_line->number = 0; + Ntemp->line_array = (struct _line **) malloc(LINES * sizeof(struct _line *)); + + Ntemp->line_array[0] = Ntemp->first_line; + + for (i = 1; i < lines; i++) + { + temp_screen->next_screen = Screenalloc(cols); + temp_screen->next_screen->number = i; + temp_screen->next_screen->prev_screen = temp_screen; + temp_screen = temp_screen->next_screen; + Ntemp->line_array[i] = temp_screen; + } + Ntemp->first_line->prev_screen = NULL; + temp_screen->next_screen = NULL; + return(Ntemp); +} + +#ifdef CAP +void +Cap_Out(string, p_list, place) /* interpret the output string if necessary */ +char *string; +int p_list[]; /* stack of values */ +int place; /* place keeper of top of stack */ +{ + char *Otemp; /* temporary string pointer to parse output */ + int delay; + int p1, p2, temp; + float chars; + + if (string == NULL) + return; + + if (p_list != NULL) + { + p1 = p_list[--place]; + p2 = p_list[--place]; + } + delay = 0; + Otemp = string; + if ((*Otemp >= '0') && (*Otemp <= '9')) + { + delay = atoi(Otemp); + while ((*Otemp >= '0') && (*Otemp <= '9')) + Otemp++; + if (*Otemp == '*') + Otemp++; + } + while (*Otemp != (char)NULL) + { + if (*Otemp == '%') + { + Otemp++; + if ((*Otemp == 'd') || (*Otemp == '2') || (*Otemp == '3') || (*Otemp == '.') || (*Otemp == '+')) + { + if (*Otemp == 'd') + printf("%d", p1); + else if (*Otemp == '2') + printf("%02d", p1); + else if (*Otemp == '3') + printf("%03d", p1); + else if (*Otemp == '+') + { + Otemp++; + p1 += *Otemp; + putchar(p1); + } + else if (*Otemp == '.') + putchar(p1); + p1 = p2; + p2 = 0; + } + else if (*Otemp == '>') + { + Otemp++; + if (p1 > *Otemp) + { + Otemp++; + p1 += *Otemp; + } + else + Otemp++; + } + else if (*Otemp == 'r') + { + temp = p1; + p1 = p2; + p2 = temp; + } + else if (*Otemp == 'i') + { + p1++; + p2++; + } + else if (*Otemp == '%') + putchar(*Otemp); + else if (*Otemp == 'n') + { + p1 ^= 0140; + p2 ^= 0140; + } + else if (*Otemp == 'B') + { + p1 = (16 * (p1/10)) + (p1 % 10); + p2 = (16 * (p2/10)) + (p2 % 10); + } + else if (*Otemp == 'D') + { + p1 = (p1 - 2 * (p1 % 16)); + p2 = (p2 - 2 * (p2 % 16)); + } + } + else + putchar (*Otemp); + Otemp++; + } + if (delay != 0) + { + chars = delay * chars_per_millisecond; + delay = chars; + if ((chars - delay) > 0.0) + delay++; + for (; delay > 0; delay--) + putchar(*String_table[pc__]); + } + fflush(stdout); +} + +#else + + char *Otemp; /* temporary string pointer to parse output */ + float chars; + int p[10]; + int variable[27]; + +int +Operation(Temp_Stack, place) /* handle conditional operations */ +int Temp_Stack[]; +int place; +{ + int temp; + + if (*Otemp == 'd') + { + Otemp++; + temp = Temp_Stack[--place]; + printf("%d", temp); + } + else if (!strncmp(Otemp, "2d", 2)) + { + temp = Temp_Stack[--place]; + printf("%2d", temp); + Otemp++; + Otemp++; + } + else if (!strncmp(Otemp, "3d", 2)) + { + temp = Temp_Stack[--place]; + printf("%0d", temp); + Otemp++; + Otemp++; + } + else if (!strncmp(Otemp, "02d", 3)) + { + temp = Temp_Stack[--place]; + printf("%02d", temp); + Otemp++; + Otemp++; + Otemp++; + } + else if (!strncmp(Otemp, "03d", 3)) + { + temp = Temp_Stack[--place]; + printf("%03d", temp); + Otemp++; + Otemp++; + Otemp++; + } + else if (*Otemp == '+') + { + Otemp++; + temp = Temp_Stack[--place]; + temp += Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == '-') + { + Otemp++; + temp = Temp_Stack[--place]; + temp -= Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == '*') + { + Otemp++; + temp = Temp_Stack[--place]; + temp *= Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == '/') + { + Otemp++; + temp = Temp_Stack[--place]; + temp /= Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == 'm') + { + Otemp++; + temp = Temp_Stack[--place]; + temp %= Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == '&') + { + Otemp++; + temp = Temp_Stack[--place]; + temp &= Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == '|') + { + Otemp++; + temp = Temp_Stack[--place]; + temp |= Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == '^') + { + Otemp++; + temp = Temp_Stack[--place]; + temp ^= Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == '=') + { + Otemp++; + temp = Temp_Stack[--place]; + temp = (temp == Temp_Stack[--place]); + Temp_Stack[place++] = temp; + } + else if (*Otemp == '>') + { + Otemp++; + temp = Temp_Stack[--place]; + temp = temp > Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == '<') + { + Otemp++; + temp = Temp_Stack[--place]; + temp = temp < Temp_Stack[--place]; + Temp_Stack[place++] = temp; + } + else if (*Otemp == 'c') + { + Otemp++; + putchar(Temp_Stack[--place]); + } + else if (*Otemp == 'i') + { + Otemp++; + p[1]++; + p[2]++; + } + else if (*Otemp == '%') + { + putchar(*Otemp); + Otemp++; + } + else if (*Otemp == '!') + { + temp = ! Temp_Stack[--place]; + Temp_Stack[place++] = temp; + Otemp++; + } + else if (*Otemp == '~') + { + temp = ~Temp_Stack[--place]; + Temp_Stack[place++] = temp; + Otemp++; + } + else if (*Otemp == 'p') + { + Otemp++; + Temp_Stack[place++] = p[*Otemp - '0']; + Otemp++; + } + else if (*Otemp == 'P') + { + Otemp++; + Temp_Stack[place++] = variable[*Otemp - 'a']; + Otemp++; + } + else if (*Otemp == 'g') + { + Otemp++; + variable[*Otemp - 'a'] = Temp_Stack[--place]; + Otemp++; + } + else if (*Otemp == '\'') + { + Otemp++; + Temp_Stack[place++] = *Otemp; + Otemp++; + Otemp++; + } + else if (*Otemp == '{') + { + Otemp++; + temp = atoi(Otemp); + Temp_Stack[place++] = temp; + while (*Otemp != '}') + Otemp++; + Otemp++; + } + return(place); +} + +void +Info_Out(string, p_list, place) /* interpret the output string if necessary */ +char *string; +int p_list[]; +int place; +{ + char *tchar; + int delay; + int temp; + int Cond_FLAG; + int EVAL; + int Cond_Stack[128]; + int Cond_place; + int Stack[128]; + int Top_of_stack; + + if (string == NULL) + return; + + Cond_FLAG = FALSE; + Cond_place = 0; + Top_of_stack = 0; + p[0] = 0; + p[1] = 0; + p[2] = 0; + p[3] = 0; + p[4] = 0; + p[5] = 0; + p[6] = 0; + p[7] = 0; + p[8] = 0; + p[9] = 0; + if (p_list != NULL) + { + for (temp = 1; (place != 0); temp++) + { + p[temp] = p_list[--place]; + } + } + delay = 0; + Otemp = string; + while (*Otemp != (char) NULL) + { + if (*Otemp == '%') + { + Otemp++; + if ((*Otemp == '?') || (*Otemp == 't') || (*Otemp == 'e') || (*Otemp == ';')) + { + if (*Otemp == '?') + { + Otemp++; + Cond_FLAG = TRUE; + EVAL = TRUE; + while (EVAL) + { + /* + | find the end of the + | conditional statement + */ + while ((strncmp(Otemp, "%t", 2)) && (*Otemp != (char) NULL)) + { + /* + | move past '%' + */ + Otemp++; + Cond_place = Operation(Cond_Stack, Cond_place); + } + + /* + | if condition is true + */ + if ((Cond_place > 0) && (Cond_Stack[Cond_place-1])) + { + /* + | end conditional + | parsing + */ + EVAL = FALSE; + Otemp++; + Otemp++; + } + else /* condition is false */ + { + /* + | find 'else' or end + | of if statement + */ + while ((strncmp(Otemp, "%e", 2)) && (strncmp(Otemp, "%;", 2)) && (*Otemp != (char) NULL)) + Otemp++; + /* + | if an 'else' found + */ + if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%e", 2))) + { + Otemp++; + Otemp++; + tchar = Otemp; + /* + | check for 'then' part + */ + while ((*tchar != (char) NULL) && (strncmp(tchar, "%t", 2)) && (strncmp(tchar, "%;", 2))) + tchar++; + /* + | if end of string + */ + if (*tchar == (char) NULL) + { + EVAL = FALSE; + Cond_FLAG = FALSE; + Otemp = tchar; + } + /* + | if end of if found, + | set up to parse + | info + */ + else if (!strncmp(tchar, "%;", 2)) + EVAL = FALSE; + /* + | otherwise, check + | conditional in + | 'else' + */ + } + /* + | if end of if found, + | get out of if + | statement + */ + else if ((*Otemp != (char) NULL) && (!strncmp(Otemp, "%;", 2))) + { + EVAL = FALSE; + Otemp++; + Otemp++; + } + else /* Otemp == NULL */ + { + EVAL = FALSE; + Cond_FLAG = FALSE; + } + } + } + } + else + { + Otemp++; + Cond_FLAG = FALSE; + if (*Otemp != ';') + { + while ((*Otemp != (char) NULL) && (strncmp(Otemp, "%;", 2))) + Otemp++; + if (*Otemp != (char) NULL) + { + Otemp++; + Otemp++; + } + } + else + Otemp++; + } + } + else + { + Top_of_stack = Operation(Stack, Top_of_stack); + } + } + else if (!strncmp(Otemp, "$<", 2)) + { + Otemp++; + Otemp++; + delay = atoi(Otemp); + while (*Otemp != '>') + Otemp++; + Otemp++; + chars = delay * chars_per_millisecond; + delay = chars; + if ((chars - delay) > 0.0) + delay++; + if (String_table[pc__] == NULL) + temp = 0; + else + temp = *String_table[pc__]; + for (; delay > 0; delay--) + putc(temp, stdout); + } + else + { + putchar(*Otemp); + Otemp++; + } + } + fflush(stdout); +} +#endif + +void +wmove(window, row, column) /* move cursor to indicated position in window */ +WINDOW *window; +int row, column; +{ + if ((row < window->Num_lines) && (column < window->Num_cols)) + { + window->LX = column; + window->LY = row; + } +} + +void +clear_line(line, column, cols) +struct _line *line; +int column; +int cols; +{ + int j; + + if (column > line->last_char) + { + for (j = line->last_char; j < column; j++) + { + line->row[j] = ' '; + line->attributes[j] = (char) NULL; + } + } + line->last_char = column; + line->row[column] = (char) NULL; + line->attributes[column] = (char) NULL; + line->changed = TRUE; +} + +void +werase(window) /* clear the specified window */ +WINDOW *window; +{ + int i; + struct _line *tmp; + + window->SCROLL_CLEAR = CLEAR; + window->scroll_up = window->scroll_down = 0; + for (i = 0, tmp = window->first_line; i < window->Num_lines; i++, tmp = tmp->next_screen) + clear_line(tmp, 0, window->Num_cols); +} + +void +wclrtoeol(window) /* erase from current cursor position to end of line */ +WINDOW *window; +{ + int column, row; + struct _line *tmp; + + window->SCROLL_CLEAR = CHANGE; + column = window->LX; + row = window->LY; + for (row = 0, tmp = window->first_line; row < window->LY; row++) + tmp = tmp->next_screen; + clear_line(tmp, column, window->Num_cols); +} + +void +wrefresh(window) /* flush all previous output */ +WINDOW *window; +{ + wnoutrefresh(window); +#ifdef DIAG +{ + struct _line *temp; + int value; + fprintf(stderr, "columns=%d, lines=%d, SC=%d, SR=%d\n",window->Num_cols, window->Num_lines, window->SC, window->SR); + for (value = 0, temp = window->first_line; value < window->Num_lines; value++, temp = temp->next_screen) + { + if (temp->number == -1) + fprintf(stderr, "line moved "); + if (temp->scroll) + fprintf(stderr, "scroll_x is set: "); + fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row); + } + fprintf(stderr, "+-------------------- virtual screen ----------------------------------------+\n"); + fprintf(stderr, "columns=%d, lines=%d \n",virtual_scr->Num_cols, virtual_scr->Num_lines); + for (value = 0, temp = virtual_scr->first_line; value < virtual_scr->Num_lines; value++, temp = temp->next_screen) + { + if (temp->number == -1) + fprintf(stderr, "line moved "); + if (temp->scroll) + fprintf(stderr, "scroll_x is set: "); + fprintf(stderr, "lc%d=%s|\n", temp->last_char, temp->row); + } + fprintf(stderr, "columns=%d, lines=%d \n",curscr->Num_cols, curscr->Num_lines); + for (value = 0, temp = curscr->first_line; value < curscr->Num_lines; value++, temp = temp->next_screen) + fprintf(stderr, "line=%s|\n", temp->row); +} +#endif + doupdate(); + virtual_scr->SCROLL_CLEAR = FALSE; + virtual_scr->scroll_down = virtual_scr->scroll_up = 0; + fflush(stdout); +} + +void +touchwin(window) +WINDOW *window; +{ + struct _line *user_line; + int line_counter = 0; + + for (line_counter = 0, user_line = window->first_line; + line_counter < window->Num_lines; line_counter++) + { + user_line->changed = TRUE; + } + window->SCROLL_CLEAR = TRUE; +} + +void +wnoutrefresh(window) +WINDOW *window; +{ + struct _line *user_line; + struct _line *virtual_line; + int line_counter = 0; + int user_col = 0; + int virt_col = 0; + + if (window->SR >= virtual_scr->Num_lines) + return; + user_line = window->first_line; + virtual_line = virtual_scr->first_line; + virtual_scr->SCROLL_CLEAR = window->SCROLL_CLEAR; + virtual_scr->LX = window->LX + window->SC; + virtual_scr->LY = window->LY + window->SR; + virtual_scr->scroll_up = window->scroll_up; + virtual_scr->scroll_down = window->scroll_down; + if ((last_window_refreshed == window) && (!window->SCROLL_CLEAR)) + return; + for (line_counter = 0; line_counter < window->SR; line_counter++) + { + virtual_line = virtual_line->next_screen; + } + for (line_counter = 0; (line_counter < window->Num_lines) + && ((line_counter + window->SR) < virtual_scr->Num_lines); + line_counter++) + { + if ((last_window_refreshed != window) || (user_line->changed) || ((SCROLL | CLEAR) & window->SCROLL_CLEAR)) + { + for (user_col = 0, virt_col = window->SC; + (virt_col < virtual_scr->Num_cols) + && (user_col < user_line->last_char); + virt_col++, user_col++) + { + virtual_line->row[virt_col] = user_line->row[user_col]; + virtual_line->attributes[virt_col] = user_line->attributes[user_col]; + } + for (user_col = user_line->last_char, + virt_col = window->SC + user_line->last_char; + (virt_col < virtual_scr->Num_cols) + && (user_col < window->Num_cols); + virt_col++, user_col++) + { + virtual_line->row[virt_col] = ' '; + virtual_line->attributes[virt_col] = (char) NULL; + } + } + if (virtual_scr->Num_cols != window->Num_cols) + { + if (virtual_line->last_char < (user_line->last_char + window->SC)) + { + if (virtual_line->row[virtual_line->last_char] == (char) NULL) + virtual_line->row[virtual_line->last_char] = ' '; + virtual_line->last_char = + min(virtual_scr->Num_cols, + (user_line->last_char + window->SC)); + } + } + else + virtual_line->last_char = user_line->last_char; + virtual_line->row[virtual_line->last_char] = (char) NULL; + virtual_line->changed = user_line->changed; + virtual_line = virtual_line->next_screen; + user_line = user_line->next_screen; + } + window->SCROLL_CLEAR = FALSE; + window->scroll_up = window->scroll_down = 0; + last_window_refreshed = window; +} + +void +flushinp() /* flush input */ +{ +} + +void +ungetch(c) /* push a character back on input */ +int c; +{ + if (bufp < 100) + in_buff[bufp++] = c; +} + +#ifdef BSD_SELECT +int +timed_getchar() +{ + struct timeval tv; + fd_set fds; + int ret_val; + int nfds = 1; + char temp; + + FD_ZERO(&fds); + tv.tv_sec = 0; + tv.tv_usec = 500000; /* half a second */ + FD_SET(0, &fds); + Time_Out = FALSE; /* just in case */ + + ret_val = select(nfds, &fds, 0, 0, &tv); + + /* + | if ret_val is less than zero, there was no input + | otherwise, get a character and return it + */ + + if (ret_val <= 0) + { + Time_Out = TRUE; + return(-1); + } + + return(read(0, &temp, 1)? temp : -1); +} +#endif + +int +wgetch(window) /* get character from specified window */ +WINDOW *window; +{ + int in_value; + char temp; +#ifndef SYS5 + int old_arg; +#endif /* SYS5 */ + +#ifdef BSD_SELECT + if (Noblock) + in_value = ((bufp > 0) ? in_buff[--bufp] : timed_getchar()); + else + in_value = ((bufp > 0) ? in_buff[--bufp] : read(0, &temp, 1)? temp : -1); +#else /* BSD_SELECT */ +#ifdef SYS5 + in_value = ((bufp > 0) ? in_buff[--bufp] : + (read(0, &temp, 1)> 0) ? temp : -1); +#else /* SYS5 */ + if (Noblock) + { + Time_Out = FALSE; + old_arg = fcntl(0, F_GETFL, 0); + in_value = fcntl(0, F_SETFL, old_arg | FNDELAY); + } + in_value = ((bufp > 0) ? in_buff[--bufp] : read(0, &temp, 1)? temp : -1); + if (Noblock) + { + fcntl(0, F_SETFL, old_arg); + if (Time_Out) + in_value = -1; + } +#endif /* SYS5 */ +#endif /* BSD_SELECT */ + + if (in_value != -1) + { + in_value &= 0xff; + if ((Parity) && (Num_bits < 8)) + /* strip eighth bit if parity in use */ + in_value &= 0177; + } + else if (interrupt_flag) + { + interrupt_flag = FALSE; + in_value = wgetch(window); + } + + if ((in_value == '\033') || (in_value == '\037'))/* escape character */ + in_value = Get_key(in_value); + return(in_value); +} + +#ifndef BSD_SELECT +void +Clear(arg) /* notify that time out has occurred */ +int arg; +{ + Time_Out = TRUE; +#ifdef DEBUG +fprintf(stderr, "inside Clear()\n"); +fflush(stderr); +#endif /* DEBUG */ +} +#endif /* BSD_SELECT */ + +int +Get_key(first_char) /* try to decode key sequence */ +int first_char; /* first character of sequence */ +{ + int in_char; + int Count; + char string[128]; + char *Gtemp; + int Found; +#ifdef SYS5 + struct termio Gterminal; +#else + struct sgttyb Gterminal; +#endif + struct KEY_STACK *St_point; +#if (!defined( BSD_SELECT)) || (!defined(SYS5)) + int value; +#endif /* BSD_SELECT */ + + Count = 0; + Gtemp = string; + string[Count++] = first_char; + string[Count] = (char) NULL; + Time_Out = FALSE; +#ifndef BSD_SELECT + signal(SIGALRM, Clear); + value = alarm(1); +#endif /* BSD_SELECT */ + Noblock = TRUE; +#ifdef SYS5 + Gterminal.c_cc[VTIME] = 0; /* timeout value */ + Gterminal.c_lflag &= ~ICANON; /* disable canonical operation */ + Gterminal.c_lflag &= ~ECHO; /* disable echo */ +#endif + Count = 1; + Found = FALSE; + while ((Count < Max_Key_len) && (!Time_Out) && (!Found)) + { + in_char = wgetch(stdscr); +#ifdef DEBUG +fprintf(stderr, "back in GetKey()\n"); +fflush(stderr); +#endif /* DEBUG */ + if (in_char != -1) + { + string[Count++] = in_char; + string[Count] = (char) NULL; + St_point = KEY_TOS; + while ((St_point != NULL) && (!Found)) + { + if (!strcmp(string, St_point->element->string)) + Found = TRUE; + else + St_point = St_point->next; + } + } + } +#ifndef BSD_SELECT + if (!Time_Out) + value = alarm(0); +#endif /* BSD_SELECT */ +#ifdef SYS5 +/* value = ioctl(0, TCSETA, &Terminal);*/ +#else + value = ioctl(0, TIOCSETP, &Terminal); +/* value = fcntl(0, F_SETFL, old_arg);*/ +#endif + Noblock = FALSE; + if (Found) + { + return(St_point->element->value); + } + else + { + while (Count > 1) + { + if ((string[--Count] != -1) && + ((unsigned char) (string[Count]) != 255)) + { +#ifdef DIAG +fprintf(stderr, "ungetting character %d\n", string[Count]);fflush(stdout); +#endif + ungetch(string[Count]); + } + } + return(first_char); + } +} + +void +waddch(window, c) /* output the character in the specified window */ +WINDOW *window; +int c; +{ + int column, j; + int shift; /* number of spaces to shift if a tab */ + struct _line *tmpline; + +#ifdef DIAG +/*printf("starting waddch \n");fflush(stdout);*/ +#endif + column = window->LX; + if (c == '\t') + { + shift = (column + 1) % 8; + if (shift == 0) + shift++; + else + shift = 9 - shift; + while (shift > 0) + { + shift--; + waddch(window, ' '); + } + } + else if ((column < window->Num_cols) && (window->LY < window->Num_lines)) + { + if ((c == '~') && (Booleans[hz__])) + c = '@'; + + if (( c != '\b') && (c != '\n') && (c != '\r')) + { + tmpline = window->line_array[window->LY]; + tmpline->row[column] = c; + tmpline->attributes[column] = window->Attrib; + tmpline->changed = TRUE; + if (column >= tmpline->last_char) + { + if (column > tmpline->last_char) + for (j = tmpline->last_char; j < column; j++) + { + tmpline->row[j] = ' '; + tmpline->attributes[j] = (char) NULL; + } + tmpline->row[column + 1] = (char) NULL; + tmpline->attributes[column + 1] = (char) NULL; + tmpline->last_char = column + 1; + } + } + if (c == '\n') + { + wclrtoeol(window); + window->LX = window->Num_cols; + } + else if (c == '\r') + window->LX = 0; + else if (c == '\b') + window->LX--; + else + window->LX++; + } + if (window->LX >= window->Num_cols) + { + window->LX = 0; + window->LY++; + if (window->LY >= window->Num_lines) + { + window->LY = window->Num_lines - 1; +/* window->LY = row; + wmove(window, 0, 0); + wdeleteln(window); + wmove(window, row, 0);*/ + } + } + window->SCROLL_CLEAR = CHANGE; +} + +void +winsertln(window) /* insert a blank line into the specified window */ +WINDOW *window; +{ + int row, column; + struct _line *tmp; + struct _line *tmp1; + + window->scroll_down += 1; + window->SCROLL_CLEAR = SCROLL; + column = window->LX; + row = window->LY; + for (row = 0, tmp = window->first_line; (row < window->Num_lines) && (tmp->next_screen != NULL); row++) + tmp = tmp->next_screen; + if (tmp->prev_screen != NULL) + tmp->prev_screen->next_screen = NULL; + tmp1 = tmp; + clear_line(tmp1, 0, window->Num_cols); + tmp1->number = -1; + for (row = 0, tmp = window->first_line; (row < window->LY) && (tmp->next_screen != NULL); row++) + tmp = tmp->next_screen; + if ((window->LY == (window->Num_lines - 1)) && (window->Num_lines > 1)) + { + tmp1->next_screen = tmp->next_screen; + tmp->next_screen = tmp1; + tmp->changed = TRUE; + tmp->next_screen->prev_screen = tmp; + } + else if (window->Num_lines > 1) + { + if (tmp->prev_screen != NULL) + tmp->prev_screen->next_screen = tmp1; + tmp1->prev_screen = tmp->prev_screen; + tmp->prev_screen = tmp1; + tmp1->next_screen = tmp; + tmp->changed = TRUE; + tmp->scroll = DOWN; + } + if (window->LY == 0) + window->first_line = tmp1; + + for (row = 0, tmp1 = window->first_line; + row < window->Num_lines; row++) + { + window->line_array[row] = tmp1; + tmp1 = tmp1->next_screen; + } +} + +void +wdeleteln(window) /* delete a line in the specified window */ +WINDOW *window; +{ + int row, column; + struct _line *tmp; + struct _line *tmpline; + + if (window->Num_lines > 1) + { + window->scroll_up += 1; + window->SCROLL_CLEAR = SCROLL; + column = window->LX; + row = window->LY; + for (row = 0, tmp = window->first_line; row < window->LY; row++) + tmp = tmp->next_screen; + if (window->LY == 0) + window->first_line = tmp->next_screen; + if (tmp->prev_screen != NULL) + tmp->prev_screen->next_screen = tmp->next_screen; + if (tmp->next_screen != NULL) + { + tmp->next_screen->changed = TRUE; + tmp->next_screen->scroll = UP; + tmp->next_screen->prev_screen = tmp->prev_screen; + } + tmpline = tmp; + clear_line(tmpline, 0, window->Num_cols); + tmpline->number = -1; + for (row = 0, tmp = window->first_line; tmp->next_screen != NULL; row++) + tmp = tmp->next_screen; + if (tmp != NULL) + { + tmp->next_screen = tmpline; + tmp->next_screen->prev_screen = tmp; + tmp->changed = TRUE; + tmp = tmp->next_screen; + } + else + tmp = tmpline; + tmp->next_screen = NULL; + + for (row = 0, tmp = window->first_line; row < window->Num_lines; row++) + { + window->line_array[row] = tmp; + tmp = tmp->next_screen; + } + } + else + { + clear_line(window->first_line, 0, window->Num_cols); + } +} + +void +wclrtobot(window) /* delete from current position to end of the window */ +WINDOW *window; +{ + int row, column; + struct _line *tmp; + + window->SCROLL_CLEAR |= CLEAR; + column = window->LX; + row = window->LY; + for (row = 0, tmp = window->first_line; row < window->LY; row++) + tmp = tmp->next_screen; + clear_line(tmp, column, window->Num_cols); + for (row = (window->LY + 1); row < window->Num_lines; row++) + { + tmp = tmp->next_screen; + clear_line(tmp, 0, window->Num_cols); + } + wmove(window, row, column); +} + +void +wstandout(window) /* begin standout mode in window */ +WINDOW *window; +{ + if (Numbers[sg__] < 1) /* if not magic cookie glitch */ + window->Attrib |= A_STANDOUT; +} + +void +wstandend(window) /* end standout mode in window */ +WINDOW *window; +{ + window->Attrib &= ~A_STANDOUT; +} + +void +waddstr(window, string) /* write 'string' in window */ +WINDOW *window; +char *string; +{ + char *wstring; + + for (wstring = string; *wstring != (char) NULL; wstring++) + waddch(window, *wstring); +} + +void +clearok(window, flag) /* erase screen and redraw at next refresh */ +WINDOW *window; +int flag; +{ + Repaint_screen = TRUE; +} + + +void +echo() /* turn on echoing */ +{ + int value; + +#ifdef SYS5 + Terminal.c_lflag |= ECHO; /* enable echo */ + value = ioctl(0, TCSETA, &Terminal); /* set characteristics */ +#else + Terminal.sg_flags |= ECHO; /* enable echo */ + value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */ +#endif +} + +void +noecho() /* turn off echoing */ +{ + int value; + +#ifdef SYS5 + Terminal.c_lflag &= ~ECHO; /* disable echo */ + value = ioctl(0, TCSETA, &Terminal); /* set characteristics */ +#else + Terminal.sg_flags &= ~ECHO; /* disable echo */ + value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */ +#endif +} + +void +raw() /* set to read characters immediately */ +{ + int value; + +#ifdef SYS5 + Intr = Terminal.c_cc[VINTR]; /* get the interrupt character */ + Terminal.c_lflag &= ~ICANON; /* disable canonical operation */ + Terminal.c_lflag &= ~ISIG; /* disable signal checking */ +#ifdef FLUSHO + Terminal.c_lflag &= ~FLUSHO; +#endif +#ifdef PENDIN + Terminal.c_lflag &= ~PENDIN; +#endif +#ifdef IEXTEN + Terminal.c_lflag &= ~IEXTEN; +#endif + Terminal.c_cc[VMIN] = 1; /* minimum of one character */ + Terminal.c_cc[VTIME] = 0; /* timeout value */ + Terminal.c_cc[VINTR] = 0; /* eliminate interrupt */ + value = ioctl(0, TCSETA, &Terminal); /* set characteristics */ +#else + Terminal.sg_flags |= RAW; /* enable raw mode */ + value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */ +#endif +} + +void +noraw() /* set to normal character read mode */ +{ + int value; + +#ifdef SYS5 + Terminal.c_lflag |= ICANON; /* enable canonical operation */ + Terminal.c_lflag |= ISIG; /* enable signal checking */ + Terminal.c_cc[VEOF] = 4; /* EOF character = 4 */ + Terminal.c_cc[VEOL] = (char) NULL; /* EOL = 0 */ + Terminal.c_cc[VINTR] = Intr; /* reset interrupt char */ + value = ioctl(0, TCSETA, &Terminal); /* set characteristics */ +#else + Terminal.sg_flags &= ~RAW; /* disable raw mode */ + value = ioctl(0, TIOCSETP, &Terminal); /* set characteristics */ +/* old_arg = fcntl(0, F_GETFL, 0); + value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/ +#endif +} + +void +nl() +{ + int value; + +#ifdef SYS5 + Terminal.c_iflag |= ICRNL; /* enable carriage-return to line-feed mapping */ + value = ioctl(0, TCSETA, &Terminal); /* set characteristics */ +#endif +} + +void +nonl() +{ + int value; + +#ifdef SYS5 + Terminal.c_iflag &= ~ICRNL; /* disable carriage-return to line-feed mapping */ + Terminal.c_iflag &= ~IGNCR; /* do not ignore carriage-return */ + value = ioctl(0, TCSETA, &Terminal); /* set characteristics */ +#endif +} + +void +saveterm() +{ +} + +void +fixterm() +{ +} + +void +resetterm() +{ +} + +void +nodelay(window, flag) +WINDOW *window; +int flag; +{ +} + +void +idlok(window, flag) +WINDOW *window; +int flag; +{ +} + +void +keypad(window, flag) +WINDOW *window; +int flag; +{ + if (flag) + String_Out(String_table[ks__], NULL, 0); + else + String_Out(String_table[ke__], NULL, 0); +} + +void +savetty() /* save current tty stats */ +{ + int value; + +#ifdef SYS5 + value = ioctl(0, TCGETA, &Saved_tty); /* set characteristics */ +#else + value = ioctl(0, TIOCGETP, &Saved_tty); /* set characteristics */ +#endif +} + +void +resetty() /* restore previous tty stats */ +{ + int value; + +#ifdef SYS5 + value = ioctl(0, TCSETA, &Saved_tty); /* set characteristics */ +#else + value = ioctl(0, TIOCSETP, &Saved_tty); /* set characteristics */ +#endif +} + +void +endwin() /* end windows */ +{ + keypad(stdscr, FALSE); + initialized = FALSE; + delwin(curscr); + delwin(virtual_scr); + delwin(stdscr); +#ifndef SYS5 +{ + int old_arg, value; +/* old_arg = fcntl(0, F_GETFL, 0); + value = fcntl(0, F_SETFL, old_arg & ~FNDELAY);*/ +} +#endif +} + +void +delwin(window) /* delete the window structure */ +WINDOW *window; +{ + int i; + + for (i = 1; (i < window->Num_lines) && (window->first_line->next_screen != NULL); i++) + { + window->first_line = window->first_line->next_screen; + free(window->first_line->prev_screen->row); + free(window->first_line->prev_screen->attributes); + free(window->first_line->prev_screen); + } + if (window == last_window_refreshed) + last_window_refreshed = 0; + if (window->first_line != NULL) + { + free(window->first_line->row); + free(window->first_line->attributes); + free(window->first_line); + free(window); + } +} + +#ifndef __STDC__ +void +wprintw(va_alist) +va_dcl +#else /* __STDC__ */ +void +wprintw(WINDOW *window, const char *format, ...) +#endif /* __STDC__ */ +{ +#ifndef __STDC__ + WINDOW *window; + char *format; + va_list ap; +#else + va_list ap; +#endif + int value; + char *fpoint; + char *wtemp; + +#ifndef __STDC__ + va_start(ap); + window = va_arg(ap, WINDOW *); + format = va_arg(ap, char *); +#else /* __STDC__ */ + va_start(ap, format); +#endif /* __STDC__ */ + + fpoint = (char *) format; + while (*fpoint != (char) NULL) + { + if (*fpoint == '%') + { + fpoint++; + if (*fpoint == 'd') + { + value = va_arg(ap, int); + iout(window, value); + } + else if (*fpoint == 'c') + { + value = va_arg(ap, int); + waddch(window, value); + } + else if (*fpoint == 's') + { + wtemp = va_arg(ap, char *); + waddstr(window, wtemp); + } + fpoint++; + } + else if (*fpoint == '\\') + { + fpoint++; + if (*fpoint == 'n') + waddch(window, '\n'); + else if ((*fpoint >= '0') && (*fpoint <= '9')) + { + value = 0; + while ((*fpoint >= '0') && (*fpoint <= '9')) + { + value = (value * 8) + (*fpoint - '0'); + fpoint++; + } + waddch(window, value); + } + fpoint++; + } + else + waddch(window, *fpoint++); + } +#ifdef __STDC__ + va_end(ap); +#endif /* __STDC__ */ +} + +void +iout(window, value) /* output characters */ +WINDOW *window; +int value; +{ + int i; + + if ((i = value / 10) != 0) + iout(window, i); + waddch(window, ((value % 10) + '0')); +} + +int +Comp_line(line1, line2) /* compare lines */ +struct _line *line1; +struct _line *line2; +{ + int count1; + int i; + char *att1, *att2; + char *c1, *c2; + + if (line1->last_char != line2->last_char) + return(2); + + c1 = line1->row; + c2 = line2->row; + att1 = line1->attributes; + att2 = line2->attributes; + i = 0; + while ((c1[i] != (char) NULL) && (c2[i] != (char) NULL) && (c1[i] == c2[i]) && (att1[i] == att2[i])) + i++; + count1 = i + 1; + if ((count1 == 1) && (c1[i] == (char) NULL) && (c2[i] == (char) NULL)) + count1 = 0; /* both lines blank */ + else if ((c1[i] == (char) NULL) && (c2[i] == (char) NULL)) + count1 = -1; /* equal */ + else + count1 = 1; /* lines unequal */ + return(count1); +} + +struct _line * +Insert_line(row, end_row, window) /* insert line into screen */ +int row; +int end_row; +WINDOW *window; +{ + int i; + struct _line *tmp; + struct _line *tmp1; + + for (i = 0, tmp = curscr->first_line; i < window->SR; i++) + tmp = tmp->next_screen; + if ((end_row + window->SR) == 0) + curscr->first_line = curscr->first_line->next_screen; + top_of_win = tmp; + /* + | find bottom line to delete + */ + for (i = 0, tmp = top_of_win; (tmp->next_screen != NULL) && (i < end_row); i++) + tmp = tmp->next_screen; + if (tmp->prev_screen != NULL) + tmp->prev_screen->next_screen = tmp->next_screen; + if (tmp->next_screen != NULL) + tmp->next_screen->prev_screen = tmp->prev_screen; + tmp1 = tmp; + /* + | clear deleted line + */ + clear_line(tmp, 0, window->Num_cols); + tmp1->number = -1; + for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++) + tmp = tmp->next_screen; + top_of_win = tmp; + for (i = 0, tmp = top_of_win; i < row; i++) + tmp = tmp->next_screen; + if ((tmp->prev_screen != NULL) && (window->Num_lines > 0)) + tmp->prev_screen->next_screen = tmp1; + tmp1->prev_screen = tmp->prev_screen; + tmp->prev_screen = tmp1; + tmp1->next_screen = tmp; + if ((row + window->SR) == 0) + curscr->first_line = tmp1; + if (tmp1->next_screen != NULL) + tmp1 = tmp1->next_screen; + + if ((!String_table[cs__]) && (end_row < window->Num_lines)) + { + Position(window, (window->SR + end_row), 0); + String_Out(String_table[dl__], NULL, 0); + } + Position(window, (window->SR + row), 0); + if (String_table[al__] != NULL) + String_Out(String_table[al__], NULL, 0); + else + String_Out(String_table[sr__], NULL, 0); + + for (i = 0, top_of_win = curscr->first_line; (top_of_win->next_screen != NULL) && (i < window->SR); i++) + top_of_win = top_of_win->next_screen; + return(tmp1); +} + + +struct _line * +Delete_line(row, end_row, window) /* delete a line on screen */ +int row; +int end_row; +WINDOW *window; +{ + int i; + struct _line *tmp; + struct _line *tmp1; + struct _line *tmp2; + + i = 0; + tmp = curscr->first_line; + while (i < window->SR) + { + i++; + tmp = tmp->next_screen; + } + /* + | find line to delete + */ + top_of_win = tmp; + if ((row + window->SR) == 0) + curscr->first_line = top_of_win->next_screen; + for (i = 0, tmp = top_of_win; i < row; i++) + tmp = tmp->next_screen; + if (tmp->prev_screen != NULL) + tmp->prev_screen->next_screen = tmp->next_screen; + if (tmp->next_screen != NULL) + tmp->next_screen->prev_screen = tmp->prev_screen; + tmp2 = tmp->next_screen; + tmp1 = tmp; + /* + | clear deleted line + */ + clear_line(tmp1, 0, window->Num_cols); + tmp1->number = -1; + /* + | find location to insert deleted line + */ + for (i = 0, tmp = curscr->first_line; (tmp->next_screen != NULL) && (i < window->SR); i++) + tmp = tmp->next_screen; + top_of_win = tmp; + for (i = 0, tmp = top_of_win; (i < end_row) && (tmp->next_screen != NULL); i++) + tmp = tmp->next_screen; + tmp1->next_screen = tmp; + tmp1->prev_screen = tmp->prev_screen; + if (tmp1->prev_screen != NULL) + tmp1->prev_screen->next_screen = tmp1; + tmp->prev_screen = tmp1; + + Position(window, (window->SR + row), 0); + String_Out(String_table[dl__], NULL, 0); + if ((!String_table[cs__]) && (end_row < window->Num_lines)) + { + Position(window, (window->SR + end_row), 0); + String_Out(String_table[al__], NULL, 0); + } + else if ((String_table[cs__] != NULL) && (String_table[dl__] == NULL)) + { + Position(window, (window->SR + end_row), 0); + putchar('\n'); + } + + if (row == (window->Num_lines-1)) + tmp2 = tmp1; + if ((row + window->SR) == 0) + curscr->first_line = top_of_win = tmp2; + return(tmp2); +} + +void +CLEAR_TO_EOL(window, row, column) +WINDOW *window; +int row, column; +{ + int x, y; + struct _line *tmp1; + + for (y = 0, tmp1 = curscr->first_line; (y < (window->SR+row)) && (tmp1->next_screen != NULL); y++) + tmp1 = tmp1->next_screen; + for (x = column; x<window->Num_cols; x++) + { + tmp1->row[x] = ' '; + tmp1->attributes[x] = (char) NULL; + } + tmp1->row[column] = (char) NULL; + tmp1->last_char = column; + if (column < COLS) + { + if (STAND) + { + STAND = FALSE; + Position(window, row, column); + attribute_off(); + } + if (String_table[ce__] != NULL) + String_Out(String_table[ce__], NULL, 0); + else + { + for (x = column; x < window->Num_cols; x++) + putchar(' '); + Curr_x = x; + } + } +} + +int +check_delete(window, line, offset, pointer_new, pointer_old) +WINDOW *window; +int line, offset; +struct _line *pointer_new, *pointer_old; +{ + int end_old; + int end_new; + int k; + int changed; + char *old_lin; + char *new_lin; + char *old_att; + char *new_att; + + changed = FALSE; + new_lin = pointer_new->row; + new_att = pointer_new->attributes; + old_lin = pointer_old->row; + old_att = pointer_old->attributes; + end_old = end_new = offset; + while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (old_lin[end_old] != (char) NULL) && (new_lin[end_old] != (char) NULL)) + end_old++; + if (old_lin[end_old] != (char) NULL) + { + k = 0; + while ((old_lin[end_old+k] == new_lin[end_new+k]) && (new_att[end_new+k] == old_att[end_old+k]) && (new_lin[end_new+k] != (char) NULL) && (old_lin[end_old+k] != (char) NULL) && (k < 10)) + k++; + if ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0))) + { + if (new_lin[end_new+k] == (char) NULL) + { + Position(window, line, (end_new+k)); + CLEAR_TO_EOL(window, line, (end_new+k)); + } + Position(window, line, offset); + for (k = offset; k < end_old; k++) + Char_del(old_lin, old_att, offset, window->Num_cols); + while ((old_lin[offset] != (char) NULL) && (offset < COLS)) + offset++; + pointer_old->last_char = offset; + changed = TRUE; + } + } + return(changed); +} + +/* + | Check if characters were inserted in the middle of a line, and if + | so, insert them. + */ + +int +check_insert(window, line, offset, pointer_new, pointer_old) +WINDOW *window; +int line, offset; +struct _line *pointer_new, *pointer_old; +{ + int changed; + int end_old, end_new; + int k; + int same = FALSE; + int old_off; + int insert; + char *old_lin; + char *new_lin; + char *old_att; + char *new_att; + + changed = FALSE; + new_lin = pointer_new->row; + new_att = pointer_new->attributes; + old_lin = pointer_old->row; + old_att = pointer_old->attributes; + end_old = end_new = offset; + while (((new_lin[end_new] != old_lin[end_old]) || (new_att[end_new] != old_att[end_old])) && (new_lin[end_new] != (char) NULL) && (old_lin[end_new] != (char) NULL)) + end_new++; + if (new_lin[end_new] != (char) NULL) + { + k = 0; + while ((old_lin[end_old+k] == new_lin[end_new+k]) && (old_att[end_old+k] == new_att[end_new+k]) && (new_lin[end_new+k] != (char) NULL) && (old_lin[end_old+k] != (char) NULL) && (k < 10)) + k++; + /* + | check for commonality between rest of lines (are the old + | and new lines the same, except for a chunk in the middle?) + | if the rest of the lines are common, do not insert text + */ + old_off = end_new; + while ((old_lin[old_off] != (char) NULL) && (new_lin[old_off] != (char) NULL) && (old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off])) + old_off++; + if ((old_lin[old_off] == new_lin[old_off]) && (old_att[old_off] == new_att[old_off])) + same = TRUE; + if ((!same) && ((k > 8) || ((new_lin[end_new+k] == (char) NULL) && (k != 0)))) + { + Position(window, line, offset); + insert = FALSE; + if (String_table[ic__] == NULL) + { + String_Out(String_table[im__], NULL, 0); + insert = TRUE; + } + for (k = offset; k < end_new; k++) + { + if (!insert) + String_Out(String_table[ic__], NULL, 0); + Char_ins(old_lin, old_att, new_lin[k], new_att[k], k, window->Num_cols); + } + if (insert) + String_Out(String_table[ei__], NULL, 0); + while ((old_lin[offset] != (char) NULL) && (offset < COLS)) + offset++; + pointer_old->last_char = offset; + changed = TRUE; + } + } + return(changed); +} + +void +doupdate() +{ + WINDOW *window; + int similar; + int diff; + int begin_old, begin_new; + int end_old, end_new; + int count1, j; + int from_top, tmp_ft, offset; + int changed; + int first_time; + int first_same; + int last_same; + int list[10]; + int bottom; + + struct _line *curr; + struct _line *virt; + struct _line *old; + + struct _line *new; + + struct _line *old1, *new1; + + char *cur_lin; + char *vrt_lin; + char *cur_att; + char *vrt_att; + char *att1, *att2; + char *c1, *c2; + + char NC_chinese = FALSE; /* flag to indicate handling Chinese */ + + window = virtual_scr; + + if ((nc_attributes & A_NC_BIG5) != 0) + NC_chinese = TRUE; + + if (Repaint_screen) + { + if (String_table[cl__]) + String_Out(String_table[cl__], NULL, 0); + else + { + from_top = 0; + while (from_top < LINES) + { + Position(curscr, from_top, 0); + if (String_table[ce__] != NULL) + String_Out(String_table[ce__], NULL, 0); + else + { + for (j = 0; j < window->Num_cols; j++) + putchar(' '); + } + from_top++; + } + } + for (from_top = 0, curr = curscr->first_line; from_top < curscr->Num_lines; from_top++, curr = curr->next_screen) + { + Position(curscr, from_top, 0); + for (j = 0; (curr->row[j] != (char) NULL) && (j < curscr->Num_cols); j++) + { + Char_out(curr->row[j], curr->attributes[j], curr->row, curr->attributes, j); + } + if (STAND) + { + STAND = FALSE; + Position(curscr, from_top, j); + attribute_off(); + } + } + Repaint_screen = FALSE; + } + + similar = 0; + diff = FALSE; + top_of_win = curscr->first_line; + + for (from_top = 0, curr = top_of_win, virt = window->first_line; + from_top < window->Num_lines; from_top++) + { + virtual_lines[from_top] = TRUE; + if ((similar = Comp_line(curr, virt)) > 0) + { + virtual_lines[from_top] = FALSE; + diff = TRUE; + } + curr = curr->next_screen; + virt = virt->next_screen; + } + + from_top = 0; + virt = window->first_line; + curr = top_of_win; + similar = 0; + /* + | if the window has lines that are different, check for scrolling + */ + if (diff) + { + last_same = -1; + changed = FALSE; + for (first_same = window->Num_lines; + (first_same > from_top) && (virtual_lines[first_same - 1]); + first_same--) + ; + for (last_same = 0; + (last_same < window->Num_lines) && (virtual_lines[last_same]== FALSE); + last_same++) + ; + while ((from_top < first_same) && nc_scrolling_ability) + /* check entire lines for diffs */ + { + + if (from_top >= last_same) + { + for (last_same = from_top; + (last_same < window->Num_lines) && + (virtual_lines[last_same] == FALSE); + last_same++) + ; + } + if (!virtual_lines[from_top]) + { + diff = TRUE; + /* + | check for lines deleted (scroll up) + */ + for (tmp_ft = from_top+1, old = curr->next_screen; + ((window->scroll_up) && (diff) && + (tmp_ft < last_same) && + (!virtual_lines[tmp_ft])); + tmp_ft++) + { + if ((Comp_line(old, virt) == -1) && (!virtual_lines[from_top])) + { + /* + | Find the bottom of the + | area that should be + | scrolled. + */ + for (bottom = tmp_ft, old1 = old, + new1 = virt, count1 = 0; + (bottom < window->Num_lines) && + (Comp_line(old1, new1) <= 0); + bottom++, old1 = old1->next_screen, + new1 = new1->next_screen, + count1++) + ; + if (count1 > 3) + { + if (String_table[cs__]) /* scrolling region */ + { + list[1] = from_top; + list[0] = min((bottom - 1), (window->Num_lines - 1)); + String_Out(String_table[cs__], list, 2); + Curr_y = Curr_x = -1; + } + + for (offset = (tmp_ft - from_top); (offset > 0); offset--) + { + old = Delete_line(from_top, min((bottom - 1), (window->Num_lines - 1)), window); + diff = FALSE; + } + + if (String_table[cs__]) /* scrolling region */ + { + list[1] = 0; + list[0] = LINES - 1; + String_Out(String_table[cs__], list, 2); + Curr_y = Curr_x = -1; + } + + top_of_win = curscr->first_line; + curr = top_of_win; + for (offset = 0; offset < from_top; offset++) + curr = curr->next_screen; + for (offset = from_top, old=curr, new=virt; + offset < window->Num_lines; + old=old->next_screen, new=new->next_screen, + offset++) + { + similar = Comp_line(old, new); + virtual_lines[offset] = (similar > 0 ? FALSE : TRUE); + } + } + } + else + old = old->next_screen; + } + /* + | check for lines inserted (scroll down) + */ + for (tmp_ft = from_top-1, old = curr->prev_screen; + ((window->scroll_down) && (tmp_ft >= 0) && + (diff) && + (!virtual_lines[tmp_ft])); + tmp_ft--) + { + if (Comp_line(old, virt) == -1) + { + /* + | Find the bottom of the + | area that should be + | scrolled. + */ + for (bottom = from_top, old1 = old, + new1 = virt, count1 = 0; + (bottom < window->Num_lines) && + (Comp_line(old1, new1) <= 0); + bottom++, old1 = old1->next_screen, + new1 = new1->next_screen, + count1++) + ; + if (count1 > 3) + { + if (String_table[cs__]) /* scrolling region */ + { + list[1] = tmp_ft; + list[0] = min((bottom - 1), (window->Num_lines - 1)); + String_Out(String_table[cs__], list, 2); + Curr_y = Curr_x = -1; + } + + for (offset = (from_top - tmp_ft); (offset > 0); offset--) + { + old = Insert_line(tmp_ft, min((bottom - 1), (window->Num_lines -1)), window); + diff = FALSE; + } + + if (String_table[cs__]) /* scrolling region */ + { + list[1] = 0; + list[0] = LINES - 1; + String_Out(String_table[cs__], list, 2); + Curr_y = Curr_x = -1; + } + + top_of_win = curscr->first_line; + curr = top_of_win; + for (offset = 0; offset < from_top; offset++) + curr = curr->next_screen; + for (offset = from_top, old=curr, new=virt; + offset < window->Num_lines; + old=old->next_screen, new=new->next_screen, + offset++) + { + similar = Comp_line(old, new); + virtual_lines[offset] = (similar > 0 ? FALSE : TRUE); + } + } + } + else + old = old->prev_screen; + } + } + from_top++; + curr = curr->next_screen; + virt = virt->next_screen; + } + } + + + /* + | Scrolling done, now need to insert, delete, or modify text + | within lines. + */ + + for (from_top = 0, curr = curscr->first_line; from_top < window->SR; from_top++) + curr = curr->next_screen; + top_of_win = curr; + for (from_top = 0, curr = top_of_win, virt = window->first_line; from_top < window->Num_lines; from_top++, curr = curr->next_screen, virt = virt->next_screen) + { + + /* + | If either 'insert mode' or 'insert char' are + | available, enter the following 'if' statement, + | else, need to simply rewrite the contents of the line + | at the point where the contents of the line change. + */ + + if (((String_table[ic__]) || (String_table[im__])) && + (String_table[dc__]) && (curr->row[0] != (char) NULL) && + (!NC_chinese)) + { + j = 0; + first_time = TRUE; + vrt_lin = virt->row; + vrt_att = virt->attributes; + cur_lin = curr->row; + cur_att = curr->attributes; + while ((vrt_lin[j] != (char) NULL) && (j < window->Num_cols)) + { + if ((STAND) && (Booleans[xs__])) + { + while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL) && (vrt_att[j])) + j++; + if ((STAND) && (!vrt_att[j])) + { + STAND = FALSE; + Position(window, from_top, j); + attribute_off(); + attribute_off(); + } + } + else + { + while ((vrt_lin[j] == cur_lin[j]) && (vrt_att[j] == cur_att[j]) && (vrt_lin[j] != (char) NULL)) + j++; + } + if ((vrt_att[j] != cur_att[j]) && (cur_att[j]) && (Booleans[xs__])) + { + Position(window, from_top, j); +/* CLEAR_TO_EOL(window, from_top, j);*/ + attribute_off(); + attribute_off(); + } + if (vrt_lin[j] != (char) NULL) + { + begin_new = j; + begin_old = j; + end_old = j; + end_new = j; + if ((first_time) && (virt->changed)) + { + if (curr->last_char <= virt->last_char) + changed = check_insert(window, from_top, j, virt, curr); + } + changed = check_delete(window, from_top, j, virt, curr); + first_time = FALSE; + virt->changed = FALSE; + if (!changed) + changed = check_insert(window, from_top, j, virt, curr); + if (((!changed) || (cur_lin[j] != vrt_lin[j]) || (cur_att[j] != vrt_att[j])) && (j < window->Num_cols)) + { + if ((vrt_lin[j] == ' ') && (cur_lin[j] == (char) NULL) && (vrt_att[j] == cur_att[j])) + cur_lin[j] = ' '; + else + { + Position(window, from_top, j); + Char_out(vrt_lin[j], vrt_att[j], cur_lin, cur_att, j); + } + } + if ((vrt_lin[j] != (char) NULL)) + j++; + } + if ((STAND) && (!vrt_att[j])) + { + STAND = FALSE; + Position(window, from_top, j); + attribute_off(); + } + } + if ((vrt_lin[j] == (char) NULL) && (cur_lin[j] != (char) NULL)) + { + Position(window, from_top, j); + CLEAR_TO_EOL(window, from_top, j); + } + } + else /*if ((similar != -1) && (similar != 0))*/ + { + j = 0; + c1 = curr->row; + att1 = curr->attributes; + c2 = virt->row; + att2 = virt->attributes; + while ((j < window->Num_cols) && (c2[j] != (char) NULL)) + { + while ((c1[j] == c2[j]) && (att1[j] == att2[j]) && (j < window->Num_cols) && (c2[j] != (char) NULL)) + j++; + + /* + | if previous character is an eight bit + | char, start redraw from that character + */ + + if ((NC_chinese) && (highbitset(c1[j - 1]))) + j--; + begin_old = j; + begin_new = j; + if ((j < window->Num_cols) && (c2[j] != (char) NULL)) + { + Position(window, from_top, begin_old); + CLEAR_TO_EOL(window, from_top, j); + Position(window, from_top, begin_old); + for (j = begin_old; (c2[j] != (char) NULL) && (j < window->Num_cols); j++) + Char_out(c2[j], att2[j], c1, att1, j); + } + } + if ((c2[j] == (char) NULL) && (c1[j] != (char) NULL)) + { + Position(window, from_top, j); + CLEAR_TO_EOL(window, from_top, j); + } + } + if (STAND) + { + STAND = FALSE; + Position(window, from_top, j); + attribute_off(); + } + virt->number = from_top; + } + Position(window, window->LY, window->LX); +} + +void +Position(window, row, col) /* position the cursor for output on the screen */ +WINDOW *window; +int row; +int col; +{ + int list[10]; + int place; + + int pos_row; + int pos_column; + + pos_row = row + window->SR; + pos_column = col + window->SC; + if ((pos_row != Curr_y) || (pos_column != Curr_x)) + { + if (String_table[cm__] != NULL) /* && (row < window->Num_lines) && (column < window->Num_cols))*/ + { + place = 0; + list[place++] = pos_column; + list[place++] = pos_row; + String_Out(String_table[cm__], list, place); + if ((STAND) && (!Booleans[ms__])) + attribute_on(); + } + Curr_x = pos_column; + Curr_y = pos_row; + } +} + +void +Char_del(line, attrib, offset, maxlen) /* delete chars from line */ +char *line; +char *attrib; +int offset; +int maxlen; +{ + int one, two; + + for (one = offset, two = offset+1; (line[one] != (char) NULL) && (one < maxlen); one++, two++) + { + line[one] = line[two]; + attrib[one] = attrib[two]; + } + String_Out(String_table[dc__], NULL, 0); +} + +void +Char_ins(line, attrib, newc, newatt, offset, maxlen) /* insert chars in line */ +char *line; +char *attrib; +char newc; +char newatt; +int offset; +int maxlen; +{ + int one, two; + + one = 0; + while ((line[one] != (char) NULL) && (one < (maxlen - 2))) + one++; + for (two = one + 1; (two > offset); one--, two--) + { + line[two] = line[one]; + attrib[two] = attrib[one]; + } + line[offset] = newc; + attrib[offset] = newatt; + Char_out(newc, newatt, line, attrib, offset); +} + +void +attribute_on() +{ + if (String_table[sa__]) + { + attributes_set[0] = 1; + String_Out(String_table[sa__], attributes_set, 1); + } + else if (String_table[so__]) + String_Out(String_table[so__], NULL, 0); +} + +void +attribute_off() +{ + if (String_table[me__]) + String_Out(String_table[me__], NULL, 0); + else if (String_table[sa__]) + { + attributes_set[0] = 0; + String_Out(String_table[sa__], attributes_set, 1); + } + else if (String_table[se__]) + String_Out(String_table[se__], NULL, 0); +} + +void +Char_out(newc, newatt, line, attrib, offset) /* output character with proper attribute */ +char newc; +char newatt; +char *line; +char *attrib; +int offset; +{ + + + if ((newatt) && (!STAND)) + { + STAND = TRUE; + attribute_on(); + } + else if ((STAND) && (!newatt)) + { + STAND = FALSE; + attribute_off(); + } + + if ((newatt) && (STAND) && (Booleans[xs__])) + { + attribute_on(); + } + + if (!((Curr_y >= (LINES - 1)) && (Curr_x >= (COLS - 1)))) + { + putchar(newc); + line[offset] = newc; + attrib[offset] = newatt; + } + Curr_x++; +} + +/* + | + | The two routines that follow, nc_setattrib(), nc_clearattrib(), are + | hacks that notify new_curse to handle characters that have the high + | bit set as the first of two bytes of a multi-byte string. + | + */ + +void +nc_setattrib(flag) +int flag; +{ + nc_attributes |= flag; +} + +void +nc_clearattrib(flag) +int flag; +{ + nc_attributes &= ~flag; +} + diff --git a/contrib/ee/new_curse.h b/contrib/ee/new_curse.h new file mode 100644 index 0000000..db538bb --- /dev/null +++ b/contrib/ee/new_curse.h @@ -0,0 +1,260 @@ +/* + | new_curse.h + | + | A subset of curses developed for use with ae. + | + | written by Hugh Mahon + | + | 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. + | + | This software is not a product of Hewlett-Packard, Co., or any + | other company. No support is implied or offered with this software. + | You've got the source, and you're on your own. + | + | This software may be distributed under the terms of Larry Wall's + | Artistic license, a copy of which is included in this distribution. + | + | This notice must be included with this software and any derivatives. + | + | Copyright (c) 1986, 1987, 1988, 1991, 1995 Hugh Mahon + | All are rights reserved. + | + */ + +#include <stdio.h> + +#ifdef SYS5 +#include <termio.h> +#else +#include <sgtty.h> +#include <fcntl.h> +#endif + +#define KEY_BREAK 0401 +#define KEY_DOWN 0402 +#define KEY_UP 0403 +#define KEY_LEFT 0404 +#define KEY_RIGHT 0405 +#define KEY_HOME 0406 +#define KEY_BACKSPACE 0407 +#define KEY_F0 0410 +#define KEY_F(n) (KEY_F0+(n)) +#define KEY_DL 0510 +#define KEY_IL 0511 +#define KEY_DC 0512 +#define KEY_IC 0513 +#define KEY_EIC 0514 +#define KEY_CLEAR 0515 +#define KEY_EOS 0516 +#define KEY_EOL 0517 +#define KEY_SF 0520 +#define KEY_SR 0521 +#define KEY_NPAGE 0522 +#define KEY_PPAGE 0523 +#define KEY_STAB 0524 +#define KEY_CTAB 0525 +#define KEY_CATAB 0526 +#define KEY_ENTER 0527 +#define KEY_SRESET 0530 +#define KEY_RESET 0531 +#define KEY_PRINT 0532 +#define KEY_LL 0533 +#define KEY_A1 0534 +#define KEY_A3 0535 +#define KEY_B2 0536 +#define KEY_C1 0537 +#define KEY_C3 0540 +#define KEY_BTAB 0541 +#define KEY_BEG 0542 +#define KEY_CANCEL 0543 +#define KEY_CLOSE 0544 +#define KEY_COMMAND 0545 +#define KEY_COPY 0546 +#define KEY_CREATE 0547 +#define KEY_END 0550 +#define KEY_EXIT 0551 +#define KEY_FIND 0552 +#define KEY_HELP 0553 +#define KEY_MARK 0554 +#define KEY_MESSAGE 0555 +#define KEY_MOVE 0556 +#define KEY_NEXT 0557 +#define KEY_OPEN 0560 +#define KEY_OPTIONS 0561 +#define KEY_PREVIOUS 0562 +#define KEY_REDO 0563 +#define KEY_REFERENCE 0564 +#define KEY_REFRESH 0565 +#define KEY_REPLACE 0566 +#define KEY_RESTART 0567 +#define KEY_RESUME 0570 +#define KEY_SAVE 0571 +#define KEY_SBEG 0572 +#define KEY_SCANCEL 0573 +#define KEY_SCOMMAND 0574 +#define KEY_SCOPY 0575 +#define KEY_SCREATE 0576 +#define KEY_SDC 0577 +#define KEY_SDL 0600 +#define KEY_SELECT 0601 +#define KEY_SEND 0602 +#define KEY_SEOL 0603 +#define KEY_SEXIT 0604 +#define KEY_SFIND 0605 +#define KEY_SHELP 0606 +#define KEY_SHOME 0607 +#define KEY_SIC 0610 +#define KEY_SLEFT 0611 +#define KEY_SMESSAGE 0612 +#define KEY_SMOVE 0613 +#define KEY_SNEXT 0614 +#define KEY_SOPTIONS 0615 +#define KEY_SPREVIOUS 0616 +#define KEY_SPRINT 0617 +#define KEY_SREDO 0620 +#define KEY_SREPLACE 0621 +#define KEY_SRIGHT 0622 +#define KEY_SRSUME 0623 +#define KEY_SSAVE 0624 +#define KEY_SSUSPEND 0625 +#define KEY_SUNDO 0626 +#define KEY_SUSPEND 0627 +#define KEY_UNDO 0630 + +#define TRUE 1 +#define FALSE 0 + +#define A_STANDOUT 0001 /* standout mode */ +#define A_NC_BIG5 0x0100 /* Handle Chinese Big5 characters */ +#define SCROLL 1 /* text has been scrolled */ +#define CLEAR 2 /* window has been cleared */ +#define CHANGE 3 /* window has been changed */ +#define UP 1 /* direction of scroll */ +#define DOWN 2 + +struct _line { + struct _line *next_screen; + struct _line *prev_screen; + char *row; + char *attributes; + int last_char; + int changed; + int scroll; + int number; + }; + +struct _line *top_of_win; + +typedef struct WIND { + int SR; /* starting row */ + int SC; /* starting column */ + int LC; /* last column */ + int LX; /* last cursor column position */ + int LY; /* last cursor row position */ + int Attrib; /* attributes active in window */ + int Num_lines; /* number of lines */ + int Num_cols; /* number of columns */ + int scroll_up; /* number of lines moved */ + int scroll_down; + int SCROLL_CLEAR; /* indicates that window has been scrolled or cleared */ + struct _line *first_line; + struct _line **line_array; + } WINDOW; + +extern WINDOW *curscr; +extern WINDOW *stdscr; + +extern int LINES, COLS; + +#if defined(__STDC__) || defined(__cplusplus) +#define P_(s) s +#else +#define P_(s) () +#endif + +extern void copy_window P_((WINDOW *origin, WINDOW *destination)); +extern void reinitscr P_((int)); +extern void initscr P_((void)); +extern int Get_int P_((void)); +extern int INFO_PARSE P_((void)); +extern int AtoI P_((void)); +extern void Key_Get P_((void)); +extern void keys_vt100 P_((void)); +extern struct _line *Screenalloc P_((int columns)); +extern WINDOW *newwin P_((int lines, int cols, int start_l, int start_c)); +extern int Operation P_((int Temp_Stack[], int place)); +extern void Info_Out P_((char *string, int p_list[], int place)); +extern void wmove P_((WINDOW *window, int row, int column)); +extern void clear_line P_((struct _line *line, int column, int cols)); +extern void werase P_((WINDOW *window)); +extern void wclrtoeol P_((WINDOW *window)); +extern void wrefresh P_((WINDOW *window)); +extern void touchwin P_((WINDOW *window)); +extern void wnoutrefresh P_((WINDOW *window)); +extern void flushinp P_((void)); +extern void ungetch P_((int c)); +extern int wgetch P_((WINDOW *window)); +extern void Clear P_((int)); +extern int Get_key P_((int first_char)); +extern void waddch P_((WINDOW *window, int c)); +extern void winsertln P_((WINDOW *window)); +extern void wdeleteln P_((WINDOW *window)); +extern void wclrtobot P_((WINDOW *window)); +extern void wstandout P_((WINDOW *window)); +extern void wstandend P_((WINDOW *window)); +extern void waddstr P_((WINDOW *window, char *string)); +extern void clearok P_((WINDOW *window, int flag)); +extern void echo P_((void)); +extern void noecho P_((void)); +extern void raw P_((void)); +extern void noraw P_((void)); +extern void nl P_((void)); +extern void nonl P_((void)); +extern void saveterm P_((void)); +extern void fixterm P_((void)); +extern void resetterm P_((void)); +extern void nodelay P_((WINDOW *window, int flag)); +extern void idlok P_((WINDOW *window, int flag)); +extern void keypad P_((WINDOW *window, int flag)); +extern void savetty P_((void)); +extern void resetty P_((void)); +extern void endwin P_((void)); +extern void delwin P_((WINDOW *window)); +extern void wprintw P_((WINDOW *window, const char* format, ...)); +extern void iout P_((WINDOW *window, int value)); +extern int Comp_line P_((struct _line *line1, struct _line *line2)); +extern struct _line *Insert_line P_((int row, int end_row, WINDOW *window)); +extern struct _line *Delete_line P_((int row, int end_row, WINDOW *window)); +extern void CLEAR_TO_EOL P_((WINDOW *window, int row, int column)); +extern int check_delete P_((WINDOW *window, int line, int offset, struct _line *pointer_new, struct _line *pointer_old)); +extern int check_insert P_((WINDOW *window, int line, int offset, struct _line *pointer_new, struct _line *pointer_old)); +extern void doupdate P_((void)); +extern void Position P_((WINDOW *window, int row, int col)); +extern void Char_del P_((char *line, char *attrib, int offset, int maxlen)); +extern void Char_ins P_((char *line, char *attrib, int newc, int newatt, int offset, int maxlen)); +extern void attribute_on P_((void)); +extern void attribute_off P_((void)); +extern void Char_out P_((int newc, int newatt, char *line, char *attrib, int offset)); + +extern void nc_setattrib P_((int)); +extern void nc_clearattrib P_((int)); +#undef P_ + |