Vile 16/17 - vi feel-alike (multi-window)
Paul Fox
pgf at cayman.COM
Sat Jun 8 08:10:23 AEST 1991
#!/bin/sh
# this is vileshar.16 (part 16 of Vile)
# do not concatenate these parts, unpack them in order with /bin/sh
# file vile.hlp continued
#
if test ! -r _shar_seq_.tmp; then
echo 'Please unpack part 1 first!'
exit 1
fi
(read Scheck
if test "$Scheck" != 16; then
echo Please unpack part "$Scheck" next!
exit 1
else
exit 0
fi
) < _shar_seq_.tmp || exit 1
echo 'x - continuing file vile.hlp'
sed 's/^X//' << 'SHAR_EOF' >> 'vile.hlp' &&
X single following digit.) Note that since the buffer names
X are displayed in order of use, the list can quickly grow
X "stale" -- the numbers may be meaningless if buffer
X switching has been done since the last display of the list.
X
X The program version is also displayed with this command.
X
X ^A-* Always display a list of all buffers. Useful for updating the
X list if it's already on the screen but may be out of date.
X Any argument will cause the list to include _all_ buffers,
X even those normally considered "invisible". (For example,
X macros are stored in "invisible" buffers.)
X
Window manipulation commands:
-----------------------------
X ^T Make Two windows. Splits the current window in half. This
X is the usual way to create a new window.
X ^K Get rid of (Kill) this window.
X ^O Make this the Only window on the screen.
X
X The emacs-style commands ^X-2, ^X-0, and ^X-1 are also
X included, and are synonymous with ^T, ^K, and ^O.
X
X ^N Go to the next window on the screen.
X ^P Go to the previous window on the screen.
X
X These two commands may be disturbing to vi users who use
X ^N and ^P to move between lines. See the examples under
X Key Rebinding for how to fix this.
X
X v Make the current window smaller.
X V Make the current window larger.
X
X ^A-^D Scroll the next window down half a screen.
X ^A-^U Scroll the next window up half a screen.
X ^A-^E Scroll the next window up one line.
X ^A-^Y Scroll the next window down one line.
X (The previous four commands are useful when comparing two buffers.
X Mnemonic -- think of them as affecting the "A"lternate window.)
X
X zH zM zL These are synonyms for vi's 'z+', 'z.', and 'z-', which
X position the line holding the cursor at the top, middle, or
X bottom of the screen, respectively.
X
X ^X-^R Scroll the window right by 1/3 of a screen, or by the
X number of lines specifed.
X ^X-^L Scroll the window left by 1/3 of a screen, or by the
X number of lines specifed.
X
X If for some reason you can't get your screen set right via a
X TERM variable, try the ":screen-rows" or ":screen-columns"
X commands (which take their args (number of rows or columns
X respectively) before you type the ":").
X
File manipulation commands:
---------------------------
X The usual :e, :r, :f, :w commands are available, though only
X ":e!" is available of the "!" options. The :r command reads the
X named file in after the current line. To read a file before the
X first line, use ":0r".
X
X As in vi, ranges of lines specified by line numbers (including '.',
X '$', and '%' shorthands) or marks may precede these commands.
X Unlike vi, search patterns cannot be used as line specifiers.
X
X In addition, two non-"colon" commands have been added:
X
X ^R Prompts for a filename, and then reads it in _above_ the
X current line. If a register is specified (e.g. "a^R ),
X the file is read into that named register, but not inserted
X into the current buffer.
X
X ^W is a writing operator, which prompts for a filename, and
X writes the specified region to that file. Like all operators,
X it the command is repeated, as in ^W^W, then lines are
X affected. Use 10^W^W to write 10 lines.
X
X If a register is specified (e.g. "a^W ) then the command
X is _not_ an operator, but writes the specified register to
X the named file.
X
Shell Access
------------
X Anywhere a filename is valid, a command name is also
X valid, entered in the form "!shell-command". The whole line is
X handed to the shell, and the read or write operation is done on
X the commands standard input or output, as appropriate. Thus
X you can type ":e !date" to edit a copy of today's date.
X
X The ": !cmd" shell escape works pretty much as it does in vi.
X The command ":!!" will rerun the previous such shell command.
X
X The '!' operator works as expected.
X
X In addition, the ^X-! command runs a shell command and captures
X its output in a specific buffer, called "[Output]". This is
X almost identical to ":e !cmd", except that in that case the buffer
X is named according to the command name.
X
X These output capture commands are most useful in conjunction with
X the "error finder", described below.
X
X On systems supporting job control, ^Z will suspend vile.
X
Text manipulation command:
--------------------------
X Remember, these are only the new or different commands. The
X standard vi set should still work.
X
X Undo ("u") and line-undo ("U") are available for all commands.
X They should be a little less capricious than their
X vi counterparts, since they do not share the default yank register
X for their operation. Also, line-undo ("U") is available until
X the next change anywhere in the file, rather than until you leave
X the line. Unfortunately, the cursor position after an undo may not
X always be the same as it would be in vi.
X
X The vi "global" command is present, in its non-interactive form
X only. So is the "substitute" command. These both look pretty
X different while they're being used than they do in vi, and since
X the searching is done right after the pattern is entered, there
X can be a long delay while you're trying to finish typing your
X complete command. You can type commands just as you would have
X in vi, i.e. ":g/oldpat/s//newstring/" will work. But you won't
X see any of the '/' characters. Try it-- you'll get the idea.
X Line ranges are not possible on ":g", but they are on ":s".
X
X The ":v" counterpart to ":g" is not implemented.
X
X The ":g" command can be followed by any of l (list), p (print),
X < (left shift), > (right shift), r (read file), d (delete),
X L (lower case), U (upper case), ~ (flip case), put (append
X yanked text), Put (prepend yanked text), s (substitute),
X t (trim trailing whitespace). For example, ":g/pattern/Put"
X will insert the contents of the default yank register just
X above every line containing "pattern".
X
X Operators
X ---------
X Vi has a class of commands known as "operators". Operator
X commands are always immediately followed by a motion command.
X The text affected by an operator is bounded by the initial
X position, and the cursor position after the motion is
X completed. Thus the delete operator ('d') can be followed by
X the word motion command ('w'), causing the next word to be
X deleted. The sequence "dG" will delete through the end of the
X file, and "d/junk" will delete to the next occurence of the
X string "junk". Operators can all be "stuttered" to affect
X lines. Thus "dd" deletes one line, "4dd" affects 4 lines,
X etc.
X
X Some operators in vile can be forced to affect whole lines,
X though the motion wouldn't normally imply it, by using the ^X
X form of the command. For example, "d%" (assuming you are on a
X curly brace) will delete a C-style block of code. "^X-d%"
X will delete that same area, plus anything else on the lines
X containing the curly- brace endpoints.
X
X Note that some operators always affect whole lines, no matter
X how the motion is specified. For instance, "!w" will always
X filter an entire line, and not just a single word.
X
X There are several new operator commands:
X
X ^A-~ Is the operator form of the '~' command, so "^A-~~"
X changes the case of all characters on the current
X line, "^A-~w" does it to a word, "3^A-~}" does it for
X 3 paragraphs, etc.
X ^A-u Like ^A-~, but converts the region to upper case.
X ^A-l Like ^A-~, but converts the region to lower case.
X
X ^A-f Format the region based on the current fill column. The
X initial indentation of both the first and second lines
X of the region are preserved, and all subsequent lines
X get the second line's indentation. This makes indented/
X outdented paragraphs work correctly. The usual use of
X this command is "^A-f}", which does it to the current
X paragraph. (This is intentionally _not_ the same bevavior
X obtained by "!fmt", since that behavior is obviously
X available elsewhere.)
X
X ^X-d Delete the region, including the lines it starts and ends on.
X ^X-c Change the region, including the lines it starts and ends on.
X ^X-y Yank the region, including the lines it starts and ends on.
X
X Text insertion
X --------------
X ^X-p Causes the previously yanked or deleted text, no matter
X how it was obtained, to be inserted after the current line.
X Usually text that did not consist of whole lines where it
X came from is inserted immediately following the cursor.
X ^X-P As above, but the text is put before the current line.
X Thus "dw" followed by a "p" command does a normal insertion
X of the deleted word, whereas "^X-p" results in the word
X being inserted on a line by itself.
X
X Searching
X ---------
X ^X-/ Does a forward search for the "word" located under the
X cursor.
X ^X-? Does a reverse search for the "word" located under the
X cursor.
X ^A-/ Does not do a search, but sets the search pattern to the
X "word" under the cursor. Useful for "picking up" a word
X from one buffer, and searching for it in another.
X
X The following two commands may not always be present in vile,
X depeinding on how it was built:
X ^X-S Incremental forward searching. As you enter the search
X string, the cursor is advanced to the next match with
X what you've typed so far. Use ^F and ^R to continue the
X search forward or in reverse, using the current pattern.
X ^X-R As above, but in reverse.
X
X Tags
X ----
X Vile supports vi-style "tags" files.
X
X ":ta" or ":tag" allows you to enter a tagname to locate. Changes
X to that file and location.
X ^] Uses the identifier currently under the cursor as the
X tagname.
X ^X-^] "Un-tag" - pops to the file and location just previous to
X the last tag command. (Some versions of vi have this command
X attached to ^T)
X
X When one of these commands is used, vile will look for a file named
X "tags" in the current directory, and load it into a hidden buffer
X for use during tag searches. This buffer is editable if you wish
X (":e tags"), but will not appear in the buffer lists. If a buffer
X named "tags" is already available when a tag is first requested, it
X will be used instead of a file called "tags", and of course will
X remain visible.
X
X "Advanced" editing
X ------------------
X [ Eventually, these will be rewritten to become "operators", similar to
X those described above. ]
X ^A-<SPACE> Convert tabs to spaces on the current line. An argument
X tells how many lines.
X ^A-<TAB> Convert as many spaces to tabs as possible on the
X current line. Argument tells how many lines.
X ^A-o Remove all but one blank line at the current spot.
X
Miscellaneous commands
----------------------
X ^X-^X The "error finder". Goes to the next file/line error pair
X specified in the last buffer captured from a command's
X output. This buffer is usually created with the ^X-! command.
X For example, "-!cc -c junk.c" puts all of the compiler output
X into the buffer named "[Output]". Repeatedly hitting ^X-^X
X will position the editor at each error in turn, and will
X eventually start over again at the top..
X ^X-t Set or report on the tab-stop width. Tab-stops may only be
X set to 2, 4, 8, or 16 column spacings. To set, the spacing
X must precede the command, as in "4^X-t". The "set tabstop"
X command described below does the same thing.
X ^X-f Set the fill-column to be used with ^A-f and auto-wrap mode on
X insert. The default value is 7/8's of the screen size, with
X a maximum of 70. Since arguments come before commands, you
X type: 65^X-f. The "set fillcol" command does the same thing.
X ^X-x Set encryption key. (not well tested, but hopefully not broken)
X The CRYPT mode must be set for this to do anything.
X K Count prefix. The first time you type it, it is equivalent
X to an argument of 4 to the following command. If you repeat
X it, it becomes worth 16, the next time 64, etc...
X
Editor modes
------------
X Modes are associated with buffers, and are inherited from a set of
X global modes. To set a mode on a buffer, use ":set", to remove the
X mode, use ":unset", ":setno", or ":set" with the modename prefixed
X with "no". To set and reset global modes, use ":setg", ":unsetg",
X ":setgno". To display modes, use ":setall", ":modes", or
X ":setgall", ":gmodes". (The modename "all" is also accepted as a
X dummy mode, which sets nothing, but display instead. So vi's "set all"
X works as well.) The possible modes are:
X
X wrap similar to vi's auto-wrap mode. While inserting, words are
X moved to the next line if the current line gets too long.
X Unlike vi, wrapping is only attempted when a space is typed.
X
X cmode C-code mode.. Maintains current indentation level
X automatically during insert. If a line ends with a '{',
X then the next line tabs in further. If a line begins with
X a '}', it is lined up with its matching paired brace. If a
X line starts with '#' it is started at the beginning of
X line. If the global CMODE is set, then the buffer's mode
X is turned on automatically only for files ending in ".c" or
X ".h". A common mistake is to put "set cmode" in a .vilerc
X file. One almost always wants "setg cmode".
X
X swrap Scanwrap mode. Text searches will continue from past the
X bottom of the file to the top, and vice-versa.
X
X exact Text searches must match the pattern exactly. Otherwise,
X searches are case-insensitive.
X
X view View the file only. No changes are permitted. This is set
X automatically for the output of shell commands.
X
X magic Allow meta-characters in search strings. Otherwise,
X strings are taken literally. Meta characters available are:
X ^ - matches beginning of line
X $ - matches end of line
X . - matches any single character
X * - matches any number of the previous character
X [...] - matches a character class
X \ - take the next character literally
X
X asave Automatic file saving. Writes the file after every 256
X characters of inserted text. Other file changes are not
X counted.
X
X crypt Causes files to be encrypted. This is NOT compatible
X with the UNIX crypt(1) routines.
X
X list The buffer will be displayed with tabs and newlines made
X visible, instead of as whitespace.
X
X dos When writing the buffer, terminate lines with CR/LF pairs,
X rather than the usual single LF. On input, if the global
X DOS mode is set, then incoming CR/LF pairs are taken as
X line terminators, and the local DOS mode is set on the
X buffer if the majority of lines ended that way. If global
X DOS mode is _not_ set, then incoming CR characters will be
X visible on the screen.
X
X aindent Similar to C mode, above, but works for any buffer, and is
X not sensitive to {, }, or #. Attempts to align new lines
X of text with previous lines.
X
X lazy If an attempt is made to edit a file (with ":e filename")
X which does not exist in the current directory, vile will
X try looking for a file of the same name (but in a different
X directory) which has been referenced in the tags file.
X This mode is global to the editor, and is not "inherited"
X by buffers. It's not very fast, either.
X
X tabstop Will prompt for a new value for spacing of tabstops. The
X only supported values are 2, 4, 8, and 16. This value is,
X unfortunately, not settable on a per-buffer basis.
X
X fillcol Will prompt for a new value for the fill column, where
X auto-wrapping and region formatting will break lines. This
X value is, unfortunately, not settable on a per-buffer
X basis.
X
Special Character Expansion
---------------------------
X
X As in vi, the % and # characters typed while responding to a prompt
X will expand to the current or "alternate" filename. In addition,
X the colon character (":") expands to the identifier name under the
X cursor. Expansion of ! to the last command run is not implemented.
X
Key Rebinding
-------------
X
X The vi "map", "map!", and "abbr" commands are not currently supported.
X
X There is a key rebinding facility (if vile is built to include it),
X which is invoked as follows. One must know the "english" name for the
X command being rebound. Use ":describe-bindings" or ":apropos string"
X to find englishnames containing "string". Then use the command:
X ":bind-key englishname keyseq"
X where keyseq is the exact keyboard sequence (i.e. single character,
X or ^X or ^A followed by a single character) to which the
X command should be bound. In a ".vilerc" file, keyseq should be the
X printable representation of the sequence, e.g. M-a or ^X-S.
X
X Examples:
X To cause the / and ? commands to perform incremental
X searches, use:
X bind-key incremental-search /
X bind-key reverse-incremental-search ?
X To change the default window-switching behavior of ^N and ^P, try
X bind-key next-line ^N
X bind-key previous-line ^P
X To cause the space bar to move forward by pages, as in them "more"
X command, use:
X bind-key next-page <sp>
X
X (Space and tab can be represented with the strings: "<sp>" and
X "<tab>".) The englishname "rebind-key" is synonymous with "bind-key".
X
X Note that even the ^A and ^X prefix characters can be rebound, using
X the dummy functions "cntl_a-prefix" and "cntl_x-prefix". Even
X if they are rebound, however, the binding list and bind-key
X commands will refer to them as ^A and ^X.
X
Macros
------
X
X The first type of macro in vile, is for temporary, quick macro
X usage, and lets you record a macro as you execute vile commands.
X You can then replay those keystrokes with a single key.
X
X ^X-( Begin recording a keyboard macro. The keystrokes you type
X are recorded, until you use ^X-).
X ^X-) Finish recording a keyboard macro.
X ^X-& Execute the keyboard macro.
X
X Vile can also be extended (though I confess this has only been
X lightly used or tested) by defining macros and then binding
X execution of those macros to key sequences. For example, if
X the following lines appear in a .vilerc file:
X
X 1 store-macro
X 5 delete-til next-word
X endm
X
X bind-key execute-macro-1 M-1
X
X then when M-1 is executed, 5 words will be deleted. The "-til"
X suffix on an englishname denotes that it is a vi operator style
X command, and expects to be followed by a motion command.
X
Differences
------------
X Of course, this really isn't vi. Some of the following differences
X deserve changing, others do not.
X
X The parser for the ':' commands is not very vi-like. For instance,
X ":e" will prompt you for a file name. Most commands remember their
X last argument, and will present it as the default reply to their
X prompt.
X
X The backspace, line kill, job control, etc. characters are not
X taken from the terminal settings on startup, but are hard-coded.
X The insert-mode command characters cannot even be rebound.
X
X In insert mode there is no word kill (^W) or line kill (^U or @).
X
X Repeated backspacing while in insert mode will move past the point
X where the insert began, until the beginning of line is reached.
X
X There is no expansion of ! in filenames or shell escapes. The
X command ":!!" does rerun the previous shell command. Occurences of
X '#' and '%' are recognized and expanded to the previous or current
X filename. Other punctuation (e.g. '~') may be expanded by your
X shell (sh, csh), since it is handed filenames for expansion if they
X contain any of these characters: * ? ~ [ ] $ { }
X
X Paragraph and section boundaries, for the {, }, [, and ] commands
X are not configurable, and do not exactly match those in vi. The
X current set is:
X Paragraphs: blank lines, or lines beginning in .I .L .P .Q or .b
X Sections: lines beginning in {, formfeeds, or .S .H .N
X I think these will find more boundaries than vi, rather than fewer.
X
X There is no special lisp support. But then, when was the last time
X you heard of a lisp programmer that used vi?
X
X Of course, ex and open mode aren't there.
X
X There is no concept of shiftwidth. ^D and ^T are aliased to backspace
X and tab for those whose fingers are too old for new tricks.
X
X There are no "sentence" oriented motions. That is, "(" and ")" are
X missing.
X
X Most, but not all, of the word-motion-with-operator and end-of-line
X anomalies have been recreated. One missing anomaly: In vile, "dw"
X on the last word of a line ending in whitespace deletes the
X trailing whitespace. Vi does not delete the whitespace.
X
Credits
-------
X This code has been written by a _lot_ of people. Names appearing
X within comments in the micro-Emacs source code are: Dave
X Conroy, Daniel Lawrence, John Gamble, Roger Ove, Dana Hoggatt,
X Jon Reid, Steve Wilhite, George Jones, Adam Fritz, D.R.Banks,
X Bob McNamara. In addition, some of the "ex" code is by Steve
X Kirkendall, author of the vi clone called "elvis". The
X changes to create vile from micro-Emacs were all done by Paul
X Fox, who can be reached at pgf at cayman.com. (By the way, this is
X not the same Paul Fox who did the Crisp editor.)
X
X
SHAR_EOF
echo 'File vile.hlp is complete' &&
chmod 0444 vile.hlp ||
echo 'restore of vile.hlp failed'
Wc_c="`wc -c < 'vile.hlp'`"
test 24385 -eq "$Wc_c" ||
echo 'vile.hlp: original size 24385, current size' "$Wc_c"
# ============= vmalloc.c ==============
echo 'x - extracting vmalloc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'vmalloc.c' &&
#include "estruct.h"
#include "edef.h"
X
/* these routines copied without permission from "The C User's Journal",
X issue of Feb. 1989. I assume they are Copyright 1989 by them.
X They and the accompanying article were written by Eric White */
X
#if VMALLOC
X
#undef malloc
#undef free
#undef realloc
#undef calloc
#undef vverify
X
#include "stdio.h"
#include "string.h"
X
char *malloc(), *calloc(), *realloc();
X
char *vmalloc();
void vfree();
void rvverify();
char *vrealloc();
char *vcalloc();
void vdump();
X
typedef unsigned long ulong;
X
/* max buffers alloced but not yet freed */
#define MAXMALLOCS 20000
X
/* known pattern, and how many of them */
#define KP 0xaaaaaaaaL
#define KPW (2*sizeof(unsigned long))
X
X
static void trace();
static void errout();
X
static int nummallocs = 0;
struct mtype {
X unsigned char *addr;
X int size;
};
X
static struct mtype m[MAXMALLOCS];
X
#define VMAL 1
#define VFRE 2
#define VREA 4
int doverifys = VMAL|VREA; /* |VFRE */
X
static void
dumpbuf(x)
int x;
{
X unsigned char *c;
X char s [80];
X c = (unsigned char *)m[x].addr - 2;
X /* dump malloc buffer to the vmalloc file */
X while (c <= m[x].addr + m[x].size + KPW + KPW + 1) {
X sprintf(s, "%04.4lx : %02x ", (long)c, *c);
X if (c == m[x].addr)
X strcat(s," <= leading known pattern");
X if (c == m[x].addr + KPW)
X strcat(s," <= addr of malloc buffer");
X if (c == m[x].addr + m[x].size + KPW)
X strcat(s," <= trailing known pattern");
X strcat(s,"\n");
X trace(s);
X ++c;
X }
}
X
void
rvverify(id,f,l)
char *id;
char *f;
{
X char s[80];
X register int c;
X register struct mtype *mp;
X
X
X /* verify entire malloc heap */
X for (mp = &m[nummallocs-1]; mp >= m; mp--) {
X if (mp->addr != NULL) {
X if (*(ulong *)mp->addr != KP ||
X *(ulong *)(mp->addr + sizeof (ulong)) != KP)
X {
X sprintf(s,
X "ERROR: Malloc area corrupted (%s). %s %d\n",
X id,f,l);
X fputs(s,stderr);
X trace(s);
X dumpbuf(mp - m);
X errout();
X }
X }
X }
}
X
char *
vmalloc(size,f,l)
char *f;
{
X unsigned char *buffer;
X char *sp, s[80];
X register int c;
X register struct mtype *mp;
X
X if (doverifys & VMAL)
X rvverify("vmalloc",f,l);
X if (( buffer = (unsigned char *)malloc(size + KPW + KPW)) == NULL) {
X sp = "ERROR: real malloc returned NULL\n";
X fprintf(stderr,sp);
X trace(sp);
X errout();
X }
#ifdef VERBOSE
X sprintf(s,"%04.4lx:vmalloc size = %ld, %s %d\n",
X (long)buffer,(long)size,f,l);
X trace(s);
#endif
X /* find a place for an entry in m */
X for (mp = m; mp < &m[MAXMALLOCS] && mp->addr != NULL; ++mp)
X ;
X if (mp == &m[MAXMALLOCS]) {
X sp = "ERROR: too many mallocs\n";
X fprintf(stderr,sp);
X trace(sp);
X errout();
X }
X mp->addr = buffer;
X mp->size = size;
X if (mp == &m[nummallocs])
X ++nummallocs;
X *(ulong *)(mp->addr) = KP;
X *(ulong *)(mp->addr + sizeof(ulong)) = KP;
X return (char *)(buffer + KPW);
}
X
char *
vcalloc(n,size,f,l)
int n, size;
char *f;
{
X return vmalloc(n * size,f,l);
}
X
void
vfree(buffer,f,l)
unsigned char *buffer;
char *f;
{
X unsigned char *b;
X char s[80], *sp;
X register struct mtype *mp;
X
X b = buffer - KPW;
X if (doverifys & VFRE)
X rvverify("vfree",f,l);
X for (mp = &m[nummallocs-1]; mp >= m && mp->addr != b; mp--)
X ;
X if (mp < m) {
X sprintf(s,"ERROR: location to free is not in list. %s %d\n",
X f,l);
X fprintf(stderr,s);
X trace(s);
X errout();
X }
#ifdef VERBOSE
X sprintf(s,"%04.4lx:vfree %s %d\n",(long)b,f,l);
X trace(s);
#endif
X if (*(ulong *)mp->addr != KP ||
X *(ulong *)(mp->addr + sizeof (ulong)) != KP)
X {
X sprintf(s,"ERROR: corrupted freed block. %s %d\n", f,l);
X fprintf(stderr,s);
X trace(s);
X errout();
X }
X free(b);
X mp->addr = NULL;
X if (mp == &m[nummallocs-1])
X --nummallocs;
}
X
char *
vrealloc(buffer,size,f,l)
unsigned char *buffer;
int size;
char *f;
{
X unsigned char *b, *b2;
X char *sp, s[80];
X register int c;
X register struct mtype *mp;
X
X b = buffer - KPW;
X if (doverifys & VREA)
X rvverify("vrealloc",f,l);
X
X for (mp = &m[nummallocs-1]; mp >= m && mp->addr != b; mp--)
X ;
X if (mp < m) {
X sprintf(s,"ERROR: location to realloc is not in list. %s %d\n",
X sp,f,l);
X fprintf(stderr,s);
X trace(s);
X errout();
X }
X
#ifdef VERBOSE
X sprintf(s,"%04.4lx:vrealloc size = %ld, %s %d\n",
X (long)b,(long)size,f,l);
X trace(s);
#endif
X *(ulong *)(mp->addr) = KP;
X *(ulong *)(mp->addr + sizeof (ulong)) = KP;
X b2 = (unsigned char *)realloc(b,size+KPW+KPW);
X *(ulong *)(mp->addr + mp->size + KPW) = KP;
X *(ulong *)(mp->addr + mp->size + KPW + sizeof (ulong)) = KP;
X return (char *)(b2 + KPW);
}
X
void
vdump(id)
char *id;
{
X char s[80];
X int x;
X sprintf(s,"=============Dump of malloc heap==========%s\n",id);
X trace(s);
X for (x = 0; x < nummallocs; ++x) {
X if (m[x].addr != NULL) {
X sprintf(s,"=========malloc buffer addr: %04.4lx\n",
X (long)m[x].addr);
X trace(s);
X sprintf(s,"=========malloc buffer size: %04x\n",
X (long)m[x].size + KPW + KPW);
X trace(s);
X dumpbuf(x);
X }
X }
}
X
static void
trace(s)
char *s;
{
X static FILE *out = NULL;
X if (out == NULL) {
X unlink("vmalloc.log");
X out = fopen("vmalloc.log", "w");
X setbuf(out,NULL);
X }
X fputs(s,out);
}
X
static void
errout()
{
X sleep(1);
X kill(getpid(),3);
X pause();
}
X
setvmalloc(f,n)
{
X register struct mtype *mp;
X int i,num,found;
X
X if (f)
X doverifys = n;
X rvverify("requested",__FILE__,__LINE__);
X for (mp = m, num = 0; mp < &m[MAXMALLOCS]; ++mp) {
X if (mp->addr != NULL)
X num++;
X }
X found = 0;
X { /* windows */
X register WINDOW *wp;
X for (wp=wheadp; wp != NULL; wp = wp->w_wndp)
X found++;
X }
X { /* buffers */
X register BUFFER *bp;
X for (bp=bheadp; bp != NULL; bp = bp->b_bufp) {
X LINE *lp;
X found++; /* for b_linep */
X for(lp = bp->b_linep; lp->l_fp != bp->b_linep;
X lp = lp->l_fp)
X found++;
X if (bp->b_nmmarks)
X found++;
X if (bp->b_ulinep)
X found++;
X found++; /* for the buffer itself */
X for (i = 0; i < 2; i++) {
X for (lp = bp->b_udstks[i]; lp != NULL;
X lp = lp->l_nxtundo)
X found++;
X }
X }
X }
X found += term.t_mrow+1; /* vscreen and the rows */
#if ! MEMMAP
X found += term.t_mrow+1; /* pscreen and the rows */
#endif
X if (fline)
X found++;
#if ! SMALLER
X { /* user vars */
X extern UVAR uv[MAXVARS];
X for (i=0; i < MAXVARS; i++)
X if (uv[i].u_value) found++;
X }
#endif
#if FILOCK
X need to count lock mallocs...
#endif
X { /* searching */
X register MC *mcptr;
X
X if (patmatch)
X found++;
X
X mcptr = &mcpat[0];
X while (mcptr->mc_type != MCNIL)
X {
X if ((mcptr->mc_type & MASKCL) == CCL ||
X (mcptr->mc_type & MASKCL) == NCCL)
X if (mcptr->u.cclmap) found++;
X mcptr++;
X }
X }
X { /* kill registers */
X for (i = 0; i < NKREGS; i++) {
X KILL *kb;
X if ((kb = kbs[i].kbufh) != NULL) {
X while (kb) {
X found++;
X kb = kb->d_next;
X }
X }
X }
X }
X mlwrite("doverifys %s %d, outstanding mallocs: %d, %d accounted for.",
X f ? "set to":"is still", doverifys, num, found);
X return TRUE;
}
X
#endif
SHAR_EOF
chmod 0444 vmalloc.c ||
echo 'restore of vmalloc.c failed'
Wc_c="`wc -c < 'vmalloc.c'`"
test 6798 -eq "$Wc_c" ||
echo 'vmalloc.c: original size 6798, current size' "$Wc_c"
# ============= vmsvt.c ==============
echo 'x - extracting vmsvt.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'vmsvt.c' &&
/*
X * Advanced VMS terminal driver
X *
X * Knows about any terminal defined in SMGTERMS.TXT and TERMTABLE.TXT
X * located in SYS$SYSTEM.
X *
X * Author: Curtis Smith
X * Last Updated: 07/14/87
X */
X
#include <stdio.h> /* Standard I/O package */
#include "estruct.h" /* Emacs' structures */
#include "edef.h" /* Emacs' definitions */
X
#if VMSVT
X
#include <descrip.h> /* Descriptor definitions */
X
/* These would normally come from iodef.h and ttdef.h */
#define IO$_SENSEMODE 0x27 /* Sense mode of terminal */
#define TT$_UNKNOWN 0x00 /* Unknown terminal */
X
/** Forward references **/
int vmsopen(), ttclose(), vmskopen(), vmskclose(), ttgetc(), ttputc();
int ttflush(), vmsmove(), vmseeol(), vmseeop(), vmsbeep(), vmsrev();
int vmscres();
extern int eolexist, revexist;
extern char sres[];
X
#if COLOR
int vmsfcol(), vmsbcol();
#endif
X
/** SMG stuff **/
static char * begin_reverse, * end_reverse, * erase_to_end_line;
static char * erase_whole_display;
static int termtype;
X
#define SMG$K_BEGIN_REVERSE 0x1bf
#define SMG$K_END_REVERSE 0x1d6
#define SMG$K_SET_CURSOR_ABS 0x23a
#define SMG$K_ERASE_WHOLE_DISPLAY 0x1da
#define SMG$K_ERASE_TO_END_LINE 0x1d9
X
X
/* Dispatch table. All hard fields just point into the terminal I/O code. */
TERM term = {
X 24 - 1, /* Max number of rows allowable */
X /* Filled in */ - 1, /* Current number of rows used */
X 132, /* Max number of columns */
X /* Filled in */ 0, /* Current number of columns */
X 64, /* Min margin for extended lines*/
X 8, /* Size of scroll region */
X 100, /* # times thru update to pause */
X vmsopen, /* Open terminal at the start */
X ttclose, /* Close terminal at end */
X vmskopen, /* Open keyboard */
X vmskclose, /* Close keyboard */
X ttgetc, /* Get character from keyboard */
X ttputc, /* Put character to display */
X ttflush, /* Flush output buffers */
X vmsmove, /* Move cursor, origin 0 */
X vmseeol, /* Erase to end of line */
X vmseeop, /* Erase to end of page */
X vmsbeep, /* Beep */
X vmsrev, /* Set reverse video state */
X vmscres /* Change screen resolution */
#if COLOR
X , vmsfcol, /* Set forground color */
X vmsbcol /* Set background color */
#endif
};
X
/***
X * ttputs - Send a string to ttputc
X *
X * Nothing returned
X ***/
ttputs(string)
char * string; /* String to write */
{
X if (string)
X while (*string != '\0')
X ttputc(*string++);
}
X
X
/***
X * vmsmove - Move the cursor (0 origin)
X *
X * Nothing returned
X ***/
vmsmove(row, col)
int row; /* Row position */
int col; /* Column position */
{
X char buffer[32];
X int ret_length;
X static int request_code = SMG$K_SET_CURSOR_ABS;
X static int max_buffer_length = sizeof(buffer);
X static int arg_list[3] = { 2 };
X register char * cp;
X
X register int i;
X
X /* Set the arguments into the arg_list array
X * SMG assumes the row/column positions are 1 based (boo!)
X */
X arg_list[1] = row + 1;
X arg_list[2] = col + 1;
X
X if ((smg$get_term_data( /* Get terminal data */
X &termtype, /* Terminal table address */
X &request_code, /* Request code */
X &max_buffer_length, /* Maximum buffer length */
X &ret_length, /* Return length */
X buffer, /* Capability data buffer */
X arg_list) /* Argument list array */
X
X /* We'll know soon enough if this doesn't work */
X & 1) == 0) {
X ttputs("OOPS");
X return;
X }
X
X /* Send out resulting sequence */
X i = ret_length;
X cp = buffer;
X while (i-- > 0)
X ttputc(*cp++);
}
X
X
/***
X * vmsrev - Set the reverse video status
X *
X * Nothing returned
X ***/
vmsrev(status)
int status; /* TRUE if setting reverse */
{
X if (status)
X ttputs(begin_reverse);
X else
X ttputs(end_reverse);
}
X
/***
X * vmscres - Change screen resolution (which it doesn't)
X *
X * Nothing returned
X ***/
vmscres()
{
X /* But it could. For vt100/vt200s, one could switch from
X 80 and 132 columns modes */
}
X
X
#if COLOR
/***
X * vmsfcol - Set the forground color (not implimented)
X *
X * Nothing returned
X ***/
vmsfcol()
{
}
X
/***
X * vmsbcol - Set the background color (not implimented)
X *
X * Nothing returned
X ***/
vmsbcol()
{
}
#endif
X
/***
X * vmseeol - Erase to end of line
X *
X * Nothing returned
X ***/
vmseeol()
{
X ttputs(erase_to_end_line);
}
X
X
/***
X * vmseeop - Erase to end of page (clear screen)
X *
X * Nothing returned
X ***/
vmseeop()
{
X ttputs(erase_whole_display);
}
X
X
/***
X * vmsbeep - Ring the bell
X *
X * Nothing returned
X ***/
vmsbeep()
{
X ttputc('\007');
}
X
X
/***
X * vmsgetstr - Get an SMG string capability by name
X *
X * Returns: Escape sequence
X * NULL No escape sequence available
X ***/
char * vmsgetstr(request_code)
int request_code; /* Request code */
{
X register char * result;
X static char seq_storage[1024];
X static char * buffer = seq_storage;
X static int arg_list[2] = { 1, 1 };
X int max_buffer_length, ret_length;
X
X /* Precompute buffer length */
X
X max_buffer_length = (seq_storage + sizeof(seq_storage)) - buffer;
X
X /* Get terminal commands sequence from master table */
X
X if ((smg$get_term_data( /* Get terminal data */
X &termtype, /* Terminal table address */
X &request_code, /* Request code */
X &max_buffer_length,/* Maximum buffer length */
X &ret_length, /* Return length */
X buffer, /* Capability data buffer */
X arg_list) /* Argument list array */
X
X /* If this doesn't work, try again with no arguments */
X
X & 1) == 0 &&
X
X (smg$get_term_data( /* Get terminal data */
X &termtype, /* Terminal table address */
X &request_code, /* Request code */
X &max_buffer_length,/* Maximum buffer length */
X &ret_length, /* Return length */
X buffer) /* Capability data buffer */
X
X /* Return NULL pointer if capability is not available */
X
X & 1) == 0)
X return NULL;
X
X /* Check for empty result */
X if (ret_length == 0)
X return NULL;
X
X /* Save current position so we can return it to caller */
X
X result = buffer;
X
X /* NIL terminate the sequence for return */
X
X buffer[ret_length] = 0;
X
X /* Advance buffer */
X
X buffer += ret_length + 1;
X
X /* Return capability to user */
X return result;
}
X
X
/** I/O information block definitions **/
struct iosb { /* I/O status block */
X short i_cond; /* Condition value */
X short i_xfer; /* Transfer count */
X long i_info; /* Device information */
};
struct termchar { /* Terminal characteristics */
X char t_class; /* Terminal class */
X char t_type; /* Terminal type */
X short t_width; /* Terminal width in characters */
X long t_mandl; /* Terminal's mode and length */
X long t_extend; /* Extended terminal characteristics */
};
static struct termchar tc; /* Terminal characteristics */
X
/***
X * vmsgtty - Get terminal type from system control block
X *
X * Nothing returned
X ***/
vmsgtty()
{
X short fd;
X int status;
X struct iosb iostatus;
X $DESCRIPTOR(devnam, "SYS$INPUT");
X
X /* Assign input to a channel */
X status = sys$assign(&devnam, &fd, 0, 0);
X if ((status & 1) == 0)
X exit (status);
X
X /* Get terminal characteristics */
X status = sys$qiow( /* Queue and wait */
X 0, /* Wait on event flag zero */
X fd, /* Channel to input terminal */
X IO$_SENSEMODE, /* Get current characteristic */
X &iostatus, /* Status after operation */
X 0, 0, /* No AST service */
X &tc, /* Terminal characteristics buf */
X sizeof(tc), /* Size of the buffer */
X 0, 0, 0, 0); /* P3-P6 unused */
X
X /* De-assign the input device */
X if ((sys$dassgn(fd) & 1) == 0)
X exit(status);
X
X /* Jump out if bad status */
X if ((status & 1) == 0)
X exit(status);
X if ((iostatus.i_cond & 1) == 0)
X exit(iostatus.i_cond);
}
X
X
/***
X * vmsopen - Get terminal type and open terminal
X *
X * Nothing returned
X ***/
vmsopen()
{
X /* Get terminal type */
X vmsgtty();
X if (tc.t_type == TT$_UNKNOWN) {
X printf("Terminal type is unknown!\n");
X printf("Try set your terminal type with SET TERMINAL/INQUIRE\n");
X printf("Or get help on SET TERMINAL/DEVICE_TYPE\n");
X exit(3);
X }
X
X /* Access the system terminal definition table for the */
X /* information of the terminal type returned by IO$_SENSEMODE */
X if ((smg$init_term_table_by_type(&tc.t_type, &termtype) & 1) == 0)
X return -1;
X
X /* Set sizes */
X term.t_nrow = ((unsigned int) tc.t_mandl >> 24) - 1;
X term.t_ncol = tc.t_width;
X
X /* Get some capabilities */
X begin_reverse = vmsgetstr(SMG$K_BEGIN_REVERSE);
X end_reverse = vmsgetstr(SMG$K_END_REVERSE);
X revexist = begin_reverse != NULL && end_reverse != NULL;
X erase_to_end_line = vmsgetstr(SMG$K_ERASE_TO_END_LINE);
X eolexist = erase_whole_display != NULL;
X erase_whole_display = vmsgetstr(SMG$K_ERASE_WHOLE_DISPLAY);
X
X /* Set resolution */
X strcpy(sres, "NORMAL");
X
X /* Open terminal I/O drivers */
X ttopen();
}
X
X
/***
X * vmskopen - Open keyboard (not used)
X *
X * Nothing returned
X ***/
vmskopen()
{
}
X
X
/***
X * vmskclose - Close keyboard (not used)
X *
X * Nothing returned
X ***/
vmskclose()
{
}
X
X
/***
X * fnclabel - Label function keys (not used)
X *
X * Nothing returned
X ***/
#if FLABEL
fnclabel(f, n) /* label a function key */
int f,n; /* default flag, numeric argument [unused] */
{
X /* on machines with no function keys...don't bother */
X return(TRUE);
}
#endif
X
X
/***
X * spal - Set palette type (Are you kidding?)
X *
X * Nothing returned
X ***/
spal()
{
}
X
#else
X
/***
X * hellovms - Avoid error because of empty module
X *
X * Nothing returned
X ***/
hellovms()
{
}
X
#endif
SHAR_EOF
chmod 0444 vmsvt.c ||
echo 'restore of vmsvt.c failed'
Wc_c="`wc -c < 'vmsvt.c'`"
test 9271 -eq "$Wc_c" ||
echo 'vmsvt.c: original size 9271, current size' "$Wc_c"
# ============= vt52.c ==============
echo 'x - extracting vt52.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'vt52.c' &&
/*
X * The routines in this file
X * provide support for VT52 style terminals
X * over a serial line. The serial I/O services are
X * provided by routines in "termio.c". It compiles
X * into nothing if not a VT52 style device. The
X * bell on the VT52 is terrible, so the "beep"
X * routine is conditionalized on defining BEL.
X */
#define termdef 1 /* don't define "term" external */
X
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
X
#if VT52
X
#define NROW 24 /* Screen size. */
#define NCOL 80 /* Edit if you want to. */
#define MARGIN 8 /* size of minimim margin and */
#define SCRSIZ 64 /* scroll size for extended lines */
#define NPAUSE 100 /* # times thru update to pause */
#define BIAS 0x20 /* Origin 0 coordinate bias. */
#define ESC 0x1B /* ESC character. */
#define BEL 0x07 /* ascii bell character */
X
extern int ttopen(); /* Forward references. */
extern int ttgetc();
extern int ttputc();
extern int ttflush();
extern int ttclose();
extern int vt52move();
extern int vt52eeol();
extern int vt52eeop();
extern int vt52beep();
extern int vt52open();
extern int vt52rev();
extern int vt52cres();
extern int vt52kopen();
extern int vt52kclose();
X
#if COLOR
extern int vt52fcol();
extern int vt52bcol();
#endif
X
/*
X * Dispatch table. All the
X * hard fields just point into the
X * terminal I/O code.
X */
TERM term = {
X NROW-1,
X NROW-1,
X NCOL,
X NCOL,
X MARGIN,
X SCRSIZ,
X NPAUSE,
X &vt52open,
X &ttclose,
X &vt52kopen,
X &vt52kclose,
X &ttgetc,
X &ttputc,
X &ttflush,
X &vt52move,
X &vt52eeol,
X &vt52eeop,
X &vt52beep,
X &vt52rev,
X &vt52cres
#if COLOR
X , &vt52fcol,
X &vt52bcol
#endif
};
X
vt52move(row, col)
{
X ttputc(ESC);
X ttputc('Y');
X ttputc(row+BIAS);
X ttputc(col+BIAS);
}
X
vt52eeol()
{
X ttputc(ESC);
X ttputc('K');
}
X
vt52eeop()
{
X ttputc(ESC);
X ttputc('J');
}
X
vt52rev(status) /* set the reverse video state */
X
int status; /* TRUE = reverse video, FALSE = normal video */
X
{
X /* can't do this here, so we won't */
}
X
vt52cres() /* change screen resolution - (not here though) */
X
{
X return(TRUE);
}
X
spal() /* change palette string */
X
{
X /* Does nothing here */
}
X
#if COLOR
vt52fcol() /* set the forground color [NOT IMPLIMENTED] */
{
}
X
vt52bcol() /* set the background color [NOT IMPLIMENTED] */
{
}
#endif
X
vt52beep()
{
#ifdef BEL
X ttputc(BEL);
X ttflush();
#endif
}
X
vt52open()
{
#if V7 | BSD
X register char *cp;
X char *getenv();
X
X if ((cp = getenv("TERM")) == NULL) {
X puts("Shell variable TERM not defined!");
X exit(1);
X }
X if (strcmp(cp, "vt52") != 0 && strcmp(cp, "z19") != 0) {
X puts("Terminal type not 'vt52'or 'z19' !");
X exit(1);
X }
#endif
X ttopen();
}
X
vt52kopen()
X
{
}
X
vt52kclose()
X
{
}
X
X
#if FLABEL
fnclabel(f, n) /* label a function key */
X
int f,n; /* default flag, numeric argument [unused] */
X
{
X /* on machines with no function keys...don't bother */
X return(TRUE);
}
#endif
#else
X
vt52hello()
X
{
}
X
#endif
SHAR_EOF
chmod 0444 vt52.c ||
echo 'restore of vt52.c failed'
Wc_c="`wc -c < 'vt52.c'`"
test 3386 -eq "$Wc_c" ||
echo 'vt52.c: original size 3386, current size' "$Wc_c"
# ============= window.c ==============
echo 'x - extracting window.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'window.c' &&
/*
X * Window management. Some of the functions are internal, and some are
X * attached to keys that the user actually types.
X */
X
#include <stdio.h>
#include "estruct.h"
#include "edef.h"
X
#if MEGAMAX & ST520
overlay "window"
#endif
X
/*
X * Reposition dot's line to line "n" of the window. If the argument is
X * positive, it is that line. If it is negative it is that line from the
X * bottom. If it is 0 the window is centered around dot (this is what
X * the standard redisplay code does). Defaults to 0.
X */
reposition(f, n)
{
X if (f == FALSE) /* default to 0 to center screen */
X n = 0;
X curwp->w_force = n;
X curwp->w_flag |= WFFORCE;
X return (TRUE);
}
X
/*
X * Refresh the screen. With no argument, it just does the refresh. With an
X * argument it recenters "." in the current window.
X */
refresh(f, n)
{
#if NeWS /* see if the window has changed size */
X newsrefresh() ;
#endif
X
X if (f == FALSE) {
X sgarbf = TRUE;
X } else {
X curwp->w_force = 0; /* Center dot. */
X curwp->w_flag |= WFFORCE;
X }
X
#if NeWS
X newsreportmodes() ;
#endif
X return (TRUE);
}
X
/*
X * The command make the next window (next => down the screen) the current
X * window. There are no real errors, although the command does nothing if
X * there is only 1 window on the screen.
X *
X * with an argument this command finds the <n>th window from the top
X *
X */
nextwind(f, n)
int f, n; /* default flag and numeric argument */
{
X register WINDOW *wp;
X register int nwindows; /* total number of windows */
X
X if (f) {
X
X /* first count the # of windows */
X wp = wheadp;
X nwindows = 1;
X while (wp->w_wndp != NULL) {
X nwindows++;
X wp = wp->w_wndp;
X }
X
X /* if the argument is negative, it is the nth window
X from the bottom of the screen */
X if (n < 0)
X n = nwindows + n + 1;
X
X /* if an argument, give them that window from the top */
X if (n > 0 && n <= nwindows) {
X wp = wheadp;
X while (--n)
X wp = wp->w_wndp;
X } else {
X mlwrite("Window number out of range");
X return(FALSE);
X }
X } else {
X if ((wp = curwp->w_wndp) == NULL)
X wp = wheadp;
X }
X curwp = wp;
X make_current(curwp->w_bufp);
X upmode();
X return (TRUE);
}
X
poswind(f,n)
{
X register int c;
X register int rows;
X int s;
X
X c = kbd_key();
X if (c == abortc)
X return FALSE;
X
X if (c == '+' || c == '\r' || c == 'H') {
X rows = 1;
X } else if (c == '.' || c == 'M') {
X rows = 0;
X } else if (c == '-' || c == 'L') {
X rows = -1;
X } else {
X TTbeep();
X return FALSE;
X }
X
X if (f == TRUE) {
X s = gotoline(f,n);
X if (s != TRUE)
X return(s);
X }
X return(reposition(TRUE,rows));
}
X
/*
X * This command makes the previous window (previous => up the screen) the
X * current window. There arn't any errors, although the command does not do a
X * lot if there is 1 window.
X */
prevwind(f, n)
{
X register WINDOW *wp1;
X register WINDOW *wp2;
X
X /* if we have an argument, we mean the nth window from the bottom */
X if (f)
X return(nextwind(f, -n));
X
X wp1 = wheadp;
X wp2 = curwp;
X
X if (wp1 == wp2)
X wp2 = NULL;
X
X while (wp1->w_wndp != wp2)
X wp1 = wp1->w_wndp;
X
X curwp = wp1;
X make_current(curwp->w_bufp);
X upmode();
X return (TRUE);
}
X
/*
X * This command moves the current window down by "arg" lines. Recompute the
X * top line in the window. The move up and move down code is almost completely
X * the same; most of the work has to do with reframing the window, and picking
X * a new dot. We share the code by having "move down" just be an interface to
X * "move up". Magic.
X */
mvdnwind(f, n)
int n;
{
X return (mvupwind(f, -n));
}
X
/*
X * Move the current window up by "arg" lines. Recompute the new top line of
X * the window. Look to see if "." is still on the screen. If it is, you win.
X * If it isn't, then move "." to center it in the new framing of the window
X * (this command does not really move "." (except as above); it moves the
X * frame).
X */
mvupwind(f, n)
int n;
{
X register LINE *lp;
X register int i;
X int was_n = n;
X
X lp = curwp->w_linep;
X
X if (n < 0) {
X while (n++ && lforw(lp) != curbp->b_linep)
X lp = lforw(lp);
X } else {
X while (n-- && lback(lp)!=curbp->b_linep)
X lp = lback(lp);
X }
X
X curwp->w_linep = lp;
X curwp->w_flag |= WFHARD|WFMODE;
X
X /* is it still in the window */
X for (i = 0; i < curwp->w_ntrows; ++i) {
X if (lp == curwp->w_dotp)
X return (TRUE);
X if (lforw(lp) == curbp->b_linep)
X break;
X lp = lforw(lp);
X }
X /* now lp is either just past the window bottom, or
X it's the last line of the file */
X
X /* preserve the current column */
X if (curgoal < 0)
X curgoal = getccol(FALSE);
X
X if (was_n < 0)
X curwp->w_dotp = curwp->w_linep;
X else
X curwp->w_dotp = lback(lp);
X curwp->w_doto = getgoal(curwp->w_dotp);
X return (TRUE);
}
X
mvdnnxtwind(f, n)
{
X nextwind(FALSE, 1);
X mvdnwind(f, n);
X prevwind(FALSE, 1);
}
X
mvupnxtwind(f, n)
{
X nextwind(FALSE, 1);
X mvupwind(f, n);
X prevwind(FALSE, 1);
}
X
mvrightwind(f,n)
{
X int move, col;
X
X if (f)
X move = n;
X else
X move = term.t_ncol/3;
X
X if (curwp->w_sideways + move > (col = getccol(FALSE)) - 1) {
X TTbeep();
X return FALSE;
X }
X
X curwp->w_sideways += move;
X
X curwp->w_flag |= WFHARD|WFMOVE;
X
X return TRUE;
}
X
mvleftwind(f,n)
{
X if (f)
X curwp->w_sideways -= n;
X else
X curwp->w_sideways -= term.t_ncol/3;
X
X if (curwp->w_sideways < 0)
X curwp->w_sideways = 0;
X
X curwp->w_flag |= WFHARD|WFMOVE;
X
X return TRUE;
}
X
/*
X * This command makes the current window the only window on the screen.
X * Try to set the framing so that "." does not have to move on the
X * display. Some care has to be taken to keep the values of dot and mark in
X * the buffer structures right if the distruction of a window makes a buffer
X * become undisplayed.
X */
onlywind(f, n)
{
X register WINDOW *wp;
X register LINE *lp;
X register int i;
X
X wp = wheadp;
X while (wp != NULL) {
X register WINDOW *nwp;
X nwp = wp->w_wndp;
X if (wp != curwp) {
X if (--wp->w_bufp->b_nwnd == 0)
X undispbuff(wp->w_bufp,wp);
X free((char *) wp);
X }
X wp = nwp;
X }
X wheadp = curwp;
X wheadp->w_wndp = NULL;
X lp = curwp->w_linep;
X i = curwp->w_toprow;
X while (i!=0 && lback(lp)!=curbp->b_linep) {
X --i;
X lp = lback(lp);
X }
X curwp->w_toprow = 0;
X curwp->w_ntrows = term.t_nrow-1;
X curwp->w_linep = lp;
X curwp->w_flag |= WFMODE|WFHARD;
X return (TRUE);
}
X
/*
X * Delete the current window, placing its space in the window above,
X * or, if it is the top window, the window below.
X */
X
delwind(f,n)
int f, n; /* arguments are ignored for this command */
{
X return delwp(curwp);
}
X
delwp(thewp)
WINDOW *thewp;
{
X register WINDOW *wp; /* window to recieve deleted space */
X register LINE *lp; /* line pointer */
X register int i;
X
X /* if there is only one window, don't delete it */
X if (wheadp->w_wndp == NULL) {
X mlwrite("Cannot delete the only window");
X return(FALSE);
X }
X
X /* find recieving window and give up our space */
X if (thewp == wheadp) { /* there's nothing before */
X /* find the next window down */
X wp = thewp->w_wndp;
X lp = wp->w_linep;
X /* the prev. window (thewp) has wp->w_toprow rows in it */
X for (i = wp->w_toprow;
X i > 0 && lback(lp) != wp->w_bufp->b_linep; --i)
X lp = lback(lp);
X wp->w_linep = lp;
X wp->w_ntrows += wp->w_toprow; /* add in the new rows */
X wp->w_toprow = 0; /* and we're at the top of the screen */
X wheadp = wp; /* and at the top of the list as well */
X } else {
X /* find window before thewp in linked list */
X for (wp = wheadp; wp->w_wndp != thewp; wp = wp->w_wndp)
X ;
X /* add thewp's rows to the next window up */
X wp->w_ntrows += thewp->w_ntrows+1;
X
X wp->w_wndp = thewp->w_wndp; /* make their next window ours */
X }
X
X /* get rid of the current window */
X if (--thewp->w_bufp->b_nwnd == 0)
X undispbuff(thewp->w_bufp,thewp);
X free((char *)thewp);
X if (thewp == curwp) {
X curwp = wp;
X curwp->w_flag |= WFHARD;
X make_current(curwp->w_bufp);
X }
X upmode();
X return(TRUE);
}
X
/*
X Split the current window. A window smaller than 3 lines cannot be
X split. An argument of 1 forces the cursor into the upper window, an
X argument of two forces the cursor to the lower window. The only other
X error that is possible is a "malloc" failure allocating the structure
X for the new window.
X */
splitwind(f, n)
{
X register WINDOW *wp;
X register LINE *lp;
X register int ntru;
X register int ntrl;
X register int ntrd;
X register WINDOW *wp1;
X register WINDOW *wp2;
X register int i;
X
X if (curwp->w_ntrows < 3) {
X mlwrite("Cannot split a %d line window", curwp->w_ntrows);
X return (FALSE);
X }
X if ((wp = (WINDOW *) malloc(sizeof(WINDOW))) == NULL) {
X mlwrite("[OUT OF MEMORY]");
X return (FALSE);
X }
X ++curbp->b_nwnd; /* Displayed twice. */
X wp->w_bufp = curbp;
X wp->w_dotp = curwp->w_dotp;
X wp->w_doto = curwp->w_doto;
X wp->w_mkp = curwp->w_mkp;
X wp->w_mko = curwp->w_mko;
X wp->w_linep = curwp->w_linep;
X wp->w_ldmkp = curwp->w_ldmkp;
X wp->w_ldmko = curwp->w_ldmko;
X wp->w_sideways = curwp->w_sideways;
X wp->w_flag = 0;
X wp->w_force = 0;
#if COLOR
X /* set the colors of the new window */
X wp->w_fcolor = gfcolor;
X wp->w_bcolor = gbcolor;
#endif
X ntru = (curwp->w_ntrows-1) / 2; /* Upper size */
X ntrl = (curwp->w_ntrows-1) - ntru; /* Lower size */
X lp = curwp->w_linep;
X ntrd = 0;
X while (lp != curwp->w_dotp) {
X ++ntrd;
X lp = lforw(lp);
X }
X /* ntrd is now the row containing dot */
X if (((f == FALSE) && (ntrd <= ntru)) || ((f == TRUE) && (n == 1))) {
X /* Old is upper window. */
X /* Adjust the top line if necessary */
X if (ntrd == ntru) /* Hit mode line. */
X if (ntrl > 1) {
X ntru++;
X ntrl--;
X } else
X curwp->w_linep = lforw(curwp->w_linep);
X curwp->w_ntrows = ntru; /* new size */
X /* insert new window after curwp in window list */
X wp->w_wndp = curwp->w_wndp;
X curwp->w_wndp = wp;
X /* set new window's position and size */
X wp->w_toprow = curwp->w_toprow+ntru+1;
X wp->w_ntrows = ntrl;
X /* try to keep lower from reframing */
X for (i = ntru+1; i > 0 &&
X wp->w_linep != wp->w_bufp->b_linep; i--) {
X wp->w_linep = lforw(wp->w_linep);
X }
X wp->w_dotp = wp->w_linep;
X wp->w_doto = 0;
X } else {
X /* Old is lower window */
X wp1 = NULL;
X wp2 = wheadp;
X while (wp2 != curwp) {
X wp1 = wp2;
X wp2 = wp2->w_wndp;
X }
X if (wp1 == NULL)
X wheadp = wp;
X else
X wp1->w_wndp = wp;
X wp->w_wndp = curwp;
X wp->w_toprow = curwp->w_toprow;
X wp->w_ntrows = ntru;
X ++ntru; /* Mode line. */
X curwp->w_toprow += ntru;
X curwp->w_ntrows = ntrl;
X wp->w_dotp = wp->w_linep;
X /* move upper window dot to bottom line of upper */
X for (i = ntru-2; i > 0 && wp->w_dotp!=wp->w_bufp->b_linep; i--)
X wp->w_dotp = lforw(wp->w_dotp);
X wp->w_doto = 0;
X /* adjust lower window topline */
X while (ntru--)
X curwp->w_linep = lforw(curwp->w_linep);
X }
X curwp->w_flag |= WFMODE|WFHARD;
X wp->w_flag |= WFMODE|WFHARD;
X return (TRUE);
}
X
/*
X * Enlarge the current window. Find the window that loses space. Make sure it
X * is big enough. If so, hack the window descriptions, and ask redisplay to do
SHAR_EOF
true || echo 'restore of window.c failed'
echo 'End of Vile part 16'
echo 'File window.c is continued in part 17'
echo 17 > _shar_seq_.tmp
exit 0
--
paul fox, pgf at cayman.com, (617)494-1999
Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139
More information about the Alt.sources
mailing list