home *** CD-ROM | disk | FTP | other *** search
- From: pgf@cayman.COM (Paul Fox)
- Newsgroups: alt.sources
- Subject: Vile 01/17 - vi feel-alike (multi-window)
- Message-ID: <4520@cayman.COM>
- Date: 7 Jun 91 22:09:05 GMT
-
- #!/bin/sh
- # This is Vile, a shell archive (shar 3.47)
- # made 06/07/1991 22:01 UTC by pgf@cayman.com
- # Source directory /tmp_mnt/home/carl/pgf/vile
- #
- # existing files WILL be overwritten
- #
- # This is part 1 of a multipart archive
- # do not concatenate these parts, unpack them in order with /bin/sh
- #
- # This shar contains:
- # length mode name
- # ------ ---------- ------------------------------------------
- # 3835 -r--r--r-- README
- # 6488 -r--r--r-- ansi.c
- # 4175 -r--r--r-- at386.c
- # 20335 -r--r--r-- basic.c
- # 21479 -r--r--r-- bind.c
- # 20200 -r--r--r-- buffer.c
- # 6009 -r--r--r-- buglist
- # 17753 -r--r--r-- cmdtbl
- # 6989 -r--r--r-- crypt.c
- # 2171 -r--r--r-- csrch.c
- # 3333 -r--r--r-- dg10.c
- # 40087 -r--r--r-- display.c
- # 4340 -r--r--r-- dolock.c
- # 14722 -r--r--r-- ebind.h
- # 9852 -r--r--r-- edef.h
- # 27465 -r--r--r-- efunc.h
- # 956 -r--r--r-- epath.h
- # 30449 -r--r--r-- estruct.h
- # 18430 -r--r--r-- eval.c
- # 5247 -r--r--r-- evar.h
- # 32572 -r--r--r-- exec.c
- # 28527 -r--r--r-- file.c
- # 7384 -r--r--r-- fileio.c
- # 3373 -r--r--r-- finderr.c
- # 2834 -r--r--r-- globals.c
- # 3750 -r--r--r-- hp110.c
- # 9245 -r--r--r-- hp150.c
- # 10074 -r--r--r-- ibmpc.c
- # 10225 -r--r--r-- input.c
- # 18075 -r--r--r-- isearch.c
- # 20714 -r--r--r-- line.c
- # 3557 -r--r--r-- lock.c
- # 23507 -r--r--r-- main.c
- # 1438 -r--r--r-- make.ini
- # 9302 -r--r--r-- makefile
- # 7809 -r--r--r-- mktbls.c
- # 5332 -rw-rw-r-- nebind.h
- # 19211 -rw-rw-r-- nefunc.h
- # 17247 -rw-rw-r-- nename.h
- # 5376 -r--r--r-- news.c
- # 19928 -r--r--r-- news.cps
- # 2848 -r--r--r-- npopen.c
- # 4253 -r--r--r-- oneliner.c
- # 4699 -r--r--r-- opers.c
- # 34147 -r--r--r-- random.c
- # 7014 -r--r--r-- readme.news
- # 9127 -r--r--r-- region.c
- # 35047 -r--r--r-- search.c
- # 7910 -r--r--r-- shorten/COPYING
- # 178 -r--r--r-- shorten/defines.c
- # 857 -r--r--r-- shorten/dups.c
- # 674 -r--r--r-- shorten/header.h
- # 1637 -r--r--r-- shorten/names.c
- # 220 -r--r--r-- shorten/reserved
- # 0 -r--r--r-- shorten/special
- # 20300 -r--r--r-- spawn.c
- # 19931 -r--r--r-- st520.c
- # 57909 -r--r--r-- tags
- # 7806 -r--r--r-- tags.c
- # 6065 -r--r--r-- tcap.c
- # 16097 -r--r--r-- termio.c
- # 5308 -r--r--r-- tipc.c
- # 11158 -r--r--r-- undo.c
- # 24385 -r--r--r-- vile.hlp
- # 6798 -r--r--r-- vmalloc.c
- # 9271 -r--r--r-- vmsvt.c
- # 3386 -r--r--r-- vt52.c
- # 20419 -r--r--r-- window.c
- # 10449 -r--r--r-- word.c
- # 6094 -r--r--r-- wordmov.c
- # 652 -r--r--r-- z100bios.asm
- # 7806 -r--r--r-- z309.c
- #
- if test -r _shar_seq_.tmp; then
- echo 'Must unpack archives in sequence!'
- echo Please unpack part `cat _shar_seq_.tmp` next
- exit 1
- fi
- # ============= README ==============
- echo 'x - extracting README (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'README' &&
- X
- X
- X
- VILE -- VI Like Emacs: a vi workalike put together from Micro-Emacs by Paul Fox
- -------------------------------------------------------------------------------
- X
- X This editor grew out of a frustration that although lots of
- X eager programmers have tackled rewrites of Emacs, with new and
- X better features (not to mention free source), I've not seen
- X anything similar done with the Second True Editor. (The
- X First, of course, being /bin/ed)
- X
- X So I took a copy of MicroEmacs 3.9 (which I've since
- X discovered was out of date, unfortunately) and bashed and
- X badgered it into a vi "feel-alike". It retains the multiple
- X buffer/multiple window features of uemacs, but the
- X "finger-feel", if you will, is very much that of vi. It is
- X definitely not a clone, in that some substantial stuff is
- X missing, and the screen doesn't look quite the same. But what
- X matters most is that one's "muscle memory" does the right thing
- X to the text in front of you, and that is what vile tries to do
- X for vi users. THIS IS NOT A "CLONE"!
- X
- X This is the first really public version of vile. It is
- X version three. Users of previous versions will hopefully find
- X the additions of ":" command line ranges and the ! filter
- X operator helpful.
- X
- X The collective developers of Micro-Emacs should be
- X complimented that the changes were as easy as they were. The
- X code was pretty clean and well designed before I started on
- X it. I'm not sure that the same can be said anymore...
- X
- X The benefits over standard vi include:
- X - multiple files open at once
- X - multiple windows on the screen
- X - a larger set of operator commands
- X - the possibility of porting to your favorite micro.
- X (mind you, I haven't even tried this on a small
- X UNIX machine, let alone DOS etc...)
- X - more uniform undo/yank register treatment
- X - using tags doesn't lose your last search pattern
- X - "next error" cursor positioning after compilation
- X Of course, it _may_ lack some of vi's reliability. :-)
- X
- X ( Although I can't imagine the emacs folks wanting to buy much
- X of this stuff back (insert mode, anyone? :-), they might
- X want to look at:
- X - full global undo
- X - tags support
- X - better (maybe?) UNIX terminal handling
- X - better UNIX shell escapes
- X - terminal scroll support
- X - multiple yank registers (formerly called kill buffers)
- X - multiple marks (actually kind of messy)
- X - improved aesthetics of window splitting and deleting
- X - "next error" cursor positioning
- X - list mode )
- X
- X Take a look at vile.hlp for more information about features
- X and differences.
- X
- X In general, I suspect that the quality of the code is roughly
- X on a par with MicroEmacs. I've been using vile regularly under
- X both SunOS and 386 UNIX for about a year, with no major problems
- X (that havn't been fixed). Another dedicated user has been
- X running it on various flavors of 386 UNIX (Bell, Open DeskTop,
- X Xenix) and Ultrix, also with no problems.
- X
- X I have not tried this on a small system, or even _any_
- X non-UNIX system. I'm sure work will be required to make
- X it work on DOS again, for instance -- especially for spawning
- X sub-shells, etc.
- X
- X I ifdef'ed out the language features (user-defined procs,
- X etc.) a long time ago -- I don't know if they still work,
- X though I didn't actively try to break them.
- X
- X If anyone is interested in doing major work on this thing, let me
- X know -- I have some ideas on how to make a full ex mode work, for
- X instance, and on how to add the ":map" command. Also, take a look
- X at the buglist...
- X
- X Hope you enjoy --
- X
- X Paul G. Fox June 3, 1991
- X pgf@cayman.com
- X
- p.s. The code distributed with vile in the "shortnames" subdirectory
- X is covered by GNU Public License. The vile code itself in the
- X upper level directory is _not_ covered by the GNU public license.
- X
- p.p.s By the way, I'm _not_ the same Paul Fox who wrote Crisp, the Brief
- X work-alike.
- SHAR_EOF
- chmod 0444 README ||
- echo 'restore of README failed'
- Wc_c="`wc -c < 'README'`"
- test 3835 -eq "$Wc_c" ||
- echo 'README: original size 3835, current size' "$Wc_c"
- # ============= ansi.c ==============
- echo 'x - extracting ansi.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'ansi.c' &&
- /*
- X * The routines in this file provide support for ANSI style terminals
- X * over a serial line. The serial I/O services are provided by routines in
- X * "termio.c". It compiles into nothing if not an ANSI device.
- X */
- X
- #define termdef 1 /* don't define "term" external */
- X
- #include <stdio.h>
- #include "estruct.h"
- #include "edef.h"
- X
- #if ANSI
- X
- #if AMIGA
- #define NROW 23 /* Screen size. */
- #define NCOL 77 /* Edit if you want to. */
- #else
- #define NROW 24 /* Screen size. */
- #define NCOL 80 /* Edit if you want to. */
- #endif
- #define NPAUSE 100 /* # times thru update to pause */
- #define MARGIN 8 /* size of minimim margin and */
- #define SCRSIZ 64 /* scroll size for extended lines */
- #define BEL 0x07 /* BEL character. */
- #define ESC 0x1B /* ESC character. */
- X
- extern int ttopen(); /* Forward references. */
- extern int ttgetc();
- extern int ttputc();
- extern int ttflush();
- extern int ttclose();
- extern int ansimove();
- extern int ansieeol();
- extern int ansieeop();
- extern int ansibeep();
- extern int ansiopen();
- extern int ansirev();
- extern int ansiclose();
- extern int ansikopen();
- extern int ansikclose();
- extern int ansicres();
- #if SCROLLCODE
- extern int ansiscroll();
- #endif
- X
- #if COLOR
- extern int ansifcol();
- extern int ansibcol();
- X
- int cfcolor = -1; /* current forground color */
- int cbcolor = -1; /* current background color */
- X
- #if AMIGA
- /* apperently the AMIGA does not follow the ANSI standards as
- X regards to colors....maybe because of the default pallette
- X settings?
- */
- X
- int coltran[8] = {2, 3, 5, 7, 0, 4, 6, 1}; /* color translation table */
- #endif
- #endif
- X
- /*
- X * Standard terminal interface dispatch table. Most of the fields point into
- X * "termio" code.
- X */
- TERM term = {
- X NROW-1,
- X NROW-1,
- X NCOL,
- X NCOL,
- X MARGIN,
- X SCRSIZ,
- X NPAUSE,
- X ansiopen,
- X ansiclose,
- X ansikopen,
- X ansikclose,
- X ttgetc,
- X ttputc,
- X ttflush,
- X ansimove,
- X ansieeol,
- X ansieeop,
- X ansibeep,
- X ansirev,
- X ansicres
- #if COLOR
- X , ansifcol,
- X ansibcol
- #endif
- #if SCROLLCODE
- X , ansiscroll
- #endif
- };
- X
- csi()
- {
- X ttputc(ESC);
- X ttputc('[');
- }
- X
- #if COLOR
- ansifcol(color) /* set the current output color */
- X
- int color; /* color to set */
- X
- {
- X if (color == cfcolor)
- X return;
- X csi();
- #if AMIGA
- X ansiparm(coltran[color]+30);
- #else
- X ansiparm(color+30);
- #endif
- X ttputc('m');
- X cfcolor = color;
- }
- X
- ansibcol(color) /* set the current background color */
- X
- int color; /* color to set */
- X
- {
- X if (color == cbcolor)
- X return;
- X csi();
- #if AMIGA
- X ansiparm(coltran[color]+40);
- #else
- X ansiparm(color+40);
- #endif
- X ttputc('m');
- X cbcolor = color;
- }
- #endif
- X
- ansimove(row, col)
- {
- X csi();
- X if (row) ansiparm(row+1);
- X ttputc(';');
- X if (col) ansiparm(col+1);
- X ttputc('H');
- }
- X
- ansieeol()
- {
- X csi();
- X ttputc('K');
- }
- X
- ansieeop()
- {
- #if COLOR
- X ansifcol(gfcolor);
- X ansibcol(gbcolor);
- #endif
- X csi();
- X ttputc('J');
- }
- X
- X
- ansirev(state) /* change reverse video state */
- X
- int state; /* TRUE = reverse, FALSE = normal */
- X
- {
- #if COLOR
- X int ftmp, btmp; /* temporaries for colors */
- #else
- X static int revstate = -1;
- X if (state == revstate)
- X return;
- X revstate = state;
- #endif
- X
- X csi();
- X if (state) ttputc('7');
- X ttputc('m');
- #if COLOR
- X if (state == FALSE) {
- X ftmp = cfcolor;
- X btmp = cbcolor;
- X cfcolor = -1;
- X cbcolor = -1;
- X ansifcol(ftmp);
- X ansibcol(btmp);
- X }
- #endif
- }
- X
- ansicres() /* change screen resolution */
- {
- X return(TRUE);
- }
- X
- spal(dummy) /* change pallette settings */
- {
- X /* none for now */
- }
- X
- ansibeep()
- {
- X ttputc(BEL);
- X ttflush();
- }
- X
- #if SCROLLCODE
- X
- /* if your ansi terminal can scroll regions, like the vt100, then define
- X SCROLL_REG. If not, you can use delete/insert line code, which
- X is prettier but slower if you do it a line at a time instead of
- X all at once.
- */
- X
- #define SCROLL_REG 1
- X
- /* move howmany lines starting at from to to */
- ansiscroll(from,to,howmany)
- {
- X int i;
- X if (to == from) return;
- #if SCROLL_REG
- X if (to < from) {
- X ansiscrollregion(to, from + howmany - 1);
- X ansimove(from + howmany - 1,0);
- X for (i = from - to; i > 0; i--)
- X ttputc('\n');
- X } else { /* from < to */
- X ansiscrollregion(from, to + howmany - 1);
- X ansimove(from);
- X for (i = to - from; i > 0; i--) {
- X ttputc(ESC);
- X ttputc('M');
- X }
- X }
- X ansiscrollregion(0, term.t_mrow);
- X
- #else /* use insert and delete line */
- #if PRETTIER_SCROLL
- X if (abs(from-to) > 1) {
- X ansiscroll(from, (from<to) ? to-1:to+1, howmany);
- X if (from < to)
- X from = to-1;
- X else
- X from = to+1;
- X }
- #endif
- X if (to < from) {
- X ansimove(to,0);
- X csi();
- X if (from - to > 1) ansiparm(from - to);
- X ttputc('M'); /* delete */
- X ansimove(to+howmany,0);
- X csi();
- X if (from - to > 1) ansiparm(from - to);
- X ttputc('L'); /* insert */
- X } else {
- X ansimove(from+howmany,0);
- X csi();
- X if (to - from > 1) ansiparm(to - from);
- X ttputc('M'); /* delete */
- X ansimove(from,0);
- X csi();
- X if (to - from > 1) ansiparm(to - from);
- X ttputc('L'); /* insert */
- X }
- #endif
- }
- X
- #if SCROLL_REG
- ansiscrollregion(top,bot)
- {
- X csi();
- X if (top) ansiparm(top + 1);
- X ttputc(';');
- X if (bot != term.t_nrow) ansiparm(bot + 1);
- X ttputc('r');
- }
- #endif
- X
- #endif
- X
- ansiparm(n)
- register int n;
- {
- X register int q,r;
- X
- X q = n/10;
- X if (q != 0) {
- X r = q/10;
- X if (r != 0) {
- X ttputc((r%10)+'0');
- X }
- X ttputc((q%10) + '0');
- X }
- X ttputc((n%10) + '0');
- }
- X
- ansiopen()
- {
- #if V7 | USG | BSD
- #if 0
- 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, "vt100") != 0 && strcmp(cp, "ansi") != 0) {
- X puts("Terminal type not 'vt100' or 'ansi'!");
- X exit(1);
- X }
- #endif
- #endif
- X strcpy(sres, "NORMAL");
- X revexist = TRUE;
- X ttopen();
- }
- X
- ansiclose()
- {
- #if COLOR
- X ansifcol(7);
- X ansibcol(0);
- #endif
- X ttclose();
- }
- X
- ansikopen() /* open the keyboard (a noop here) */
- {
- }
- X
- ansikclose() /* close the keyboard (a noop here) */
- {
- }
- 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
- #else
- ansihello()
- {
- }
- #endif
- SHAR_EOF
- chmod 0444 ansi.c ||
- echo 'restore of ansi.c failed'
- Wc_c="`wc -c < 'ansi.c'`"
- test 6488 -eq "$Wc_c" ||
- echo 'ansi.c: original size 6488, current size' "$Wc_c"
- # ============= at386.c ==============
- echo 'x - extracting at386.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'at386.c' &&
- /* AT386: hacked tcap.c for the 386 console, when you don't
- X have libtermcap. grrr.
- */
- X
- #define termdef 1 /* don't define "term" external */
- X
- #include <stdio.h>
- #include "estruct.h"
- #include "edef.h"
- X
- #if AT386
- X
- #define NROW 25 /* Screen size. */
- #define NCOL 80 /* Edit if you want to. */
- #define MARGIN 8
- #define SCRSIZ 64
- #define NPAUSE 10 /* # times thru update to pause */
- #define BEL 0x07
- #define ESC 0x1B
- X
- extern int ttopen();
- extern int ttgetc();
- extern int ttputc();
- extern int tgetnum();
- extern int ttflush();
- extern int ttclose();
- extern int at386kopen();
- extern int at386kclose();
- extern int at386move();
- extern int at386eeol();
- extern int at386eeop();
- extern int at386beep();
- extern int at386rev();
- extern int at386cres();
- extern int at386open();
- extern int tput();
- extern char *tgoto();
- #if COLOR
- extern int at386fcol();
- extern int at386bcol();
- #endif
- #if SCROLLCODE
- extern int at386scroll_delins();
- #endif
- X
- #define TCAPSLEN 315
- char at386buf[TCAPSLEN];
- char *UP, PC, *CM, *CE, *CL, *SO, *SE;
- X
- #if SCROLLCODE
- char *DL, *AL, *SF, *SR;
- #endif
- X
- TERM term = {
- X NROW-1,
- X NROW-1,
- X NCOL,
- X NCOL,
- X MARGIN,
- X SCRSIZ,
- X NPAUSE,
- X at386open,
- X ttclose,
- X at386kopen,
- X at386kclose,
- X ttgetc,
- X ttputc,
- X ttflush,
- X at386move,
- X at386eeol,
- X at386eeop,
- X at386beep,
- X at386rev,
- X at386cres
- #if COLOR
- X , at386fcol,
- X at386bcol
- #endif
- #if SCROLLCODE
- X , NULL /* set dynamically at open time */
- #endif
- };
- X
- at386open()
- {
- X char *getenv();
- X char *t, *p, *tgetstr();
- X char tcbuf[1024];
- X char *tv_stype;
- X char err_str[72];
- X
- X CL = "\033[2J\033[H";
- X CE = "\033[K";
- X UP = "\033[A";
- X SE = "\033[m";
- X SO = "\033[7m";
- X revexist = TRUE;
- X
- X
- #if SCROLLCODE
- X DL = "\033[1M";
- X AL = "\033[1L";
- X term.t_scroll = at386scroll_delins;
- #endif
- X ttopen();
- }
- X
- at386kopen()
- {
- X strcpy(sres, "NORMAL");
- }
- X
- at386kclose()
- {
- }
- X
- csi()
- {
- X ttputc(ESC);
- X ttputc('[');
- }
- X
- ansiparm(n)
- register int n;
- {
- X register int q,r;
- X
- X q = n/10;
- X if (q != 0) {
- X r = q/10;
- X if (r != 0) {
- X ttputc((r%10)+'0');
- X }
- X ttputc((q%10) + '0');
- X }
- X ttputc((n%10) + '0');
- }
- X
- at386move(row, col)
- register int row, col;
- {
- X csi();
- X if (row) ansiparm(row+1);
- X ttputc(';');
- X if (col) ansiparm(col+1);
- X ttputc('H');
- }
- X
- at386eeol()
- {
- X fputs(CE,stdout);
- }
- X
- at386eeop()
- {
- X fputs(CL,stdout);
- }
- X
- at386rev(state) /* change reverse video status */
- int state; /* FALSE = normal video, TRUE = reverse video */
- {
- X static int revstate = -1;
- X if (state == revstate)
- X return;
- X revstate = state;
- X if (state) {
- X if (SO != NULL)
- X fputs(SO,stdout);
- X } else {
- X if (SE != NULL)
- X fputs(SE,stdout);
- X }
- }
- X
- at386cres() /* change screen resolution */
- {
- X return(TRUE);
- }
- X
- #if SCROLLCODE
- X
- /*
- PRETTIER_SCROLL is prettier but slower -- it scrolls
- X a line at a time instead of all at once.
- */
- X
- /* move howmany lines starting at from to to */
- at386scroll_delins(from,to,howmany)
- {
- X int i;
- X if (to == from) return;
- #if PRETTIER_SCROLL
- X if (abs(from-to) > 1) {
- X at386scroll_delins(from, (from<to) ? to-1:to+1, howmany);
- X if (from < to)
- X from = to-1;
- X else
- X from = to+1;
- X }
- #endif
- X if (to < from) {
- X at386move(to,0);
- X for (i = from - to; i > 0; i--)
- X fputs(DL,stdout);
- X at386move(to+howmany,0);
- X for (i = from - to; i > 0; i--)
- X fputs(AL,stdout);
- X } else {
- X at386move(from+howmany,0);
- X for (i = to - from; i > 0; i--)
- X fputs(DL,stdout);
- X at386move(from,0);
- X for (i = to - from; i > 0; i--)
- X fputs(AL,stdout);
- X }
- }
- X
- #endif
- X
- spal(dummy) /* change palette string */
- {
- X /* Does nothing here */
- }
- X
- X
- #if COLOR
- at386fcol() /* no colors here, ignore this */
- {
- }
- X
- at386bcol() /* no colors here, ignore this */
- {
- }
- #endif
- X
- at386beep()
- {
- X ttputc(BEL);
- }
- X
- 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
- #else
- X
- hello()
- {
- }
- X
- #endif
- SHAR_EOF
- chmod 0444 at386.c ||
- echo 'restore of at386.c failed'
- Wc_c="`wc -c < 'at386.c'`"
- test 4175 -eq "$Wc_c" ||
- echo 'at386.c: original size 4175, current size' "$Wc_c"
- # ============= basic.c ==============
- echo 'x - extracting basic.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'basic.c' &&
- /*
- X * The routines in this file move the cursor around on the screen. They
- X * compute a new value for the cursor, then adjust ".". The display code
- X * always updates the cursor location, so only moves between lines, or
- X * functions that adjust the top line in the window and invalidate the
- X * framing, are hard.
- X */
- #include <stdio.h>
- #include "estruct.h"
- #include "edef.h"
- X
- /*
- X * Move the cursor to the
- X * beginning of the current line.
- X * Trivial.
- X */
- gotobol(f, n)
- {
- X curwp->w_doto = 0;
- X return (TRUE);
- }
- X
- /*
- X * Move the cursor backwards by "n" characters. If "n" is less than zero call
- X * "forwchar" to actually do the move. Otherwise compute the new cursor
- X * location. Error if you try and move out of the buffer. Set the flag if the
- X * line pointer for dot changes.
- X */
- backchar(f, n)
- register int n;
- {
- X register LINE *lp;
- X
- X if (f == FALSE) n = 1;
- X if (n < 0)
- X return (forwchar(f, -n));
- X while (n--) {
- X if (curwp->w_doto == 0) {
- X if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
- X return (FALSE);
- X curwp->w_dotp = lp;
- X curwp->w_doto = llength(lp);
- X curwp->w_flag |= WFMOVE;
- X } else
- X curwp->w_doto--;
- X }
- X return (TRUE);
- }
- X
- /*
- X * Move the cursor to the end of the current line. Trivial. No errors.
- X */
- gotoeol(f, n)
- {
- X if (f == TRUE) {
- X if (n > 0)
- X --n;
- X else if (n < 0)
- X ++n;
- X forwline(f,n);
- X }
- X curwp->w_doto = llength(curwp->w_dotp);
- X curgoal = HUGE;
- X return (TRUE);
- }
- X
- /*
- X * Move the cursor forwards by "n" characters. If "n" is less than zero call
- X * "backchar" to actually do the move. Otherwise compute the new cursor
- X * location, and move ".". Error if you try and move off the end of the
- X * buffer. Set the flag if the line pointer for dot changes.
- X */
- forwchar(f, n)
- register int n;
- {
- X if (f == FALSE) n = 1;
- X if (n < 0)
- X return (backchar(f, -n));
- X while (n--) {
- X if (curwp->w_doto == llength(curwp->w_dotp)) {
- X if (curwp->w_dotp == curbp->b_linep ||
- X lforw(curwp->w_dotp) == curbp->b_linep)
- X return (FALSE);
- X curwp->w_dotp = lforw(curwp->w_dotp);
- X curwp->w_doto = 0;
- X curwp->w_flag |= WFMOVE;
- X } else
- X curwp->w_doto++;
- X }
- X return (TRUE);
- }
- X
- gotoline(f, n) /* move to a particular line.
- X argument (n) must be a positive integer for
- X this to actually do anything */
- {
- X register int status; /* status return */
- X
- X /* get an argument if one doesnt exist */
- X if (f == FALSE) {
- X return(gotoeob(f,n));
- X }
- X
- X if (n < 1) /* if a bogus argument...then leave */
- X return(FALSE);
- X
- X /* first, we go to the start of the buffer */
- X curwp->w_dotp = lforw(curbp->b_linep);
- X curwp->w_doto = 0;
- X status = forwline(f, n-1);
- X if (status == TRUE)
- X firstnonwhite(f,n);
- X return(status);
- }
- X
- /*
- X * Goto the beginning of the buffer. Massive adjustment of dot. This is
- X * considered to be hard motion; it really isn't if the original value of dot
- X * is the same as the new value of dot.
- X */
- gotobob(f, n)
- {
- X curwp->w_dotp = lforw(curbp->b_linep);
- X curwp->w_doto = 0;
- X curwp->w_flag |= WFMOVE;
- X return (TRUE);
- }
- X
- /*
- X * Move to the end of the buffer. Dot is always put at the end of the file
- X * (ZJ). The standard screen code does most of the hard parts of update.
- X */
- gotoeob(f, n)
- {
- X curwp->w_dotp = lback(curbp->b_linep);
- X firstnonwhite(FALSE,1);
- X curwp->w_flag |= WFMOVE;
- X return (TRUE);
- }
- X
- gotobos(f,n)
- {
- X int s = TRUE;
- X if (f == FALSE || n <= 0) n = 1;
- X curwp->w_dotp = curwp->w_linep;
- X while (--n) {
- X if ((s = forwline(FALSE,1)) != TRUE)
- X break;
- X }
- X firstnonwhite(f,n);
- X return (s);
- }
- X
- gotomos(f,n)
- {
- X return gotobos(TRUE,curwp->w_ntrows/2);
- }
- X
- gotoeos(f,n)
- {
- X return gotobos(TRUE,curwp->w_ntrows-(f==TRUE? n-1:0));
- }
- X
- /*
- X * Move forward by full lines. If the number of lines to move is less than
- X * zero, call the backward line function to actually do it. The last command
- X * controls how the goal column is set. No errors are
- X * possible.
- X */
- forwline(f, n)
- {
- X register LINE *dlp;
- X
- X if (f == FALSE) n = 1;
- X if (n < 0)
- X return (backline(f, -n));
- X
- X /* if we are on the last line as we start....fail the command */
- X if (curwp->w_dotp == curbp->b_linep)
- X return(FALSE);
- X
- X /* if the last command was not a line move,
- X reset the goal column */
- X if (curgoal < 0)
- X curgoal = getccol(FALSE);
- X
- X /* and move the point down */
- X dlp = curwp->w_dotp;
- X while (n-- && dlp!=curbp->b_linep)
- X dlp = lforw(dlp);
- X
- X /* resetting the current position */
- X curwp->w_dotp = (dlp == curbp->b_linep) ? lback(dlp) : dlp;
- X curwp->w_doto = getgoal(dlp);
- X curwp->w_flag |= WFMOVE;
- X return (TRUE);
- }
- X
- firstnonwhite(f,n)
- {
- X int c;
- X curwp->w_doto = 0;
- X while ( curwp->w_doto != llength(curwp->w_dotp) &&
- X isspace(lgetc(curwp->w_dotp, curwp->w_doto)) )
- X curwp->w_doto++;
- X return (TRUE);
- }
- X
- lastnonwhite(f,n)
- {
- X int c;
- X curwp->w_doto = llength(curwp->w_dotp)-1;
- X while ( curwp->w_doto != 0 &&
- X ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t'))
- X curwp->w_doto--;
- X return (TRUE);
- X
- }
- X
- /* like forwline, but got to first non-white char position */
- forwbline(f,n)
- {
- X int s;
- X
- X if (f == FALSE) n = 1;
- X if ((s = forwline(f,n)) != TRUE)
- X return (s);
- X firstnonwhite(f,n);
- X return(TRUE);
- }
- X
- /* like backline, but got to first non-white char position */
- backbline(f,n)
- {
- X int s;
- X
- X if (f == FALSE) n = 1;
- X if ((s = backline(f,n)) != TRUE)
- X return (s);
- X firstnonwhite(f,n);
- X return(TRUE);
- }
- X
- /*
- X * This function is like "forwline", but goes backwards. The scheme is exactly
- X * the same. Check for arguments that are less than zero and call your
- X * alternate. Figure out the new line and call "movedot" to perform the
- X * motion. No errors are possible.
- X */
- backline(f, n)
- {
- X register LINE *dlp;
- X
- X if (f == FALSE) n = 1;
- X if (n < 0)
- X return (forwline(f, -n));
- X
- X
- X /* if we are on the last line as we start....fail the command */
- X if (lback(curwp->w_dotp) == curbp->b_linep)
- X return(FALSE);
- X
- X /* if the last command was not note a line move,
- X reset the goal column */
- X if (curgoal < 0)
- X curgoal = getccol(FALSE);
- X
- X /* and move the point up */
- X dlp = curwp->w_dotp;
- X while (n-- && lback(dlp)!=curbp->b_linep)
- X dlp = lback(dlp);
- X
- X /* reseting the current position */
- X curwp->w_dotp = dlp;
- X curwp->w_doto = getgoal(dlp);
- X curwp->w_flag |= WFMOVE;
- X return (TRUE);
- }
- X
- #if WORDPRO
- X
- gotobop(f,n)
- {
- X return(backlinebeg(f,n,"\n.","ILPQb"));
- }
- gotoeop(f,n)
- {
- X return(forwlinebeg(f,n,"\n.","ILPQb"));
- }
- gotobosec(f,n)
- {
- #if STUTTER_SEC_CMD
- X int this1key;
- X if (!clexec) {
- X this1key = last1key;
- X kbd_seq();
- X if (this1key != last1key) {
- X TTbeep();
- X return(FALSE);
- X }
- X }
- #endif
- X return(backlinebeg(f,n,"{\f.","SHN"));
- }
- gotoeosec(f,n)
- {
- #if STUTTER_SEC_CMD
- X int this1key;
- X if (!clexec) {
- X this1key = last1key;
- X kbd_seq();
- X if (this1key != last1key) {
- X TTbeep();
- X return(FALSE);
- X }
- X }
- #endif
- X return(forwlinebeg(f,n,"{\f.","SHN"));
- }
- X
- backlinebeg(f, n, s1, s2)
- char *s1, *s2;
- {
- X register int suc; /* success of last backchar */
- X LINE *odotp;
- X
- X if (f == FALSE) n = 1;
- X if (n < 0) /* the other way...*/
- X return(gotoeop(f, -n));
- X
- X odotp = curwp->w_dotp;
- X while (n-- > 0) { /* for each one asked for */
- X
- X /* first scan back until we are in a word */
- X suc = backchar(FALSE, 1);
- X while (!inword() && suc)
- X suc = backchar(FALSE, 1);
- X
- X while (lback(curwp->w_dotp) != curbp->b_linep) {
- X if (issecbeg(s1,s2) == TRUE)
- X break;
- X curwp->w_dotp = lback(curwp->w_dotp);
- X }
- X }
- X /* if doing an operation and we moved */
- X if (doingopcmd && odotp != curwp->w_dotp) {
- X curwp->w_dotp = lforw(curwp->w_dotp);
- X curwp->w_doto = 0;
- X } else {
- X firstnonwhite(f,n);
- X }
- X curwp->w_flag |= WFMOVE; /* force screen update */
- X return(TRUE);
- }
- X
- forwlinebeg(f, n, s1, s2)
- char *s1, *s2;
- {
- X register int suc; /* success of last backchar */
- X LINE *odotp;
- X
- X if (f == FALSE) n = 1;
- X if (n < 0) /* the other way...*/
- X return(gotobop(f, -n));
- X
- X odotp = curwp->w_dotp;
- X while (n-- > 0) { /* for each one asked for */
- X
- X /* first scan forward until we are in a word */
- X suc = forwchar(FALSE, 1);
- X while (!inword() && suc)
- X suc = forwchar(FALSE, 1);
- X curwp->w_doto = 0; /* and go to the B-O-Line */
- X if (suc) /* of next line if not at EOF */
- X curwp->w_dotp = lforw(curwp->w_dotp);
- X
- X while (curwp->w_dotp != curbp->b_linep) {
- X if (issecbeg(s1,s2) == TRUE)
- X break;
- X curwp->w_dotp = lforw(curwp->w_dotp);
- X }
- X }
- X /* if doing an operation and we moved */
- X if (doingopcmd && odotp != curwp->w_dotp) {
- X curwp->w_dotp = lback(curwp->w_dotp);
- X curwp->w_doto = llength(curwp->w_dotp)-1;
- X } else {
- X firstnonwhite(f,n);
- X }
- X curwp->w_flag |= WFMOVE; /* force screen update */
- X return(TRUE);
- }
- X
- /* a new "section" of some sort starts at the beginning of the line,
- X with either a character from s1 or a "." followed by a character
- X from s2 */
- issecbeg(s1,s2)
- char *s1,*s2;
- {
- X register char *cp1, *cp2;
- X register int l, c1, c2;
- X
- X l = llength(curwp->w_dotp);
- X for(cp1 = s1; *cp1 != 0; cp1++) {
- X if ( l == 0) {
- X if (*cp1 == '\n')
- X return TRUE;
- X else
- X continue;
- X }
- X c1 = lgetc(curwp->w_dotp, 0);
- X if (c1 == '.' && *cp1 == '.' && s2) {
- X for(cp2 = s2; *cp2 != 0; cp2++) {
- X if ( l <= 1) {
- X if (*cp2 == '\n')
- X return TRUE;
- X else
- X continue;
- X }
- X c2 = lgetc(curwp->w_dotp, 1);
- X if ( *cp2 == c2 )
- X return TRUE;
- X }
- X
- X } else if ( *cp1 == c1 ) {
- X return TRUE;
- X }
- X }
- X return FALSE;
- }
- #endif
- X
- /*
- X * This routine, given a pointer to a LINE, and the current cursor goal
- X * column, return the best choice for the offset. The offset is returned.
- X * Used by "C-N" and "C-P".
- X */
- getgoal(dlp)
- register LINE *dlp;
- {
- X register int c;
- X register int col;
- X register int newcol;
- X register int dbo;
- X
- X col = 0;
- X dbo = 0;
- X while (dbo != llength(dlp)) {
- X c = lgetc(dlp, dbo);
- X newcol = col;
- X if (((curwp->w_bufp->b_mode&MDLIST) == 0) && c == '\t')
- X newcol |= TABMASK;
- X else if (!isprint(c))
- X ++newcol;
- X ++newcol;
- X if (newcol > curgoal)
- X break;
- X col = newcol;
- X ++dbo;
- X }
- X return (dbo);
- }
- X
- /*
- X * Scroll forward by a specified number of lines, or by a full page if no
- X * argument. The "2" in the arithmetic on the window size is
- X * the overlap; this value is the default overlap value in ITS EMACS. Because
- X * this zaps the top line in the display window, we have to do a hard update.
- X */
- forwpage(f, n)
- register int n;
- {
- X register LINE *lp;
- X
- X if (f == FALSE) {
- X n = curwp->w_ntrows - 2; /* Default scroll. */
- X if (n <= 0) /* Forget the overlap */
- X n = 1; /* if tiny window. */
- X } else if (n < 0)
- X return (backpage(f, -n));
- #if CVMVAS
- X else /* Convert from pages */
- X n *= curwp->w_ntrows; /* to lines. */
- #endif
- X lp = curwp->w_linep;
- X while (n-- && lp!=curbp->b_linep)
- X lp = lforw(lp);
- X curwp->w_linep = lp;
- X curwp->w_dotp = lp;
- X curwp->w_doto = 0;
- X curwp->w_flag |= WFHARD;
- X return (TRUE);
- }
- X
- /*
- X * This command is like "forwpage", but it goes backwards. The "2", like
- X * above, is the overlap between the two windows. The value is from the ITS
- X * EMACS manual. We do a hard update for exactly the same
- X * reason.
- X */
- backpage(f, n)
- register int n;
- {
- X register LINE *lp;
- X
- X if (f == FALSE) {
- X n = curwp->w_ntrows - 2; /* Default scroll. */
- X if (n <= 0) /* Don't blow up if the */
- X n = 1; /* window is tiny. */
- X } else if (n < 0)
- X return (forwpage(f, -n));
- #if CVMVAS
- X else /* Convert from pages */
- X n *= curwp->w_ntrows; /* to lines. */
- #endif
- X lp = curwp->w_linep;
- X while (n-- && lback(lp)!=curbp->b_linep)
- X lp = lback(lp);
- X curwp->w_linep = lp;
- X curwp->w_dotp = lp;
- X curwp->w_doto = 0;
- X curwp->w_flag |= WFHARD;
- X return (TRUE);
- }
- X
- /*
- X * Scroll forward by a specified number of lines, or by a full page if no
- X * argument. The "2" in the arithmetic on the window size is
- X * the overlap; this value is the default overlap value in ITS EMACS. Because
- X * this zaps the top line in the display window, we have to do a hard update.
- X */
- forwhpage(f, n)
- register int n;
- {
- X register LINE *llp, *dlp;
- X
- X if (f == FALSE) {
- X n = curwp->w_ntrows / 2; /* Default scroll. */
- X if (n <= 0) /* Forget the overlap */
- X n = 1; /* if tiny window. */
- X } else if (n < 0)
- X return (backhpage(f, -n));
- #if CVMVAS
- X else /* Convert from pages */
- X n *= curwp->w_ntrows/2; /* to lines. */
- #endif
- X llp = curwp->w_linep;
- X dlp = curwp->w_dotp;
- X while (n-- && lforw(dlp) != curbp->b_linep) {
- X llp = lforw(llp);
- X dlp = lforw(dlp);
- X }
- X curwp->w_linep = llp;
- X curwp->w_dotp = dlp;
- X firstnonwhite(f,n);
- X curwp->w_flag |= WFHARD|WFKILLS;
- X return (TRUE);
- }
- X
- /*
- X * This command is like "forwpage", but it goes backwards. The "2", like
- X * above, is the overlap between the two windows. The value is from the ITS
- X * EMACS manual. We do a hard update for exactly the same
- X * reason.
- X */
- backhpage(f, n)
- register int n;
- {
- X register LINE *llp, *dlp;
- X
- X if (f == FALSE) {
- X n = curwp->w_ntrows / 2; /* Default scroll. */
- X if (n <= 0) /* Don't blow up if the */
- X n = 1; /* window is tiny. */
- X } else if (n < 0)
- X return (forwhpage(f, -n));
- #if CVMVAS
- X else /* Convert from pages */
- X n *= curwp->w_ntrows/2; /* to lines. */
- #endif
- X llp = curwp->w_linep;
- X dlp = curwp->w_dotp;
- X while (n-- && lback(dlp)!=curbp->b_linep) {
- X llp = lback(llp);
- X dlp = lback(dlp);
- X }
- X curwp->w_linep = llp;
- X curwp->w_dotp = dlp;
- X firstnonwhite(f,n);
- X curwp->w_flag |= WFHARD|WFINS;
- X return (TRUE);
- }
- X
- X
- X
- /*
- X * Set the named mark in the current window to the value of "." in the window.
- X * No errors are possible.
- X */
- setnmmark(f,n)
- {
- X char *s;
- X int c,i;
- X
- X if (clexec || isnamedcmd) {
- X int stat;
- X static char cbuf[2];
- X if ((stat=mlreply("Set mark: ", cbuf, 2)) != TRUE)
- X return stat;
- X c = cbuf[0];
- X } else {
- X c = kbd_key();
- X }
- X if (c < 'a' || c > 'z') {
- X TTbeep();
- X mlwrite("[Invalid mark name]");
- X return FALSE;
- X }
- X
- X if (curbp->b_nmmarks == NULL) {
- X curbp->b_nmmarks =
- X (struct MARK *)malloc(26*sizeof(struct MARK));
- X if (curbp->b_nmmarks == NULL) {
- X mlwrite("[OUT OF MEMORY]");
- X return FALSE;
- X }
- X for (i = 0; i < 26; i++) {
- X curbp->b_nmmarks[i].markp = NULL;
- X curbp->b_nmmarks[i].marko = 0;
- X }
- X }
- X
- X curbp->b_nmmarks[c-'a'].markp = curwp->w_dotp;
- X curbp->b_nmmarks[c-'a'].marko = curwp->w_doto;
- X s = "[Mark X set]";
- X s[6] = c;
- X mlwrite(s);
- X return TRUE;
- }
- X
- golinenmmark(f,n)
- {
- X int status;
- X status = goexactnmmark(f,n);
- X if (status != TRUE)
- X return(status);
- X firstnonwhite(f,n);
- X return(TRUE);
- }
- X
- goexactnmmark(f,n)
- {
- X int c;
- X int this1key;
- X int useldmark;
- X
- X this1key = last1key;
- X c = kbd_seq();
- X useldmark = (last1key == this1key); /* '' or `` */
- X c = kcod2key(c);
- X
- X if (useldmark)
- X c = '\'';
- X
- X return gonmmark(c);
- }
- X
- gonmmark(c)
- {
- X register LINE **markpp;
- X register int *markop;
- X LINE *tmarkp;
- X int tmarko;
- X int found;
- X
- X if (!islower(c) && c != '\'') {
- X TTbeep();
- X mlwrite("[Invalid mark name]");
- X return FALSE;
- X }
- X
- X markpp = NULL;
- X
- X if (c == '\'') { /* use the 'last dot' mark */
- X markpp = &(curwp->w_ldmkp);
- X markop = &(curwp->w_ldmko);
- X } else if (curbp->b_nmmarks != NULL) {
- X markpp = &(curbp->b_nmmarks[c-'a'].markp);
- X markop = &(curbp->b_nmmarks[c-'a'].marko);
- X }
- X
- X found = FALSE;
- X if (markpp != NULL && *markpp != NULL) {
- X register LINE *lp;
- X for (lp = lforw(curbp->b_linep);
- X lp != curbp->b_linep; lp = lforw(lp)) {
- X if (*markpp == lp) {
- X found = TRUE;
- X break;
- X }
- X }
- X }
- X if (!found) {
- X TTbeep();
- X mlwrite("[Mark not set]");
- X return (FALSE);
- X }
- X
- X /* save current dot */
- X tmarkp = curwp->w_dotp;
- X tmarko = curwp->w_doto;
- X
- X /* move to the selected mark */
- X curwp->w_dotp = *markpp;
- X curwp->w_doto = *markop;
- X
- X /* reset last-dot-mark to old dot */
- X curwp->w_ldmkp = tmarkp;
- X curwp->w_ldmko = tmarko;
- X
- X curwp->w_flag |= WFMOVE;
- X return (TRUE);
- }
- X
- /*
- X * Set the mark in the current window to the value of "." in the window. No
- X * errors are possible.
- X */
- setmark()
- {
- X curwp->w_mkp = curwp->w_dotp;
- X curwp->w_mko = curwp->w_doto;
- X return (TRUE);
- }
- X
- gomark(f,n)
- {
- X curwp->w_dotp = curwp->w_mkp;
- X curwp->w_doto = curwp->w_mko;
- X curwp->w_flag |= WFMOVE;
- X return (TRUE);
- }
- X
- /* this odd routine puts us at the internal mark, plus an offset of lines */
- /* n == 1 leaves us at mark, n == 2 one line down, etc. */
- /* this is for the use of stuttered commands, and line oriented regions */
- godotplus(f,n)
- {
- X int s;
- X if (!f || n == 1)
- X return (TRUE);
- X if (n < 1)
- X return (FALSE);
- X s = forwline(TRUE,n-1);
- X if (s && curwp->w_dotp == curbp->b_linep)
- X s = backline(FALSE,1);
- X return s;
- }
- X
- atmark()
- {
- X return ((curwp->w_dotp == curwp->w_mkp) &&
- X (curwp->w_doto == curwp->w_mko));
- }
- X
- /*
- X * Swap the values of "." and "mark" in the current window. This is pretty
- X * easy, bacause all of the hard work gets done by the standard routine
- X * that moves the mark about. The only possible error is "no mark".
- X */
- swapmark()
- {
- X register LINE *odotp;
- X register int odoto;
- X
- X if (curwp->w_mkp == NULL) {
- X mlwrite("No mark in this window");
- X return (FALSE);
- X }
- X odotp = curwp->w_dotp;
- X odoto = curwp->w_doto;
- X curwp->w_dotp = curwp->w_mkp;
- X curwp->w_doto = curwp->w_mko;
- X curwp->w_mkp = odotp;
- X curwp->w_mko = odoto;
- X curwp->w_flag |= WFMOVE;
- X return (TRUE);
- }
- X
- X
- X
- #if NeWS
- /* SETCURSOR
- X *
- X * Mouse support function. Put the cursor to the requested location.
- X * The cursor will be put just after the last character of the line if
- X * requested past the line. The coordinates are expected in the command
- X * stream.
- X * In the case of multiple windows, the window indicated by the mouse
- X * is located and made the current window.
- X */
- setcursor()
- {
- int row, col, pasteol ;
- register LINE *dlp;
- WINDOW *wp0 ; /* current window on entry */
- X
- X row = tgetc() ;
- X col = tgetc() ;
- X
- /* find the window we are pointing to */
- X wp0 = curwp ;
- X while ( row < curwp->w_toprow ||
- X row > curwp->w_ntrows + curwp->w_toprow ) {
- X nextwind(FALSE,0) ;
- X if ( curwp == wp0 ) break ; /* full circle */
- X }
- X
- /* move to the right row */
- X row -= curwp->w_toprow ;
- X dlp = curwp->w_linep ; /* get pointer to 1st line */
- X while ( row-- && (dlp != curbp->b_linep) ) dlp = lforw(dlp) ;
- X curwp->w_dotp = dlp ; /* set dot line pointer */
- X
- X /* now move the dot over until near the requested column */
- X curgoal = col ; /* a global for this ?? */
- X curwp->w_doto = getgoal(dlp) ;
- X curwp->w_flag |= WFMOVE;
- X return (TRUE);
- }
- #endif
- SHAR_EOF
- chmod 0444 basic.c ||
- echo 'restore of basic.c failed'
- Wc_c="`wc -c < 'basic.c'`"
- test 20335 -eq "$Wc_c" ||
- echo 'basic.c: original size 20335, current size' "$Wc_c"
- # ============= bind.c ==============
- echo 'x - extracting bind.c (Text)'
- sed 's/^X//' << 'SHAR_EOF' > 'bind.c' &&
- /* This file is for functions having to do with key bindings,
- X descriptions, help commands and startup file.
- X
- X written 11-feb-86 by Daniel Lawrence
- X */
- X
- #include <stdio.h>
- #include "estruct.h"
- #include "edef.h"
- #include "epath.h"
- X
- /* dummy prefix binding functions */
- extern CMDFUNC f_cntl_af, f_cntl_xf, f_unarg, f_esc;
- X
- /* give me some help!!!! bring up a buffer and read the help file into it */
- help(f, n)
- {
- X register WINDOW *wp; /* scaning pointer to windows */
- X register BUFFER *bp; /* buffer pointer to help */
- X char *fname; /* ptr to file returned by flook() */
- X
- X /* first check if we are already here */
- X bp = bfind("[Help]", OK_CREAT, BFSCRTCH);
- X if (bp == NULL)
- X return FALSE;
- X
- X if (bp->b_active == FALSE) { /* never been used */
- X fname = flook(pathname[1], FL_ANYWHERE);
- X if (fname == NULL) {
- X mlwrite("[Sorry, can't find the help information]");
- X zotbuf(bp);
- X return(FALSE);
- X }
- X /* and read the stuff in */
- X if (readin(fname, 0, bp, TRUE) == FALSE ||
- X popupbuff(bp) == FALSE) {
- X zotbuf(bp);
- X return(FALSE);
- X }
- X strcpy(bp->b_bname,"[Help]");
- X sprintf(bp->b_fname, " %s %s",prognam,version);
- X bp->b_mode |= MDVIEW;
- X bp->b_mode &= ~MDEXACT;
- X bp->b_flag |= BFSCRTCH;
- X }
- X return swbuffer(bp);
- }
- X
- #if REBIND
- X
- deskey(f, n) /* describe the command for a certain key */
- {
- X register int c; /* key to describe */
- X register char *ptr; /* string pointer to scan output strings */
- X char outseq[NSTRING]; /* output buffer for command sequence */
- X char *kcod2prc();
- X
- X /* prompt the user to type us a key to describe */
- X mlwrite(": describe-key ");
- X
- X /* get the command sequence to describe
- X change it to something we can print as well */
- X
- X /* check to see if we are executing a command line */
- X if (clexec) {
- X char tok[NSTRING];
- X macarg(tok); /* get the next token */
- X c = prc2kcod(tok);
- X } else {
- X c = kbd_seq();
- X }
- X kcod2prc(c, &outseq[0]);
- X
- X /* and dump it out */
- X ostring(outseq);
- X ostring(" ");
- X
- X /* find the right ->function */
- X if ((ptr = fnc2engl(kcod2fnc(c))) == NULL)
- X ptr = "Not Bound";
- X
- X /* output the command sequence */
- X ostring(ptr);
- }
- X
- /* bindkey: add a new key to the key binding table */
- X
- bindkey(f, n)
- int f, n; /* command arguments [IGNORED] */
- {
- X register int c; /* command key to bind */
- X register CMDFUNC *kcmd; /* ptr to the requested function to bind to */
- X register KBIND *kbp; /* pointer into a binding table */
- X register int found; /* matched command flag */
- X char outseq[80]; /* output buffer for keystroke sequence */
- X char *fnp;
- X char *kbd_engl();
- X char *kcod2prc();
- X
- X /* prompt the user to type in a key to bind */
- X mlwrite(": bind-to-key ");
- X
- X /* get the function name to bind it to */
- #if NeWS
- X newsimmediateon() ;
- #endif
- X fnp = kbd_engl();
- #if NeWS
- X newsimmediateoff() ;
- #endif
- X
- X if (fnp == NULL || (kcmd = engl2fnc(fnp)) == NULL) {
- X mlwrite("[No such function]");
- X return(FALSE);
- X }
- X ostring(" ");
- X TTflush();
- X
- X /* get the command sequence to bind */
- X if (clexec) {
- X char tok[NSTRING];
- X macarg(tok); /* get the next token */
- X c = prc2kcod(tok);
- X } else {
- X /* perhaps we only want a single key, not a sequence */
- X /* (see more comments below) */
- X if ((kcmd == &f_cntl_af) || (kcmd == &f_cntl_xf) ||
- X (kcmd == &f_unarg) || (kcmd == &f_esc))
- X c = kbd_key();
- X else
- X c = kbd_seq();
- X }
- X
- X /* change it to something we can print as well */
- X kcod2prc(c, &outseq[0]);
- X
- X /* and dump it out */
- X ostring(outseq);
- X
- X /* if the function is a prefix key, i.e. we're changing the definition
- X of a prefix key, then they typed a dummy function name, which
- X has been translated into a dummy function pointer */
- X if (kcmd == &f_cntl_af || kcmd == &f_cntl_xf ||
- X kcmd == &f_unarg || kcmd == &f_esc) {
- X register CMDFUNC **cfp;
- X /* search for an existing binding for the prefix key */
- X cfp = asciitbl;
- X found = FALSE;
- X for (cfp = asciitbl; cfp < &asciitbl[128]; cfp++) {
- X if (*cfp == kcmd) {
- X unbindchar(cfp - asciitbl);
- X break;
- X }
- X }
- X
- X /* reset the appropriate global prefix variable */
- X if (kcmd == &f_cntl_af)
- X cntl_a = c;
- X if (kcmd == &f_cntl_xf)
- X cntl_x = c;
- X if (kcmd == &f_unarg)
- X reptc = c;
- X if (kcmd == &f_esc)
- X abortc = c;
- X }
- X
- X if ((c & (CTLA|SPEC|CTLX)) == 0) {
- X asciitbl[c] = kcmd;
- X } else {
- X for(kbp = kbindtbl; kbp->k_cmd && kbp->k_code != c; kbp++)
- X ;
- X if (kbp->k_cmd) { /* found it, change it in place */
- X kbp->k_cmd = kcmd;
- X } else {
- X if (kbp >= &kbindtbl[NBINDS-1]) {
- X mlwrite("Prefixed binding table full");
- X return(FALSE);
- X }
- X kbp->k_code = c; /* add keycode */
- X kbp->k_cmd = kcmd; /* and func pointer */
- X ++kbp; /* and make sure the next is null */
- X kbp->k_code = 0;
- X kbp->k_cmd = NULL;
- X }
- X }
- X
- X return TRUE;
- }
- X
- /* unbindkey: delete a key from the key binding table */
- X
- unbindkey(f, n)
- int f, n; /* command arguments [IGNORED] */
- {
- X register int c; /* command key to unbind */
- X char outseq[80]; /* output buffer for keystroke sequence */
- X char *kcod2prc();
- X
- X /* prompt the user to type in a key to unbind */
- X mlwrite(": unbind-key ");
- X
- X /* get the command sequence to unbind */
- X if (clexec) {
- X char tok[NSTRING];
- X macarg(tok); /* get the next token */
- X c = prc2kcod(tok);
- X } else {
- X c = kbd_seq();
- X }
- X
- X /* change it to something we can print as well */
- X kcod2prc(c, &outseq[0]);
- X
- X /* and dump it out */
- X ostring(outseq);
- X
- X /* if it isn't bound, bitch */
- X if (unbindchar(c) == FALSE) {
- X mlwrite("[Key not bound]");
- X return(FALSE);
- X }
- X return(TRUE);
- }
- X
- unbindchar(c)
- int c; /* command key to unbind */
- {
- X register KBIND *kbp; /* pointer into the command table */
- X register KBIND *skbp; /* saved pointer into the command table */
- X register int found; /* matched command flag */
- X
- X if ((c & (CTLA|SPEC|CTLX)) == 0) {
- X asciitbl[c] = NULL;
- X } else {
- X /* search the table to see if the key exists */
- X for (kbp = kbindtbl; kbp->k_cmd && kbp->k_code != c; kbp++)
- X ;
- X
- X /* if it isn't bound, bitch */
- X if (kbp->k_cmd == NULL)
- X return(FALSE);
- X
- X /* save the pointer and scan to the end of the table */
- X skbp = kbp;
- X while (kbp->k_cmd != NULL)
- X ++kbp;
- X --kbp; /* backup to the last legit entry */
- X
- X /* copy the last entry to the current one */
- X skbp->k_code = kbp->k_code;
- X skbp->k_cmd = kbp->k_cmd;
- X
- X /* null out the last one */
- X kbp->k_code = 0;
- X kbp->k_cmd = NULL;
- X }
- X return TRUE;
- }
- X
- /* describe bindings bring up a fake buffer and list the key bindings
- X into it with view mode */
- desbind(f, n)
- {
- X return mkblist(NULL);
- }
- X
- #if APROP
- apro(f, n) /* Apropos (List functions that match a substring) */
- {
- X static char mstring[NSTRING] = 0; /* string to match cmd names to */
- X register int s;
- X
- X
- X s = mlreply("Apropos string: ", mstring, NSTRING - 1);
- X if (s != TRUE)
- X return(s);
- X
- X return mkblist(mstring);
- }
- #endif
- X
- mkblist(mstring)
- char *mstring;
- {
- X register BUFFER *bp;
- X register int s;
- X
- X /* create the buffer list buffer */
- X bp = bfind("[Binding List]", OK_CREAT, BFSCRTCH);
- X if (bp == NULL)
- X return FALSE;
- X
- X if ((s=bclear(bp)) != TRUE) /* clear old text (?) */
- X return (s);
- X s = buildlist(mstring,bp);
- X if (s != TRUE || popupbuff(bp) == FALSE) {
- X mlwrite("[Sorry, can't list. ]");
- X zotbuf(bp);
- X return (s);
- X }
- X strcpy(bp->b_fname, "");
- X bp->b_mode |= MDVIEW;
- X bp->b_flag |= BFSCRTCH;
- X bp->b_flag &= ~BFCHG; /* Don't complain! */
- X bp->b_active = TRUE;
- X
- X return TRUE;
- }
- X
- X
- /* build a binding list (limited or full) */
- buildlist(mstring, bp)
- char *mstring; /* match string if partial list, NULL to list all */
- register BUFFER *bp; /* buffer to put binding list into */
- {
- #if ST520 & LATTICE
- #define register
- #endif
- X register WINDOW *wp; /* scanning pointer to windows */
- X register KBIND *kbp; /* pointer into a key binding table */
- X register CMDFUNC **cfp; /* pointer into the ascii table */
- X register NTAB *nptr,*nptr2; /* pointer into the name table */
- X char *strp; /* pointer int string to send */
- X int cpos; /* current position to use in outseq */
- X char outseq[81]; /* output buffer for keystroke sequence */
- X int i,pass;
- X char *kcod2prc();
- X
- X
- X /* let us know this is in progress */
- X mlwrite("[Building binding list]");
- X
- X /* build the contents of this window, inserting it line by line */
- X for (pass = 0; pass < 2; pass++) {
- X for (nptr = nametbl; nptr->n_name != NULL; ++nptr) {
- X
- X /* if we've already described this one, move on */
- X if (nptr->n_cmd->c_flags & LISTED)
- X continue;
- X
- X /* try to avoid alphabetizing by the real short names */
- X if (pass == 0 && strlen(nptr->n_name) <= 2)
- X continue;
- X
- X /* add in the command name */
- X strcpy(outseq,"\"");
- X strcat(outseq, nptr->n_name);
- X strcat(outseq,"\"");
- X cpos = strlen(outseq);
- X while (cpos < 32)
- X outseq[cpos++] = ' ';
- X outseq[cpos] = 0;
- X
- #if APROP
- X /* if we are executing an apropos command
- X and current string doesn't include the search string */
- X if (mstring && (strinc(outseq, mstring) == FALSE))
- X continue;
- #endif
- X /* look in the simple ascii binding table first */
- X for(cfp = asciitbl, i = 0; cfp < &asciitbl[128]; cfp++, i++) {
- X if (*cfp == nptr->n_cmd) {
- X cpos = kcod2prc(i, &outseq[strlen(outseq)]) -
- X outseq;
- X while(cpos & 7)
- X outseq[cpos++] = ' ';
- X outseq[cpos] = '\0';
- X }
- X }
- X /* then look in the multi-key table */
- X for(kbp = kbindtbl; kbp->k_cmd; kbp++) {
- X if (kbp->k_cmd == nptr->n_cmd) {
- X cpos =
- X kcod2prc(kbp->k_code, &outseq[strlen(outseq)]) -
- X outseq;
- X while(cpos & 7)
- X outseq[cpos++] = ' ';
- X outseq[cpos] = '\0';
- X }
- X }
- X /* dump the line */
- X addline(bp,outseq,-1);
- X
- X cpos = 0;
- X
- X /* then look for synonyms */
- X for (nptr2 = nametbl; nptr2->n_name != NULL; ++nptr2) {
- X /* if it's the one we're on, skip */
- X if (nptr2 == nptr)
- X continue;
- X /* if it's already been listed, skip */
- X if (nptr2->n_cmd->c_flags & LISTED)
- X continue;
- X /* if it's not a synonym, skip */
- X if (nptr2->n_cmd != nptr->n_cmd)
- X continue;
- X while (cpos < 8)
- X outseq[cpos++] = ' ';
- X outseq[cpos] = '\0';
- X strcat(outseq,"\"");
- X strcat(outseq,nptr2->n_name);
- X strcat(outseq,"\"");
- X addline(bp,outseq,-1);
- X cpos = 0; /* and clear the line */
- X
- X }
- X
- X nptr->n_cmd->c_flags |= LISTED; /* mark it as already listed */
- X }
- X }
- X
- X for (nptr = nametbl; nptr->n_name != NULL; ++nptr)
- X nptr->n_cmd->c_flags &= ~LISTED; /* mark it as unlisted */
- X
- X mlwrite(""); /* clear the mode line */
- X return(TRUE);
- }
- X
- #if APROP
- strinc(source, sub) /* does source include sub? */
- char *source; /* string to search in */
- char *sub; /* substring to look for */
- {
- X char *sp; /* ptr into source */
- X char *nxtsp; /* next ptr into source */
- X char *tp; /* ptr into substring */
- X
- X /* for each character in the source string */
- X sp = source;
- X while (*sp) {
- X tp = sub;
- X nxtsp = sp;
- X
- X /* is the substring here? */
- X while (*tp) {
- X if (*nxtsp++ != *tp)
- X break;
- X else
- X tp++;
- X }
- X
- X /* yes, return a success */
- X if (*tp == 0)
- X return(TRUE);
- X
- X /* no, onward */
- X sp++;
- X }
- X return(FALSE);
- }
- #endif
- X
- #endif /* REBIND */
- X
- X
- /* execute the startup file */
- X
- startup(sfname)
- char *sfname; /* name of startup file */
- {
- X char *fname; /* resulting file name to execute */
- X
- X /* look up the startup file */
- X fname = flook(sfname, FL_HERE_HOME);
- X
- X /* if it isn't around, don't sweat it */
- X if (fname == NULL) {
- X mlwrite("[Can't find startup file %s]",sfname);
- X return(TRUE);
- X }
- X
- X /* otherwise, execute the sucker */
- X return(dofile(fname));
- }
- X
- /* Look up the existence of a file along the normal or PATH
- X environment variable. Look first in the HOME directory if
- X asked and possible
- */
- X
- char *
- flook(fname, hflag)
- char *fname; /* base file name to search for */
- int hflag; /* Look in the HOME environment variable first? */
- {
- X register char *home; /* path to home directory */
- X register char *path; /* environmental PATH variable */
- X register char *sp; /* pointer into path spec */
- X register int i; /* index */
- X static char fspec[NSTRING]; /* full path spec to search */
- X char *getenv();
- X
- X /* tak care of special cases */
- X if (!fname || !fname[0] || isspace(fname[0]))
- X return NULL;
- X else if (fname[0] == '!')
- X return fname;
- X
- X /* always try the current directory first */
- X if (ffropen(fname) == FIOSUC) {
- X ffclose();
- X return(fname);
- X }
- X
- X if (hflag == FL_HERE)
- X return NULL;
- X
- #if ENVFUNC
- X
- X if (hflag) {
- X home = getenv("HOME");
- X if (home != NULL) {
- X /* build home dir file spec */
- X strcpy(fspec, home);
- X strcat(fspec, "/");
- X strcat(fspec, fname);
- X
- X /* and try it out */
- X if (ffropen(fspec) == FIOSUC) {
- X ffclose();
- X return(fspec);
- X }
- X }
- X }
- X
- X if (hflag == FL_HERE_HOME)
- X return NULL;
- X
- #if PATHLOOK
- X /* get the PATH variable */
- X path = getenv("PATH");
- X if (path != NULL)
- X while (*path) {
- X
- X /* build next possible file spec */
- X sp = fspec;
- X while (*path && (*path != PATHCHR))
- X *sp++ = *path++;
- X *sp++ = '/';
- X *sp = 0;
- X strcat(fspec, fname);
- X
- X /* and try it out */
- X if (ffropen(fspec) == FIOSUC) {
- X ffclose();
- X return(fspec);
- X }
- X
- X if (*path == PATHCHR)
- X ++path;
- X }
- #endif
- #endif
- X
- X /* look it up via the old table method */
- X for (i=2; i < NPNAMES; i++) {
- X strcpy(fspec, pathname[i]);
- X strcat(fspec, fname);
- X
- X /* and try it out */
- X if (ffropen(fspec) == FIOSUC) {
- X ffclose();
- X return(fspec);
- X }
- X }
- X
- X
- X return NULL; /* no such luck */
- }
- X
- /* translate a 10-bit keycode to its printable name (like "M-j") */
- char *
- kcod2prc(c, seq)
- int c; /* sequence to translate */
- char *seq; /* destination string for sequence */
- {
- X char *ptr; /* pointer into current position in sequence */
- X
- X ptr = seq;
- X
- X /* apply cntl_a sequence if needed */
- X if (c & CTLA) {
- X *ptr++ = '^';
- X *ptr++ = 'A';
- X *ptr++ = '-';
- X }
- X
- X /* apply ^X sequence if needed */
- X if (c & CTLX) {
- X *ptr++ = '^';
- X *ptr++ = 'X';
- X *ptr++ = '-';
- X }
- X
- X /* apply SPEC sequence if needed */
- X if (c & SPEC) {
- X *ptr++ = 'F';
- X *ptr++ = 'N';
- X *ptr++ = '-';
- X }
- X
- X c = kcod2key(c);
- X
- X /* apply control sequence if needed */
- X if (iscntrl(c)) {
- X *ptr++ = '^';
- X c = toalpha(c);
- X }
- X
- X /* and output the final sequence */
- X
- X if (c == ' ') {
- X *ptr++ = '<';
- X *ptr++ = 's';
- X *ptr++ = 'p';
- X *ptr++ = '>';
- X } else if (c == '\t') {
- X *ptr++ = '<';
- X *ptr++ = 't';
- X *ptr++ = 'a';
- X *ptr++ = 'b';
- X *ptr++ = '>';
- X } else {
- X *ptr++ = c;
- X }
- X *ptr = 0; /* terminate the string */
- X return ptr;
- }
- X
- X
- /* kcod2fnc: translate a 10-bit keycode to a function pointer */
- /* (look a key binding up in the binding table) */
- CMDFUNC *
- kcod2fnc(c)
- int c; /* key to find what is bound to it */
- {
- X register KBIND *kbp;
- X
- X if ((c & (CTLA|SPEC|CTLX)) == 0) {
- X return asciitbl[c];
- X } else {
- X for (kbp = kbindtbl; kbp->k_cmd && kbp->k_code != c; kbp++)
- X ;
- X return kbp->k_cmd;
- X }
- }
- X
- X
- /* fnc2engl: translate a function pointer to the english name for
- X that function
- */
- X
- char *
- fnc2engl(cfp)
- CMDFUNC *cfp; /* ptr to the requested function to bind to */
- {
- X register NTAB *nptr; /* pointer into the name table */
- X
- X /* skim through the table, looking for a match */
- X for (nptr = nametbl; nptr->n_cmd; nptr++) {
- SHAR_EOF
- true || echo 'restore of bind.c failed'
- echo 'End of Vile part 1'
- echo 'File bind.c is continued in part 2'
- echo 2 > _shar_seq_.tmp
- exit 0
- --
- paul fox, pgf@cayman.com, (617)494-1999
- Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139
-