[comp.sources.unix] v14i064: Jove, an emacs variant, version 4.9, Part08/21

rsalz@bbn.com (Rich Salz) (04/26/88)

Submitted-by: Jonathan Payne <jpayne@cs.rochester.edu>
Posting-number: Volume 14, Issue 64
Archive-name: jove4.9/part08



#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 8 (of 21)."
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f './Readme.mac' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./Readme.mac'\"
else
echo shar: Extracting \"'./Readme.mac'\" \(17320 characters\)
sed "s/^X//" >'./Readme.mac' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
X * is provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is    *
X * included in all the files.                                              *
X ***************************************************************************/
X
Introduction
X
This file contains a brief description of MacJove, along with
information necessary to make MacJove from the source files.
It is assumed that the reader is familiar with Jove from other
systems, and is somewhat familiar with the Macintosh as well. In
the future there may be a separate user's manual for MacJove: 
for the time being, the reader should refer to the Jove manual
for Unix users.
X
Description
X
MacJove is a direct port of Jove to the Macintosh, with the
overall structure, commands and key bindings left intact. In
addition, elements of the Macintosh user interface - menus,
window controls, and the mouse, have been integrated in a manner
consistent with the overall functioning of Jove.
X
While the integration of these tools into the Jove environment
is consistent and, to most users, familiar, Jove departs in
several places from "Macintosh User Interface Guidelines". Most
notably, the mouse is used to position the point only, not to
drag or select text, and the Jove buffer structure is not
integrated with the clipboard. Also, key bindings conform to
Jove/Emacs tradition, and not to Macintosh guidelines: i.e.
control (command)-N is next-line, not "NewFile". The reason for
these departures is that the majority of MacJove users are likely
to be those already familiar with Jove or other Emacs editors
on other systems, and for these users, consistency between machines
and operating systems is more important than fully exploiting
the features of a single system. There are numerous other text
editors which fully follow the Macintosh User Interface Guidelines.
X
MacJove retains most features of other Joves, but certain commands
cannot be implemented because of the Macintosh operating system.
Thus, there is no way to run a sub-process or a shell in a window,
because there are no shells to run on the Macintosh, and a program
X(currently) can only transfer control to another program, not run
a child process. For similar reasons, commands dealing with mail,
with running make, and checking errors, are omitted.
X
X
X
X                      Running MacJove
X
System Requirements
X
MacJove should run without difficulty on any Macintosh Plus, SE, or
Macintosh II, providing that the hierarchical file system (HFS) is used, and
assuming a reasonably current system file is used. An upgraded 512K Mac
X(with 128K rom) should also work if there is enough memory.  MacJove was
developed on a Macintosh Plus and Macintosh II running system 4.2 and Finder
X6.0., and has not been fully tested on earlier systems - however, it is
likely that it will run on system 3.2 and later versions. MacJove has been
used to a limited extent with Switcher and under Multifinder. In both cases,
it is important to reserve enough memory for MacJove, as discussed below.
X
MacJove, as compiled from the sources, uses memory as follows:
X
X   Program Code     approx 116K
X   Static Data      approx  20K
X   Tempfile Cache           64K (heap)
X                           ____
X                           200K total before stack/heap considerations
X
To this must be added stack and heap space. A bare minimum for this is
probably 100K or so, but the usage will vary as buffers are created.  With
Jove, the file itself takes up space only in the tempfile and its cache, but
the buffer structure requires 3 pointers (12 bytes) for each line in the
file. For a reasonable editing session with files totalling, say 10000 to
X20000 lines, this additional space can add up. For this reason, it is
unrealistic to expect to run Jove on a 512K system, unless a very small
system file is used, few, small files are edited each session, and the
tempfile cache is reduced (see cache size under Making Jove). You can
experiment with various memory allocations under Switcher and Multifinder to
see what works with your editing habits (backup your files first!), but a
realistic minimum is 400K - 500K and more is great.
X
When first using MacJove, and if memory space is questionable, SAVE YOUR
FILES FREQUENTLY. If it is necessary to edit many files, it is often better
to exit MacJove and restart once in a while, especially if there is a
question of limited memory.
X
Operation
X
X
Running MacJove is similar to other Macintosh applications, and should be
intuitive. You start up MacJove by either opening, or double-clicking,
the MacJove icon. If you have previously saved files created with MacJove,
double-clicking on them will also start up the program, and the files will
be put into buffers. Several files can be selected simultaneously by this
method. There is no current way to select command-line options with
MacJove, but this may change in the future.
X
The .joverc file, if used, must be present in the same directory as MacJove,
the "home" directory. The help file, "cmds.doc", must also be in this
directory. The tempfile, ".joveXXX", will be placed in whatever directory is
current when the tempfile is first opened - this may or may not be the home
directory, and may change in the future. The recover file, ".jrecXXX" is
placed in the home directory. While this file is created and updated as on
Unix versions of Jove, there is currently no "recover" program for MacJove.
Hopefully, this will be available soon.
X
MacJove can edit any text file on the Macintosh, whether created with
MacJove or another editor. It cannot be used to edit graphics material, and
graphics material cannot be inserted during operation of MacJove. Files
created with MacJove are of type 'TEXT' and of signature 'JV01'. This
signature is being registered with Apple, and may change if necessary. Note
that once MacJove files have been re-edited with another editor, they likely
will have new signatures, and double-clicking on them will start the other
editor, not MacJove.
X
The standard Macintosh keyboard is inadequate for MacJove (and most anything
else), so that it is necessary to change a couple of keys. The "`" key
becomes the ESCAPE key, since it is in the right place for one: to send a
real "'", hold the command key down while typing it. The command key is used
for a control key - unfortunately, the location of it is horrible for such a
purpose. On Macintosh SE and Macintosh II models, a real escape key exists,
and also a real control key. Note, however, that because of a small bug in
the keyboard encoding in MacJove, you cannot directly send a NUL (control-@)
with the control key. Typing command-@ or command-2 will still do this,
however.
X
During operation, you can use the keyboard as you would when running Jove on
any other system. However, many commands also have menu equivalents:  as
long as MacJove is waiting for a command, you can use either the keyboard or
the menus. Once you begin selecting a command with either the menus or the
keyboard, the other is locked out: thus, once you type control-X, MacJove
expects more characters, and will not let you choose menu items.  Also, if
you are prompted for input on the command line, the menus are locked out.
Regardless of how a command is begun, however, only the prompt line (message
line) is used for input: MacJove does not use dialog boxes, except under the
X"About Jove" menu selection.
X
Commands listed in the menus are given exactly as their string name in
the command list, for example "write-file". In addition, variables are
listed under the "Set" menu. Variables are grouped by type. Non-boolean
variables are changed on the message line after being selected. Boolean
variables are marked with a check mark if on, and selecting them toggles
the value of the variable.
X
The "Buffer" menu is a special menu, whose action is different than the
others. The first entries on this menu are the major and minor modes of
operation, with those of the current buffer marked with check marks.
Clicking on a major mode will change the major mode of the current buffer to
that mode, while clicking on a minor mode will toggle that mode's status
X(on/off) for the current buffer. Beneath this is a list of buffers, one for
each menu item, with the current buffer marked. Clicking on a buffer selects
that as the current buffer, and the active window will change accordingly.
X
Window controls (scroll bars) work as expected, and are simply bound to
the appropriate MacJove command. Occassionally the position of the
scroll bar may appear inaccurate, particularly with a small buffer.
X
Files and directories may be selected in two ways. The default method
is to use the message line to input filenames, and to change directories
using "cd". If the variable "macify" is set, however, filenames and
directories can also be set using the standard file dialogs familiar to
most Mac users. Filename paths are normally given via Unix conventions,
and not Macintosh conventions: i.e. directories are separated with "/"
and not ":". On the Buffer menu, however, filenames are listed with ":"
as the separation character, since "/" cannot be displayed in menu items.
It is not possible to back up directories beyond the volume level, so
there is not true "root". To change volumes (disks), macify must be on,
and the "Drive" selection used.
X
X"Macify" only works for those commands which REQUIRE a file operation, such
as "visit-file", "insert-file", "write-file".  Operations which first look
in buffers for files, such as "window-find" and "find-file" never use the
standard file dialogs.
X
For a list of all commands and bindings, click on "About Jove" in the
Apple menu. In the future this may also support the help file.
X
X                      Making MacJove
X
System Requirements
X
To make MacJove from the sources, you need a hard disk based Macintosh, at
least 1 mb of ram, and the LightspeedC compiler, version 2.13 or later.
Earlier versions may work but have not been used recently. Allow for the
MacJove files to take up to 1.5 mb of your hard disk. You will need a copy
of the "BinHex" utility, also.
X
Since LightspeedC does not work with a Makefile, none is supplied. In
general, the compiler itself will figure out dependencies for you, within a
X"project". Since there are three separate projects to MacJove, you will
still have to keep track of some changes, particularly for the setmaps
project. Also, since LightspeedC only knows of .c and .h dependencies,
you will have to keep track of setmaps.txt and menumaps.txt yourself.
X
Preliminary Steps
X
X0) CREATE A FOLDER (DIRECTORY) FOR JOVE. If I have to tell you how to do
that, don't go any further! Copy the source files - a few aren't needed
by MacJove, but copy them anyway, so you'll have them in one place. You
do not need anything in the "doc" subdirectory to create MacJove (but
you will eventually need cmds.doc, the help file, if you want the
X"describe-command" command to work).
X
X1) CREATE THE RESOURCE FILE: There is only one eight-bit file supplied,
X"mjove.rsrc". This is a small file which contains the program icon and a
dialog template. This file must have the same name as the MacJove project,
plus extension ".rsrc". The MacJove project (below), has name "mjove", so
this file is "mjove.rsrc".  IF YOU RENAME THE PROJECT YOU MUST RENAME THIS
FILE, ALSO. Using "BinHex", unload the file "mjovers.Hqx" --> "mjove.rsrc".
X
X2) CREATE THE "MJOVELIB" PROJECT: MacJove does not use many of the library
functions. Despite what the LightspeedC manual states, projects are loaded
as a whole: since we need only a few functions, we will build a "library" of
them in the form of a project. Run LightspeedC and create a new project,
and name it "mjovelib". Add the following files, from the Library Sources,
to the project. They all go in the same segment:
X
X     onexit.c
X     qsort.c
X     stddata_ctype.c
X     unixexit.c
X     unixid.c
X     unixmem.c
X     unixtime.c
X
X3) EXAMINE THE FILE UNIXTIME.C and make the following correction, if
necessary. The LightspeedC library function "unixtime.c" returns a string
containing the time for what is supposed to be Greenwich Mean Time, instead
of local time. Using the LightspeedC editor, and with the project open,
examine the file, comment out the definition of "GMTzonedif", and add:
X
X     #define GMTzonedif 0
X
X4) MAKE THE "MJOVELIB" PROJECT. Keeping the edited "unixtime.c" open,
run "make" on the project - everything will be compiled, with the altered
version of "unixtime.c". You do not have to permanently save the change
to unixtime.c, but if you do not, the next time you run "make" on the
project, it will tell you that it needs recompiling - simply ignore it.
After the mjovelib project is made, close it. You do not have to convert it
to a library - it is okay to leave it as a project.
X
X6) CREATE THE "MSETMAPS" PROJECT. Create a new project, name it "msetmaps",
and add the following files to it:
X
X     setmaps.c
X     stdio
X     strings           (segment 1)
X     unix
X     unix main.c
X     --------
X     MacTraps          (segment 2)
X
X7) EDIT THE FILE "TUNE.H". The only thing you should have to do with this
file is to make certain that MAC is defined. Uncomment the following line,
near the beginning of the file
X
Change:
X
X  /*#define MAC 1                /* alas, there is no command line for this */
X
to:
X
X  #define MAC 1	        /* alas, there is no command line for this */
X
You should not change anything else at this point - unless you want to
reduce memory requirements (see "Running MacJove", above). If it is
necessary to reduce the memory requirements, then reduce the number of cache
buffers, NBUF, which is defined near the end of the file (each buffer takes
up 1K of space while MacJove is running).
X
X     #ifdef MAC
X     #  undef F_COMPLETION        /* can't do it with spaces in filenames */
X     #  undef CHDIR
X     #  define CHDIR 1
X     #  define rindex strrchr
X     #  define index strchr
X     #  define bzero(s,n) setmem(s,n,0)
X     #  define LINT_ARGS
X     #  define NBUF 64 <----------reduce this if necessary.
X     #  define BUFSIZ 1024
X     #endif
X
X8) MAKE THE "MSETMAPS" PROJECT. Then choose "Build Application",and name it
X"setmaps". 
X
X9) RUN "SETMAPS" ON THE KEYMAPS.TXT FILE. You can either run "setmaps" from
LightspeedC, before closing the project, or as the standalone application.
When prompted for the "Unix command line", enter:
X
X     < keymaps.txt > keymaps.c
X
You will get a few messages from setmaps that it can't find certain
commands. You can ignore these.
X
X10) RUN "SETMAPS" ON THE MENUMAPS.TXT FILE. Just as before, run "setmaps"
and enter the following command line:
X
X     < menumaps.txt > menumaps.c
X
You should not get any messages from setmaps. If the "msetmaps" project is
still open, close it.
X
X11) CREATE THE "MJOVE" PROJECT. Create a new project, name it "MJOVE" and
set the Creator (signature) to 'JV01'. Add the following files in the
following segments:
X
X     abbrev.c
X     argcount.c
X     ask.c
X     buf.c
X     c.c
X     case.c        (segment 1)
X     ctype.c
X     delete.c
X     disp.c
X     extend.c
X     --------
X     fmt.c
X     fp.c
X     funcdefs.c    (segment 2)
X     insert.c
X     io.c
X     jove.c
X     keymaps.c
X     --------
X     mac.c
X     macros.c
X     marks.c
X     menumaps.c    (segment 3)
X     misc.c
X     move.c
X     paragraph.c
X     --------
X     re.c
X     re1.c
X     rec.c
X     screen.c
X     table.c       (segment 4)
X     term.c
X     util.c
X     vars.c
X     version.c
X     wind.c
X     --------
X     MacTraps
X     mjovelib
X     setjmp.Lib    (segment 5)
X     storage
X     strings
X
X12) MAKE THE MJOVE PROJECT. If you experience any errors, it will most
likely be from #include files not being in the default path - see the
LightspeedC manual on setting up your directories. When you are done,
run the program from the compiler to verify that it is okay, then save it as
X"MacJove" using the "Build Application" command.
X
X13) (Optional) CREATE THE HELP FILE, "CMDS.DOC". If you do not have a copy
of "cmds.doc", it must be created using nroff. Assuming you have the Jove
sources on a Unix machine, run "Make doc/cmds.doc" to create this file in
the "doc" subdirectory, then move the file to the Mac. If you obtained the
sources from a non-Unix source, this file may already be supplied. Place the
file in the same directory that MacJove will be in.
X
X                      COMMENTS AND QUESTIONS, BUGS
X
This is the first version of MacJove to receive widespread use, and problems
are anticipated. All comments and suggestions are appreciated. Before asking
for help in making MacJove, make sure you understand the above directions,
have followed them closely, and have a good copy of the sources. I will try
to reply to everyone, but have a busy schedule, and cannot guarantee any
time frame of response. I can promise you, however, that questions received
via the net or mail will be answered more promptly than those from via US
Mail. PLEASE DO NOT SEND ME DISKS!
X
X
X    Ken Mitchum
X    Decision Systems Laboratory
X    University of Pittsburgh
X    1360 Scaife Hall
X    Pittsburgh, Pa. 15261
X
X    (km@cadre.dsl.pittsburgh.edu)
X
END_OF_FILE
if test 17320 -ne `wc -c <'./Readme.mac'`; then
    echo shar: \"'./Readme.mac'\" unpacked with wrong size!
fi
# end of './Readme.mac'
fi
if test -f './jove.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./jove.h'\"
else
echo shar: Extracting \"'./jove.h'\" \(16194 characters\)
sed "s/^X//" >'./jove.h' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
X * is provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is    *
X * included in all the files.                                              *
X ***************************************************************************/
X
X/* jove.h header file to be included by EVERYONE */ 
X
X
X#include <setjmp.h>
X
X#ifndef TUNED
X#   include "tune.h"
X#endif
X
X#ifndef MAC
X#	include <sys/types.h>
X#else
X#	include <types.h>
X#endif
X
X
X#ifdef MSDOS
X#include <string.h>
X#endif
X
X
X#if !(defined(MSDOS) || defined(MAC))
X#define void int
X#endif
X
X#if !(defined(IBMPC) || defined(MAC))
X#	define TERMCAP
X#	define ASCII
X#endif
X
X#ifdef ASCII	/* seven bit characters */
X#	define NCHARS 0200
X#else
X#	define NCHARS 0400
X#endif
X#define CHARMASK (NCHARS -1)
X
X#define private	static
X
X#ifndef BSD4_2
X#   ifdef MENLO_JCL
X#	ifndef EUNICE
X#		define signal	sigset
X#	endif
X#   endif /* MENLO_JCL */
X#endif
X
X#define EOF	-1
X
X#ifdef MSDOS
X#	define NULL	((char *)0)
X#	define NIL	((char *)0)
X#else
X#	ifdef MAC
X#		define NULL 0L
X#		define NIL 0L
X#	else
X#		define NULL 0
X#		define NIL 0
X#	endif /* MAC */
X#endif /* MSDOS */
X/* kinds of regular expression compiles */
X#define NORM	0	/* nothing special */
X#define OKAY_RE	1	/* allow regular expressions */
X#define IN_CB	2	/* in curly brace; implies OKAY_RE */
X
X/* return codes for command completion (all < 0 because >= 0 are
X   legitimate offsets into array of strings */
X
X#define AMBIGUOUS	-2	/* matches more than one at this point */
X#define UNIQUE		-3	/* matches only one string */
X#define ORIGINAL	-4	/* matches no strings at all! */
X#define NULLSTRING	-5	/* just hit return without typing anything */
X
X/* values for the `flags' argument to complete */
X#define NOTHING		0	/* opposite of RET_STATE */
X#define RET_STATE	1	/* return state when we hit return */
X#define RCOMMAND	2	/* we are reading a joverc file */
X#define CASEIND		4	/* map all to lower case */
X
X#define SAVE		01	/* this macro needs saving to a file */
X
X#define	LBSIZE		BUFSIZ	/* same as a logical disk block */
X#ifndef MSDOS
X#define FILESIZE	256
X#else /* MSDOS */
X#define FILESIZE	64
X#endif /* MSDOS */
X
X#define FORWARD		1
X#define BACKWARD	-1
X
X#define CTL(c)		(c & 037)
X#define META(c)		(c | 0200)
X#define RUBOUT		'\177'
X#define LF		CTL('J')
X#define CR		CTL('M')
X#define BS		CTL('H')
X#define ESC		'\033'
X
X#define HALF(wp)	((wp->w_height - 1) / 2)
X#define IsModified(b)	(b->b_modified)
X#define SIZE(wp)	(wp->w_height - 1)
X#define SavLine(a, b)	(a->l_dline = putline(b))
X#define SetLine(line)	DotTo(line, 0)
X#define bobp()		(firstp(curline) && bolp())
X#define bolp()		(curchar == 0)
X#define eobp()		(lastp(curline) && eolp())
X#define eolp()		(linebuf[curchar] == '\0')
X#define firstp(line)	(line == curbuf->b_first)
X#define getDOT()	getline(curline->l_dline, linebuf)
X#define isdirty(line)	(line->l_dline & DIRTY)
X#define lastp(line)	(line == curbuf->b_last)
X#define makedirty(line)	line->l_dline |= DIRTY
X#define one_windp()	(fwind->w_next == fwind)
X
X#define CharUpcase(c)	(CaseEquiv[c])
X
extern int	BufSize;
X
X#define ARG_CMD		1
X#define LINECMD		2
X#define KILLCMD		3	/* so we can merge kills */
X#define YANKCMD		4	/* so we can do ESC Y (yank-pop) */
X
X/* Buffer type */
X
X#define B_SCRATCH	1	/* for internal things, e.g. minibuffer ... */
X#define B_FILE		2	/* normal file (We Auto-save these.) */
X#define B_PROCESS	3	/* process output in this buffer */
X
X/* Major modes */
X#define FUNDAMENTAL	0	/* Fundamental mode */
X#define TEXT		1	/* Text mode */
X#define CMODE		2	/* C mode */
X#ifdef LISP
X#	define LISPMODE		3	/* Lisp mode */
X#	define NMAJORS		4
X#else
X#	define NMAJORS	3
X#endif
X
X/* Minor Modes */
X#define Indent		(1 << 0)	/* indent same as previous line after return */
X#define ShowMatch	(1 << 1)	/* paren flash mode */
X#define Fill		(1 << 2)	/* text fill mode */
X#define OverWrite	(1 << 3)	/* over write mode */
X#define Abbrev		(1 << 4)	/* abbrev mode */
X
X#define BufMinorMode(b, x)	(b->b_minor & x)
X
X#define MinorMode(x)	BufMinorMode(curbuf, x)
X#define MajorMode(x)	(curbuf->b_major == x)
X#define SetMajor(x)	((curbuf->b_major = x), UpdModLine = YES)
X
X#ifdef ASCII
extern char	CharTable[NMAJORS][128];
extern char	CaseEquiv[128];
X#else /* IBMPC or MAC */
extern char	CharTable[NMAJORS][256];
extern char	CaseEquiv[256];
X#endif /* ASCII */
X
X/* setjmp/longjmp args for DoKeys() mainjmp */
X#define FIRSTCALL	0
X#define ERROR		1
X#define COMPLAIN	2	/* do the error without a getDOT */
X#define QUIT		3	/* leave this level of recursion */
X
X#define QUIET		1	/* sure, why not? */
X
X#define YES		1
X#define NO		0
X#define TRUE		1
X#define FALSE		0
X#define ON		1
X#define OFF		0
X#define YES_NODIGIT	2
X
X#define INT_OKAY	0
X#define INT_BAD		-1
X
extern char	*Mainbuf,
X		*HomeDir,	/* home directory */
X		key_strokes[],	/* strokes that make up current command */
X		*Inputp;
X
extern int	HomeLen;	/* length of home directory */
X
extern char	NullStr[];
X
X#if defined(VMUNIX)||defined(MSDOS)
extern char	genbuf[LBSIZE],
X		linebuf[LBSIZE],
X		iobuff[LBSIZE];
X#else
extern char	*genbuf,	/* scratch pad points at s_genbuf (see main()) */
X		*linebuf,	/* points at s_linebuf */
X		*iobuff;	/* for file reading ... points at s_iobuff */
X#endif
X
extern int	InJoverc,
X		Interactive;
X
X#define	READ	0
X#define	WRITE	1
extern int	errno;
X
extern jmp_buf	mainjmp;
X
X#ifdef IPROCS
typedef struct process	Process;
X#endif
typedef struct window	Window;
typedef struct position	Bufpos;
typedef struct mark	Mark;
typedef struct buffer	Buffer;
typedef struct line	Line;
typedef struct iobuf	IOBUF;
typedef struct data_obj {
X	int	Type;
X	char	*Name;
X} data_obj;	/* points to cmd, macro, or variable */
X
typedef data_obj	*keymap[NCHARS];
X
struct line {
X	Line	*l_prev,		/* pointer to prev */
X		*l_next;		/* pointer to next */
X	disk_line	l_dline;	/* pointer to disk location */
X};
X
X#ifdef IPROCS
struct process {
X	Process	*p_next;
X#ifdef PIPEPROCS
X	int	p_toproc,	/* read p_fromproc and write p_toproc */
X		p_portpid,	/* pid of child (the portsrv) */
X		p_pid;		/* pid of real child i.e. not portsrv */
X#else
X	int	p_fd,		/* file descriptor of pty? opened r/w */
X		p_pid;		/* pid of child (the shell) */
X#endif
X	Buffer	*p_buffer;	/* add output to end of this buffer */
X	char	*p_name;	/* ... */
X	char	p_state,	/* State */
X		p_howdied,	/* Killed? or Exited? */
X		p_reason;	/* If signaled, p_reason is the signal; else
X				   it is the the exit code */
X	Mark	*p_mark;	/* where output left us */
X	data_obj
X		*p_cmd;		/* command to call when process dies */
X};
X#endif /* IPROCS */
X
struct window {
X	Window	*w_prev,	/* circular list */
X		*w_next;
X	Buffer	*w_bufp;	/* buffer associated with this window */
X	Line	*w_top,		/* top line */
X		*w_line;	/* current line */
X	int	w_char,
X		w_height,	/* window height */
X		w_topnum,	/* line number of the topline */
X		w_dotcol,	/* UpdWindow sets this ... */
X		w_dotline,	/* ... and this */
X		w_flags,
X#define	W_TOPGONE	01
X#define	W_CURGONE	02	/* topline (curline) of window has been deleted
X				   since the last time a redisplay was called */
X#define W_VISSPACE	04
X#define W_NUMLINES	010
X		w_LRscroll;	/* amount of LeftRight scrolling in window */
X#ifdef MAC
X	int	w_topline;	/* row number of top line in window */
X	char **w_control;	/* scroll bar for window */
X#endif
X};
X
extern Window	*fwind,		/* first window in list */
X		*curwind;	/* current window */
X
struct position {
X	Line	*p_line;
X	int	p_char;
X};
X
struct mark {
X	Line	*m_line;
X	int	m_char;
X	Mark	*m_next;	/* list of marks */
X#define M_FIXED		00
X#define M_FLOATER	01
X#define M_BIG_DELETE	02
X	char	m_flags;	/* FLOATERing mark? */
X};
X
struct buffer {
X#ifdef MAC
X	int Type;		/* kludge... to look like a data_obj */
X	char *Name;		/* Name will not be used */
X#endif	
X	Buffer	*b_next;		/* next buffer in chain */
X	char	*b_name,		/* buffer name */
X		*b_fname;		/* file name associated with buffer */
X	dev_t	b_dev;			/* device of file name. */
X	ino_t	b_ino;			/* inode of file name */
X	time_t	b_mtime;		/* last modify time ...
X					   to detect two people writing
X					   to the same file */
X	Line	*b_first,		/* pointer to first line in list */
X		*b_dot,			/* current line */
X		*b_last;		/* last line in list */
X	int	b_char;			/* current character in line */
X
X#define NMARKS	8			/* number of marks in the ring */
X
X	Mark	*b_markring[NMARKS],	/* new marks are pushed here */
X		*b_marks;		/* all the marks for this buffer */
X	char	b_themark,		/* current mark (in b_markring) */
X		b_type,			/* file, scratch, process, iprocess */
X		b_ntbf,			/* needs to be found when we
X					   first select? */
X		b_modified;		/* is the buffer modified? */
X	int	b_major,		/* major mode */
X		b_minor;		/* and minor mode */
X	keymap	*b_keybinds;		/* local bindings (if any) */
X#ifdef IPROCS
X	Process	*b_process;		/* process we're attached to */
X#endif
X};
X
struct macro {
X	int	Type;		/* in this case a macro */
X	char	*Name;		/* name is always second ... */
X	int	m_len,		/* length of macro so we can use ^@ */
X		m_buflen,	/* memory allocated for it */
X		m_flags;
X	char	*m_body;	/* actual body of the macro */
X	struct macro
X		*m_nextm;
X};
X
struct variable {
X	int	Type;		/* in this case a variable */
X	char	*Name;		/* name is always second */
X	int	*v_value,
X		v_flags;
X};
X
struct cmd {
X	int	Type;
X	char	*Name;
X#ifdef MAC
X	void (*c_proc)();
X#else
X	int (*c_proc)();
X#endif
X#ifdef MAC
X	char c_map;			/* prefix map for About Jove... */
X	char c_key;			/* key binding for About Jove... */
X#endif
X};
X
extern keymap	mainmap,	/* various key maps */
X		pref1map,
X		pref2map,
X		miscmap;
X#ifdef MAC					/* used in About Jove... */		
X	#define F_MAINMAP '\001'
X	#define F_PREF1MAP '\002'
X	#define F_PREF2MAP '\003'
X#endif
X
extern data_obj	*LastCmd;	/* last command invoked */
X
extern char	*ProcFmt;
X
extern struct cmd	commands[];
extern struct macro	*macros;
extern struct variable	variables[];
X
extern struct macro
X	*macstack[],
X	KeyMacro;
X
X#define FUNCTION	1
X#define VARIABLE	2
X#define MACRO		3
X#ifdef MAC
X#	define BUFFER		6	/* menus can point to buffers, too */
X#	define STRING		7	/* a menu string or divider */
X#endif
X
X#define TYPEMASK	07
X#define MAJOR_MODE	010
X#define MINOR_MODE	020
X#define DefMajor(x)	(FUNCTION|MAJOR_MODE|(x << 8))
X#define DefMinor(x)	(FUNCTION|MINOR_MODE|(x << 8))
X
extern Buffer	*world,		/* first buffer */
X		*curbuf;	/* pointer into world for current buffer */
X
X#define curline	curbuf->b_dot
X#define curchar curbuf->b_char
X
X#define NUMKILLS	10	/* number of kills saved in the kill ring */
X
X#ifdef MAC		/* when doing ~DIRTY, we need high bits set */
X#	define DIRTY	(disk_line) 01	/* just needs updating for some reason */
X#else
X#	define DIRTY	01	/* just needs updating for some reason */
X#endif
X#define MODELINE	02	/* this is a modeline */
X#define L_MOD		04	/* this line has been modified internally */
X
struct scrimage {
X	int	s_offset,	/* offset to start printing at */
X		s_flags,	/* various flags */
X		s_id,		/* which buffer line */
X		s_vln;		/* Visible Line Number */
X	Line	*s_lp;		/* so we can turn off red bit */
X	Window	*s_window;	/* window that contains this line */
X};
X
extern struct scrimage
X	*DesiredScreen,		/* what we want */
X	*PhysScreen;		/* what we got */
X
X/* Variable flags (that can be set). */
X#define V_BASE10	01	/* is integer in base 10 */
X#define V_BASE8		02	/* is integer in base 8 */
X#define V_BOOL		04	/* is a boolean */
X#define V_STRING	010	/* is a string */
X#define V_CHAR		020	/* is a character */
X#define V_FILENAME	040	/* a file name (implies V_STRING) */
X#define V_TYPEMASK	077	/* mask off the extra bits */
X#define V_MODELINE	0100	/* update modeline */
X#define V_CLRSCREEN	0200	/* clear and redraw screen */
X#define V_TTY_RESET	0400	/* redo the tty modes */
X
X#ifdef MAC
X#ifdef TXT_TO_C
int		/* kludge, so setmaps will compile with variables */
X#else
extern int
X#endif /* TXT_TO_C */
X#else
extern int
X#endif	/* MAC */
X
X	OKXonXoff,		/* disable start/stop characters */
X	MetaKey,		/* this terminal has a meta key */
X	VisBell,		/* use visible bell (if possible) */
X	WrapScan,		/* make searches wrap */
X#ifndef MAC
X	phystab,		/* terminal's tabstop settings */ 
X#endif
X	tabstop,		/* expand tabs to this number of spaces */
X#ifdef BACKUPFILES
X	BkupOnWrite,		/* make backup files when writing */
X#endif
X	RMargin,		/* right margin */
X	LMargin,		/* left margin */
X	ScrollStep,		/* how should we scroll */
X#ifndef MAC
X	WtOnMk,			/* write files on compile-it command */
X#endif
X	EndWNewline,		/* end files with a blank line */
X	MarkThresh,		/* moves greater than MarkThresh will SetMark */
X	PDelay,			/* paren flash delay in tenths of a second */
X	CIndIncrmt,		/* how much each indentation level pushes
X				   over in C mode */
X	CreatMode,		/* default mode for creat'ing files */
X	CaseIgnore,		/* case ignore search */
X#ifdef ABBREV
X	AutoCaseAbbrev,		/* automatically do case on abbreviations */
X#endif
X	MarksShouldFloat,	/* adjust marks on insertion/deletion */
X	UseRE,			/* use regular expressions in search */
X	SyncFreq,		/* how often to sync the file pointers */
X	BriteMode,		/* make the mode line inverse? */
X	OkayBadChars,		/* allow bad characters in files created
X				   by JOVE */
X	UpdFreq,		/* how often to update modeline */
X	UseBuffers,		/* use buffers with Typeout() */
X#ifdef BIFF
X	BiffChk,		/* turn off/on biff with entering/exiting jove */
X#endif
X	MailInt,		/* mail check interval */
X#ifdef ID_CHAR
X	UseIC,			/* whether or not to use i/d char
X				   processesing */
X#endif
X	SExitChar,		/* type this to stop i-search */
X	AbortChar,		/* cancels command input */
X	IntChar,		/* ttysets this to generate QUIT */
X	DoEVexpand,		/* treat $foo as environment variable */
X#ifdef F_COMPLETION
X 	DispBadFs,		/* display filenames with bad extensions? */
X#endif	
X#ifdef IBMPC
X	Fgcolor,
X	Bgcolor,
X	Mdcolor,
X#endif /* IBMPC */
X#ifdef F_COMPLETION
X	DispBadFs,		/* display filenames with bad extensions? */
X#endif
X	ScrollAll,		/* we current line scrolls, scroll whole window? */
X#ifndef MAC
X	EWSize;			/* size to make the error window */
X#else	
X	Macmode,	/* see mac.c */
X	Keyonly,
X	Bufchange,
X	Modechange,
X	Windchange,
X	EventCmd;
X#endif	/* MAC */
X
X#ifdef MAC
X#	ifdef TXT_TO_C	/* kludge, for setmaps with variables */
char
X#	else
extern char
X#	endif /* TXT_TO_C */
X#else
extern char
X#endif /* MAC */
X
X#ifndef MAC
X	ErrFmtStr[256],		/* format string for parse errors */
X#endif
X#ifdef IPROCS
X	proc_prompt[128],	/* process prompt */
X#endif
X#ifdef F_COMPLETION
X	BadExtensions[128],	/* extensions (e.g., ".o" to ignore) */
X#endif
X#ifdef CMT_FMT
X	CmtFmt[80],
X#endif
X	ModeFmt[120],		/* mode line format string */
X#ifdef UNIX
X	Mailbox[FILESIZE],		/* mailbox name */
X#endif /* UNIX */
X	TmpFilePath[FILESIZE],	/* directory/device to store tmp files */
X	TagFile[FILESIZE],		/* default tag file */
X	Shell[FILESIZE];		/* shell to use */
X
extern int
X	TOabort,	/* flag set by Typeout() */
X	io,		/* file descriptor for reading and writing files */
X	errormsg,	/* last message was an error message
X			   so don't erase the error before it
X			   has been read */
X	this_cmd,	/* ... */
X	last_cmd,	/* last command ... to implement appending
X			   to kill buffer */
X	RecDepth,	/* recursion depth */
X	InputPending,	/* nonzero if there is input waiting to
X			   be processed */
X 	killptr,	/* index into killbuf */
X	CanScroll,	/* can this terminal scroll? */
X	Crashing,	/* we are in the middle of crashing */
X	Asking,		/* are we on read a string from the terminal? */
X	inIOread;	/* so we know whether we can do a redisplay. */
X
extern char	Minibuf[LBSIZE];
X
X#define curmark		(curbuf->b_markring[curbuf->b_themark])
X#define b_curmark(b)	(b->b_markring[b->b_themark])
X
extern Line	*killbuf[NUMKILLS];	/* array of pointers to killed stuff */
X
X#define MESG_SIZE 128
extern char	mesgbuf[MESG_SIZE];
X
struct screenline {
X	char	*s_line,
X		*s_length;
X};
X
extern int
X	LastKeyStruck;
X
extern int
X	InMacDefine,	/* are we defining a macro right now? */
X
X	CapLine,	/* cursor line and cursor column */
X	CapCol,
X
X	UpdModLine,	/* whether we want to update the mode line */
X	UpdMesg;	/* update the message line */
X
X#define CATCH \
X{\
X	jmp_buf	sav_jmp; \
X\
X	push_env(sav_jmp); \
X	if (setjmp(mainjmp) == 0) {
X
X#define ONERROR \
X	} else { \
X
X#define ENDCATCH \
X	} \
X	pop_env(sav_jmp); \
X}
X
X#include "externs.h"
END_OF_FILE
if test 16194 -ne `wc -c <'./jove.h'`; then
    echo shar: \"'./jove.h'\" unpacked with wrong size!
fi
# end of './jove.h'
fi
if test -f './util.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'./util.c'\"
else
echo shar: Extracting \"'./util.c'\" \(16153 characters\)
sed "s/^X//" >'./util.c' <<'END_OF_FILE'
X/***************************************************************************
X * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
X * is provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is    *
X * included in all the files.                                              *
X ***************************************************************************/
X
X#include "jove.h"
X#include "ctype.h"
X#include "termcap.h"
X#include <signal.h>
X
X#ifdef MAC
X#	include "mac.h"
X#else
X#	include <varargs.h>
X#endif
X
X#ifdef MSDOS
X#include <time.h>
X#endif
X
struct cmd *
FindCmd(proc)
register void 	(*proc)();
X{
X	register struct cmd	*cp;
X
X  	for (cp = commands; cp->Name; cp++)
X		if (cp->c_proc == proc)
X			return cp;
X	return 0;
X}
X
int	Interactive;	/* True when we invoke with the command handler? */
data_obj	*LastCmd;
char	*ProcFmt = ": %f ";
X
void
ExecCmd(cp)
data_obj	*cp;
X{
X	LastCmd = cp;
X	if (cp->Type & MAJOR_MODE)
X		SetMajor((cp->Type >> 8));
X	else if (cp->Type & MINOR_MODE)
X		TogMinor((cp->Type >> 8));
X	else	switch (cp->Type&TYPEMASK) {
X		case MACRO:
X			do_macro((struct macro *) cp);
X			break;
X
X		case FUNCTION:
X		    {
X		    	struct cmd	*cmd = (struct cmd *) cp;
X
X			if (cmd->c_proc)
X				(*cmd->c_proc)();
X		    }
X	}
X}
X
Line *
lastline(lp)
register Line	*lp;
X{
X	register Line	*next;
X
X	while (next = lp->l_next)
X		lp = next;
X	return lp;
X}
X
private int	*slowp = 0;
X
char	key_strokes[100];
private char	*key_p = key_strokes;
X
void
init_strokes()
X{
X	key_strokes[0] = 0;
X	key_p = key_strokes;
X}
X
void
add_stroke(c)
X{
X	if (key_p + 5 > &key_strokes[(sizeof key_strokes) - 1])
X		key_p = key_strokes;
X	sprintf(key_p, "%p ", c);
X	key_p += strlen(key_p);
X}
X
void
slowpoke()
X{
X	if (slowp)
X		*slowp = YES;
X	f_mess(key_strokes);
X}
X
X#ifdef UNIX
X#ifdef BSD4_2
X#	define N_SEC	1	/* will be precisely 1 second on 4.2 */
X#else
X#	define N_SEC	2	/* but from 1 to 2 seconds otherwise */
X#endif
X#else /* MSDOS or MAC */
X#define N_SEC	1
int in_macro();
X#endif /* UNIX */
X
int
waitchar(slow)
int	*slow;
X{
X#ifdef UNIX
X#ifdef EUNICE
X	return getch();
X#endif
X	unsigned int	old_time;
X	int	c;
X	int	(*oldproc)();
X#else /* MSDOS or MAC */
X	long sw, time();
X#endif /* UNIX */
X
X	slowp = slow;
X	if (slow)
X		*slow = NO;
X#ifdef UNIX
X	oldproc = signal(SIGALRM, slowpoke);
X
X	if ((old_time = alarm((unsigned) N_SEC)) == 0)
X		old_time = UpdFreq;
X	c = getch();
X	(void) alarm(old_time);
X	(void) signal(SIGALRM, oldproc);
X
X	return c;
X#else /* MSDOS or MAC */
X#ifdef MAC
X	Keyonly = 1;
X	if(charp() || in_macro()) return getch();	/* to avoid flicker */
X#endif
X	time(&sw);
X	sw += N_SEC;
X	while(time(NULL) <= sw)
X		if (charp() || in_macro())
X			return getch();
X#ifdef MAC
X	menus_off();
X#endif
X	slowpoke();
X	return getch();
X#endif /* UNIX */
X}
X
X/* dir > 0 means forward; else means backward. */
X
char *
StrIndex(dir, buf, charpos, what)
char	*buf,
X	what;
X{
X	char	*cp = &buf[charpos],
X		c;
X
X	if (dir > 0) {
X		while (c = *cp++)
X			if (c == what)
X				return (cp - 1);
X	} else {
X		while (cp >= buf && (c = *cp--))
X			if (c == what)
X				return (cp + 1);
X	}
X	return 0;
X}
X
int
blnkp(buf)
register char	*buf;
X{
X	register char	c;
X
X	while ((c = *buf++) && (c == ' ' || c == '\t'))
X		;
X	return c == 0;	/* It's zero if we got to the end of the Line */
X}
X
Line *
next_line(line, num)
register Line	*line;
register int	num;
X{
X	if (num < 0)
X		return prev_line(line, -num);
X	if (line)
X		while (--num >= 0 && line->l_next != 0)
X			line = line->l_next;
X	return line;
X}
X
Line *
prev_line(line, num)
register Line	*line;
register int	num;
X{
X	if (num < 0)
X		return next_line(line, -num);
X	if (line)
X		while (--num >= 0 && line->l_prev != 0)
X			line = line->l_prev;
X	return line;
X}
X
void
DotTo(line, col)
Line	*line;
X{
X	Bufpos	bp;
X
X	bp.p_line = line;
X	bp.p_char = col;
X	SetDot(&bp);
X}
X
X/* If bp->p_line is != current line, then save current line.  Then set dot
X   to bp->p_line, and if they weren't equal get that line into linebuf.  */
X
void
SetDot(bp)
register Bufpos	*bp;
X{
X	register int	notequal;
X
X	if (bp == 0)
X		return;
X
X	notequal = bp->p_line != curline;
X	if (notequal)
X		lsave();
X	if (bp->p_line)
X		curline = bp->p_line;
X	if (notequal)
X		getDOT();
X	curchar = bp->p_char;
X	if (curchar > length(curline))
X		curchar = length(curline);
X}
X
void
ToLast()
X{
X	SetLine(curbuf->b_last);
X	Eol();
X}
X
int	MarkThresh = 22;	/* average screen size ... */
static int	line_diff;
X
int
LineDist(nextp, endp)
register Line	*nextp,
X		*endp;
X{
X	(void) inorder(nextp, 0, endp, 0);
X	return line_diff;
X}
X
int
inorder(nextp, char1, endp, char2)
register Line	*nextp,
X		*endp;
X{
X	int	count = 0;
X	register Line	*prevp = nextp;
X
X	line_diff = 0;
X	if (nextp == endp)
X		return char1 < char2;
X
X	while (nextp || prevp) {
X		if (nextp == endp || prevp == endp)
X			break;
X		if (nextp)
X			nextp = nextp->l_next;
X		if (prevp)
X			prevp = prevp->l_prev;
X		count += 1;
X	}
X	if (nextp == 0 && prevp == 0)
X		return -1;
X	line_diff = count;
X
X	return nextp == endp;
X}
X
void
PushPntp(line)
register Line	*line;
X{
X	if (LineDist(curline, line) >= MarkThresh)
X		set_mark();
X}
X
void
ToFirst()
X{
X	SetLine(curbuf->b_first);
X}
X
int
length(line)
Line	*line;
X{
X	return strlen(lcontents(line));
X};
X
void
to_word(dir)
register int	dir;
X{
X	register char	c;
X
X	if (dir == FORWARD) {
X		while ((c = linebuf[curchar]) != 0 && !isword(c))
X			curchar += 1;
X		if (eolp()) {
X			if (curline->l_next == 0)
X				return;
X			SetLine(curline->l_next);
X			to_word(dir);
X			return;
X		}
X	} else {
X		while (!bolp() && (c = linebuf[curchar - 1], !isword(c)))
X			curchar -= 1;
X		if (bolp()) {
X			if (curline->l_prev == 0)
X				return;
X			SetLine(curline->l_prev);
X			Eol();
X			to_word(dir);
X		}
X	}
X}
X
X/* Are there any modified buffers?  Allp means include B_PROCESS
X   buffers in the check. */
X
int
ModBufs(allp)
X{
X	register Buffer	*b;
X
X	for (b = world; b != 0; b = b->b_next) {
X		if (b->b_type == B_SCRATCH)
X			continue;
X		if ((b->b_type == B_FILE || allp) && IsModified(b))
X			return 1;
X	}
X	return 0;
X}
X
char *
filename(b)
register Buffer	*b;
X{
X	return b->b_fname ? pr_name(b->b_fname, YES) : "[No file]";
X}
X
char *
itoa(num)
register int	num;
X{
X	static char	line[15];
X
X	sprintf(line, "%d", num);
X	return line;
X}
X
int
min(a, b)
register int	a,
X		b;
X{
X	return (a < b) ? a : b;
X}
X
int
max(a, b)
register int	a,
X		b;
X{
X	return (a > b) ? a : b;
X}
X
void
tiewind(w, bp)
register Window	*w;
register Buffer	*bp;
X{
X	int	not_tied = (w->w_bufp != bp);
X
X	UpdModLine = YES;	/* kludge ... but speeds things up considerably */
X	w->w_line = bp->b_dot;
X	w->w_char = bp->b_char;
X	w->w_bufp = bp;
X	if (not_tied)
X		CalcWind(w);	/* ah, this has been missing since the
X				   beginning of time! */
X}
X
extern int	Jr_Len;
X
char *
lcontents(line)
register Line	*line;
X{
X	if (line == curline)
X		return linebuf;
X	else
X		return lbptr(line);
X}
X
char *
ltobuf(line, buf)
Line	*line;
char	*buf;
X{
X	if (line == curline) {
X		if (buf != linebuf)
X			strcpy(buf, linebuf);
X		Jr_Len = strlen(linebuf);
X	} else
X		getline(line->l_dline, buf);
X	return buf;
X}
X
void
DOTsave(buf)
Bufpos *buf;
X{
X	buf->p_line = curline;
X	buf->p_char = curchar;
X}
X
X/* Return none-zero if we had to rearrange the order. */
X
int
fixorder(line1, char1, line2, char2)
register Line	**line1,
X		**line2;
register int	*char1,
X		*char2;
X{
X	Line	*tline;
X	int	tchar;
X
X	if (inorder(*line1, *char1, *line2, *char2))
X		return 0;
X
X	tline = *line1;
X	tchar = *char1;
X	*line1 = *line2;
X	*char1 = *char2;
X	*line2 = tline;
X	*char2 = tchar;
X
X	return 1;
X}
X
int
inlist(first, what)
register Line	*first,
X		*what;
X{
X	while (first) {
X		if (first == what)
X			return 1;
X		first = first->l_next;
X	}
X	return 0;
X}
X
X/* Make `buf' (un)modified and tell the redisplay code to update the modeline
X   if it will need to be changed. */
X
int	ModCount = 0;
X
void
modify()
X{
X	extern int	DOLsave;
X
X	if (!curbuf->b_modified) {
X		UpdModLine = YES;
X		curbuf->b_modified = YES;
X	}
X	DOLsave = YES;
X	if (!Asking)
X		ModCount += 1;
X}
X
void
unmodify()
X{
X	if (curbuf->b_modified) {
X		UpdModLine = YES;
X		curbuf->b_modified = NO;
X	}
X}
X
int
numcomp(s1, s2)
register char	*s1,
X		*s2;
X{
X	register int	count = 0;
X
X	while (*s1 != 0 && *s1++ == *s2++)
X		count += 1;
X	return count;
X}
X
char *
copystr(str)
char	*str;
X{
X	char	*val;
X
X	if (str == 0)
X		return 0;
X	val = emalloc(strlen(str) + 1);
X
X	strcpy(val, str);
X	return val;
X}
X
X#ifndef byte_copy
void
byte_copy(from, to, count)
register char	*from,
X		*to;
register int	count;
X{
X	while (--count >= 0)
X		*to++ = *from++;
X}
X#endif
X
void
len_error(flag)
X{
X	char	*mesg = "[line too long]";
X
X	if (flag == COMPLAIN) complain(mesg);
X		else error(mesg);
X}
X
X/* Insert num number of c's at offset atchar in a linebuf of LBSIZE */
X
void
ins_c(c, buf, atchar, num, max)
char	c, *buf;
X{
X	register char	*pp, *pp1;
X	register int	len;
X	int	numchars;	/* number of characters to copy forward */
X
X	if (num <= 0)
X		return;
X	len = atchar + strlen(&buf[atchar]);
X	if (len + num >= max)
X		len_error(COMPLAIN);
X	pp = &buf[len + 1];		/* + 1 so we can --pp (not pp--) */
X	pp1 = &buf[len + num + 1];
X	numchars = len - atchar;
X	while (numchars-- >= 0)
X		*--pp1 = *--pp;
X	pp = &buf[atchar];
X	while (--num >= 0)
X		*pp++ = c;
X}
X
int
TwoBlank()
X{
X	register Line	*next = curline->l_next;
X
X	return ((next != 0) &&
X		(*(lcontents(next)) == '\0') &&
X		(next->l_next != 0) &&
X		(*(lcontents(next->l_next)) == '\0'));
X}
X
void
linecopy(onto, atchar, from)
register char	*onto,
X		*from;
X{
X	register char	*endp = &onto[LBSIZE - 2];
X
X	onto += atchar;
X
X	while (*onto = *from++)
X		if (onto++ >= endp)
X			len_error(ERROR);
X}
X
char *
IOerr(err, file)
char	*err, *file;
X{
X	return sprint("Couldn't %s \"%s\".", err, file);
X}
X
X#ifdef UNIX
void
pclose(p)
int	*p;
X{
X	(void) close(p[0]);
X	(void) close(p[1]);
X}
X
void
dopipe(p)
int	p[];
X{
X	if (pipe(p) == -1)
X		complain("[Pipe failed]");
X}
X
X#endif /* UNIX */
X/* NOSTRICT */
X
char *
emalloc(size)
X{
X	register char	*ptr;
X
X	if (ptr = malloc((unsigned) size))
X		return ptr;
X	/* Try garbage collecting lines */
X	GCchunks();
X	if (ptr = malloc((unsigned) size))
X		return ptr;
X	/* Uh ... Oh screw it! */
X	error("[Out of memory] ");
X	/* NOTREACHED */
X}
X
X/* Return the basename of file F. */
X
char *
basename(f)
register char	*f;
X{
X	register char	*cp;
X
X	if (cp = rindex(f, '/'))
X		return cp + 1;
X	else
X#ifdef MSDOS
X		if (cp = rindex(f, '\\'))
X			return cp + 1;
X	else
X		if (cp = rindex(f, ':'))
X			return cp + 1;
X#endif /* MSDOS */
X		return f;
X}
X
void
push_env(savejmp)
jmp_buf	savejmp;
X{
X	byte_copy((char *) mainjmp, (char *) savejmp, sizeof (jmp_buf));
X}
X
void
pop_env(savejmp)
jmp_buf	savejmp;
X{
X	byte_copy((char *) savejmp, (char *) mainjmp, sizeof (jmp_buf));
X}
X
X#ifdef LOAD_AV
X# if defined(BSD4_2) && !defined(BSD2_10)
X#   if defined(PURDUE_EE) && (defined(vax) || defined(gould))
X
void
get_la(dp)
double *dp;
X{
X	*dp = (double) loadav(0) / 100.0;
X}
X
X#   else /* !PURDUE_EE || (!vax && !gould) */ 
X
X#ifdef sun
X#   include <sys/param.h>
X#endif
X#include <nlist.h>
X
static struct	nlist nl[] = {
X	{ "_avenrun" },
X#define	X_AVENRUN	0
X	{ "" }
X};
X
void
get_la(dp)
double	*dp;
X{
X#ifdef sun
X	long	avenrun[3];
X#else
X	double	avenrun[3];
X#endif
X	static int	kmem = 0;
X
X	if (kmem == -1) {
X		*dp = 4.0;	/* So shell commands will say "Chugging" */
X		return;
X	} else if (kmem == 0) {
X		if ((kmem = open("/dev/kmem", 0)) == -1) {
X			f_mess("Can't open kmem for load average.");
X			*dp = 4.0;
X			return;
X		}
X		nlist("/vmunix", nl);
X	}
X	lseek(kmem, (long) nl[X_AVENRUN].n_value, 0);
X	read(kmem, (char *) avenrun, sizeof(avenrun));
X#ifdef sun
X	*dp = (double) avenrun[0] / FSCALE;
X#else
X	*dp = avenrun[0];
X#endif
X}
X
X#    endif
X#  else /* !BSD4_2 || BSD2_10 */
X
void
get_la(dp)
double	*dp;
X{
X	short	avg[3];
X
X	gldav(avg);
X	*dp = (double) avg[0] / 256;
X}
X
X#  endif
X#endif /* LOAD_AV */
X
X/* get the time buf, designated by *timep, from FROM to TO. */
char *
get_time(timep, buf, from, to)
char	*buf;
time_t	*timep;
X{
X	time_t	now;
X	char	*cp;
X	extern char	*ctime();
X
X	if (timep != 0)
X		now = *timep;
X	else
X		(void) time(&now);
X	cp = ctime(&now) + from;
X#ifndef MSDOS
X	if (to == -1)
X#else /* MSDOS */
X	if ((to == -1) && (cp[strlen(cp)-1] == '\n'))
X#endif /* MSDOS */
X		cp[strlen(cp) - 1] = '\0';		/* Get rid of \n */
X	else
X		cp[to - from] = '\0';
X	if (buf) {
X		strcpy(buf, cp);
X		return buf;
X	} else
X		return cp;
X}
X
X#ifndef MSDOS
X#ifndef MAC
int
strlen(s)
register char	*s;
X{
X	register char	*base = s;
X
X	while (*s++)
X		;
X	return (s - base) - 1;
X}
X
char *
index(s, c)
register char	*s;
register int	c;
X{
X	register int	c1;
X
X	if (c != 0)
X		while (c1 = *s++)
X			if (c == c1)
X				return s - 1;
X	return 0;
X}
X
int
strcmp(s1, s2)
register char	*s1,
X		*s2;
X{
X	if (!s1 || !s2)
X		return 1;	/* which is not zero ... */
X	while (*s1 == *s2++)
X		if (*s1++ == '\0')
X			return 0;
X	return (*s1 - *--s2);
X}
X
X#endif /* MAC */
X#endif /* MSDOS */
X
int
casecmp(s1, s2)
register char	*s1,
X		*s2;
X{
X	if (!s1 || !s2)
X		return 1;	/* which is not zero ... */
X	while (CharUpcase(*s1) == CharUpcase(*s2++))
X		if (*s1++ == '\0')
X			return 0;
X	return (*s1 - *--s2);
X}
X
int
casencmp(s1, s2, n)
register char	*s1,
X		*s2;
register int	n;
X{
X	if (!s1 || !s2)
X		return 1;	/* which is not zero ... */
X	while (--n >= 0  && (CharUpcase(*s1) == CharUpcase(*s2++)))
X		if (*s1++ == '\0')
X			return 0;
X	return ((n < 0) ? 0 : *s1 - *--s2);
X}
X
void
null_ncpy(to, from, n)
char	*to,
X	*from;
X{
X	(void) strncpy(to, from, n);
X	to[n] = '\0';
X}
X
X#ifndef MSDOS
X#ifndef MAC
void
strcpy(t, f)
register char	*t,
X		*f;
X{
X	while (*t++ = *f++)
X		;
X}
X
X#endif /* MAC */
X#endif /* MSDOS */
X
X/* Tries to pause for delay/10 seconds OR until a character is typed
X   at the keyboard.  This works well on BSD4_2 and not so well on the
X   rest.  Returns 1 if it returned because of keyboard input, or 0
X   otherwise. */
X
X#ifdef MAC
void
SitFor(delay)
unsigned int	delay;
X{
X	long	start,
X		end;
X
X#define Ticks (long *) 0x16A	/* 1/60 sec */
X	Keyonly = 1;
X	redisplay();
X	start = *Ticks;
X
X	end = start + delay * 6;
X	do
X		if (InputPending = charp())
X			break;
X	while (*Ticks < end);
X}
X#else	/* not MAC */
X
void
SitFor(delay)
unsigned int	delay;
X{
X#ifndef MSDOS
X#if defined(BSD4_2) && !defined(BSD2_10)
X#include <sys/time.h>
X
X	struct timeval	timer;
X	long	readfds = 1;
X
X	timer.tv_sec = (delay / 10);
X	timer.tv_usec = (delay % 10) * 100000;
X
X	if (charp())
X		return;
X	/* gross that I had to snarf this from getch() */
X	if (!UpdMesg && !Asking) {	/* Don't erase if we are asking */
X		if (mesgbuf[0] && !errormsg)
X			message(NullStr);
X	}
X	redisplay();
X	select(1, &readfds, (long *)0, (long *)0, &timer);
X#else
X	static int cps[] = {
X		0,
X		5,
X		7,
X		11,
X		13,
X		15,
X		20,
X		30,
X		60,
X		120,
X		180,
X		240,
X		480,
X		960,
X		1920,
X		1920,
X	};
X	register int	nchars,
X			check_cnt;
X
X	if (charp())
X		return;
X	nchars = (delay * cps[ospeed]) / 10;
X	check_cnt = BufSize;
X	redisplay();
X	while ((--nchars > 0) && !InputPending) {
X		putchar(0);
X		if (--check_cnt == 0) {
X			check_cnt = BufSize;
X			InputPending = charp();
X		}
X	}
X#endif
X#else /* MSDOS */
X#include <bios.h>
X#include <dos.h>
X
X	long	start,
X		end;
X#ifndef IBMPC
X	struct dostime_t tc;
X#endif	
X
X	redisplay();
X#ifdef IBMPC
X	_bios_timeofday(_TIME_GETCLOCK, &start);
X#else
X	_dos_gettime(&tc);
X	start = (long)(tc.hour*60L*60L*10L)+(long)(tc.minute*60L*10L)+
X            (long)(tc.second*10)+(long)(tc.hsecond/10);
X#endif
X	end = (start + delay);
X	do  {
X		if (InputPending = charp())
X			break;
X#ifdef IBMPC
X        if (_bios_timeofday(_TIME_GETCLOCK, &start))
X		    break;	/* after midnight */
X#else
X	    start = (long)(tc.hour*60L*60L*10L)+(long)(tc.minute*60L*10L)+
X                (long)(tc.second*10)+(long)(tc.hsecond/10);
X#endif
X	}
X	while (start < end);
X#endif /* MSDOS */
X}
X#endif /* MAC */
X
int
sindex(pattern, string)
register char	*pattern,
X		*string;
X{
X	register int	len = strlen(pattern);
X
X	while (*string != '\0') {
X		if (*pattern == *string && strncmp(pattern, string, len) == 0)
X			return TRUE;
X		string += 1;
X	}
X	return FALSE;
X}
X
void
make_argv(argv, ap)
register char	*argv[];
va_list	ap;
X{
X	register char	*cp;
X	register int	i = 0;
X
X	argv[i++] = va_arg(ap, char *);
X	argv[i++] = basename(argv[0]);
X	while (cp = va_arg(ap, char *))
X		argv[i++] = cp;
X	argv[i] = 0;
X}
X
int
pnt_line()
X{
X	register Line	*lp = curbuf->b_first;
X	register int	i;
X
X	for (i = 0; lp != 0; i++, lp = lp->l_next)
X		if (lp == curline)
X			break;
X	return i + 1;
X}
END_OF_FILE
if test 16153 -ne `wc -c <'./util.c'`; then
    echo shar: \"'./util.c'\" unpacked with wrong size!
fi
# end of './util.c'
fi
echo shar: End of archive 8 \(of 21\).
cp /dev/null ark8isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 21 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.