pgf@cayman.COM (Paul Fox) (06/08/91)
#!/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@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@cayman.com, (617)494-1999 Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139