Path: seismo!harvard!husc6!panda!sources-request From: sources-request@panda.UUCP Newsgroups: mod.sources Subject: MicroEMACS 3.6 (Part 8 of 8) Message-ID: <1828@panda.UUCP> Date: 8 May 86 10:55:49 GMT Sender: jpn@panda.UUCP Lines: 1695 Approved: jpn@panda.UUCP Mod.sources: Volume 4, Issue 105 Submitted by: ihnp4!itivax!duncan!lawrence echo x - termio.c sed 's/^X//' >termio.c <<'*-*-END-of-termio.c-*-*' X/* X * The functions in this file negotiate with the operating system for X * characters, and write characters in a barely buffered fashion on the display. X * All operating systems. X */ X#include X#include "estruct.h" X#include "edef.h" X X#if AMIGA X#define NEW 1006 X#define AMG_MAXBUF 1024 Xstatic long terminal; Xstatic char scrn_tmp[AMG_MAXBUF+1]; Xstatic int scrn_tmp_p = 0; X#endif X X#if VMS X#include X#include X#include X#include X#include X X#define NIBUF 128 /* Input buffer size */ X#define NOBUF 1024 /* MM says bug buffers win! */ X#define EFN 0 /* Event flag */ X Xchar obuf[NOBUF]; /* Output buffer */ Xint nobuf; /* # of bytes in above */ Xchar ibuf[NIBUF]; /* Input buffer */ Xint nibuf; /* # of bytes in above */ Xint ibufi; /* Read index */ Xint oldmode[2]; /* Old TTY mode bits */ Xint newmode[2]; /* New TTY mode bits */ Xshort iochan; /* TTY I/O channel */ X#endif X X#if CPM X#include X#endif X X#if MSDOS & LATTICE X#undef LATTICE X#undef CPM X#include X#undef CPM Xunion REGS rg; /* cpu register for use of DOS calls */ Xint nxtchar = -1; /* character held from type ahead */ X#endif X X#if MSDOS & AZTEC Xstruct regs { /* cpu register for use of DOS calls */ X int ax, bx, cx, dx, si, di, ds, es; } rg; Xint nxtchar = -1; /* character held from type ahead */ X#endif X X#if RAINBOW X#include "rainbow.h" X#endif X X#if V7 X#undef CTRL X#include /* for stty/gtty functions */ X#include Xstruct sgttyb ostate; /* saved tty state */ Xstruct sgttyb nstate; /* values for editor mode */ Xstruct tchars otchars; /* Saved terminal special character set */ Xstruct tchars ntchars = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; X /* A lot of nothing */ X#if BSD X#include /* to get at the typeahead */ Xextern int rtfrmshell(); /* return from suspended shell */ X#define TBUFSIZ 128 Xchar tobuf[TBUFSIZ]; /* terminal output buffer */ X#endif X#endif X X/* X * This function is called once to set up the terminal device streams. X * On VMS, it translates TT until it finds the terminal, then assigns X * a channel to it and sets it raw. On CPM it is a no-op. X */ Xttopen() X{ X#if AMIGA X terminal = Open("RAW:1/1/639/199/MicroEMACS 3.6/Amiga", NEW); X#endif X#if VMS X struct dsc$descriptor idsc; X struct dsc$descriptor odsc; X char oname[40]; X int iosb[2]; X int status; X X odsc.dsc$a_pointer = "TT"; X odsc.dsc$w_length = strlen(odsc.dsc$a_pointer); X odsc.dsc$b_dtype = DSC$K_DTYPE_T; X odsc.dsc$b_class = DSC$K_CLASS_S; X idsc.dsc$b_dtype = DSC$K_DTYPE_T; X idsc.dsc$b_class = DSC$K_CLASS_S; X do { X idsc.dsc$a_pointer = odsc.dsc$a_pointer; X idsc.dsc$w_length = odsc.dsc$w_length; X odsc.dsc$a_pointer = &oname[0]; X odsc.dsc$w_length = sizeof(oname); X status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc); X if (status!=SS$_NORMAL && status!=SS$_NOTRAN) X exit(status); X if (oname[0] == 0x1B) { X odsc.dsc$a_pointer += 4; X odsc.dsc$w_length -= 4; X } X } while (status == SS$_NORMAL); X status = SYS$ASSIGN(&odsc, &iochan, 0, 0); X if (status != SS$_NORMAL) X exit(status); X status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0, X oldmode, sizeof(oldmode), 0, 0, 0, 0); X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) X exit(status); X newmode[0] = oldmode[0]; X newmode[1] = oldmode[1] | TT$M_PASSALL | TT$M_NOECHO; X status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, X newmode, sizeof(newmode), 0, 0, 0, 0); X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) X exit(status); X#endif X#if CPM X#endif X X#if MSDOS & (HP150 == 0) & LATTICE X /* kill the ctrl-break interupt */ X rg.h.ah = 0x33; /* control-break check dos call */ X rg.h.al = 1; /* set the current state */ X rg.h.dl = 0; /* set it OFF */ X intdos(&rg, &rg); /* go for it! */ X#endif X X#if V7 | BSD X gtty(0, &ostate); /* save old state */ X gtty(0, &nstate); /* get base of new state */ X nstate.sg_flags |= RAW; X nstate.sg_flags &= ~(ECHO|CRMOD); /* no echo for now... */ X stty(0, &nstate); /* set mode */ X ioctl(0, TIOCGETC, &otchars); /* Save old characters */ X ioctl(0, TIOCSETC, &ntchars); /* Place new character into K */ X#if BSD X /* provide a smaller terminal output buffer so that X the type ahead detection works better (more often) */ X setbuffer(stdout, &tobuf[0], TBUFSIZ); X signal(SIGTSTP,SIG_DFL); /* set signals so that we can */ X signal(SIGCONT,rtfrmshell); /* suspend & restart emacs */ X#endif X#endif X} X X/* X * This function gets called just before we go back home to the command X * interpreter. On VMS it puts the terminal back in a reasonable state. X * Another no-operation on CPM. X */ Xttclose() X{ X#if AMIGA X amg_flush(); X Close(terminal); X#endif X#if VMS X int status; X int iosb[1]; X X ttflush(); X status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0, X oldmode, sizeof(oldmode), 0, 0, 0, 0); X if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL) X exit(status); X status = SYS$DASSGN(iochan); X if (status != SS$_NORMAL) X exit(status); X#endif X#if CPM X#endif X#if MSDOS & (HP150 == 0) & LATTICE X /* restore the ctrl-break interupt */ X rg.h.ah = 0x33; /* control-break check dos call */ X rg.h.al = 1; /* set the current state */ X rg.h.dl = 1; /* set it ON */ X intdos(&rg, &rg); /* go for it! */ X#endif X X#if V7 X stty(0, &ostate); X ioctl(0, TIOCSETC, &otchars); /* Place old character into K */ X#endif X} X X/* X * Write a character to the display. On VMS, terminal output is buffered, and X * we just put the characters in the big array, after checking for overflow. X * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on X * MS-DOS (use the very very raw console output routine). X */ Xttputc(c) X#if AMIGA X char c; X#endif X{ X#if AMIGA X scrn_tmp[scrn_tmp_p++] = c; X if(scrn_tmp_p>=AMG_MAXBUF) X amg_flush(); X#endif X#if VMS X if (nobuf >= NOBUF) X ttflush(); X obuf[nobuf++] = c; X#endif X X#if CPM X bios(BCONOUT, c, 0); X#endif X X#if MSDOS & CWC86 X dosb(CONDIO, c, 0); X#endif X X#if MSDOS & LATTICE X bdos(6, c, 0); X#endif X X#if MSDOS & AZTEC X bdos(6, c, 0); X#endif X X#if RAINBOW X Put_Char(c); /* fast video */ X#endif X X#if V7 X fputc(c, stdout); X#endif X} X X#if AMIGA Xamg_flush() X{ X if(scrn_tmp_p) X Write(terminal,scrn_tmp,scrn_tmp_p); X scrn_tmp_p = 0; X} X#endif X X/* X * Flush terminal buffer. Does real work where the terminal output is buffered X * up. A no-operation on systems where byte at a time terminal I/O is done. X */ Xttflush() X{ X#if AMIGA X amg_flush(); X#endif X#if VMS X int status; X int iosb[2]; X X status = SS$_NORMAL; X if (nobuf != 0) { X status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT, X iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0); X if (status == SS$_NORMAL) X status = iosb[0] & 0xFFFF; X nobuf = 0; X } X return (status); X#endif X#if CPM X#endif X#if MSDOS X#endif X#if V7 X fflush(stdout); X#endif X} X X/* X * Read a character from the terminal, performing no editing and doing no echo X * at all. More complex in VMS that almost anyplace else, which figures. Very X * simple on CPM, because the system can do exactly what you want. X */ Xttgetc() X{ X#if AMIGA X char ch; X amg_flush(); X Read(terminal, &ch, 1); X return(255 & (int)ch); X#endif X#if VMS X int status; X int iosb[2]; X int term[2]; X X while (ibufi >= nibuf) { X ibufi = 0; X term[0] = 0; X term[1] = 0; X status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED, X iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0); X if (status != SS$_NORMAL) X exit(status); X status = iosb[0] & 0xFFFF; X if (status!=SS$_NORMAL && status!=SS$_TIMEOUT) X exit(status); X nibuf = (iosb[0]>>16) + (iosb[1]>>16); X if (nibuf == 0) { X status = SYS$QIOW(EFN, iochan, IO$_READLBLK, X iosb, 0, 0, ibuf, 1, 0, term, 0, 0); X if (status != SS$_NORMAL X || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL) X exit(status); X nibuf = (iosb[0]>>16) + (iosb[1]>>16); X } X } X return (ibuf[ibufi++] & 0xFF); /* Allow multinational */ X#endif X X#if CPM X return (biosb(BCONIN, 0, 0)); X#endif X X#if RAINBOW X int Ch; X X while ((Ch = Read_Keyboard()) < 0); X X if ((Ch & Function_Key) == 0) X if (!((Ch & 0xFF) == 015 || (Ch & 0xFF) == 0177)) X Ch &= 0xFF; X X return Ch; X#endif X X#if MSDOS & MWC86 X return (dosb(CONRAW, 0, 0)); X#endif X X#if MSDOS & LATTICE X int c; /* character read */ X int flags; /* cpu flags after dos call */ X X /* if a char already is ready, return it */ X if (nxtchar >= 0) { X c = nxtchar; X nxtchar = -1; X return(c); X } X X /* call the dos to get a char until one is there */ X flags = 255; X while ((flags & 64) != 0) { /* while we don't yet have a char */ X rg.h.ah = 6; /* dos Direct Console I/O call */ X rg.h.dl = 255; /* console input */ X flags = intdos(&rg, &rg); X c = rg.h.al; /* grab the char */ X } X X return(c & 255); X#endif X X#if MSDOS & AZTEC X int c; /* character read */ X int flags; /* cpu flags after dos call */ X X /* if a char already is ready, return it */ X if (nxtchar >= 0) { X c = nxtchar; X nxtchar = -1; X return(c); X } X X /* call the dos to get a char until one is there */ X flags = 255; X while ((flags & 64) != 0) { /* while we don't yet have a char */ X rg.ax = 1536; /* dos Direct Console I/O call */ X rg.dx = 255; /* console input */ X flags = sysint(33, &rg, &rg); X c = rg.ax & 255; /* grab the char */ X } X X return(c); X#endif X X#if V7 X return(127 & fgetc(stdin)); X#endif X} X X#if TYPEAH X/* typahead: Check to see if any characters are already in the X keyboard buffer X*/ X Xtypahead() X X{ X#if MSDOS & LATTICE X int c; /* character read */ X int flags; /* cpu flags from dos call */ X X if (nxtchar >= 0) X return(TRUE); X X rg.h.ah = 6; /* Direct Console I/O call */ X rg.h.dl = 255; /* does console input */ X flags = intdos(&rg, &rg); X c = rg.h.al; /* grab the character */ X X /* no character pending */ X if ((flags & 64) != 0) X return(FALSE); X X /* save the character and return true */ X nxtchar = c; X return(TRUE); X#endif X X#if MSDOS & AZTEC X int c; /* character read */ X int flags; /* cpu flags from dos call */ X X if (nxtchar >= 0) X return(TRUE); X X rg.ax = 1536; /* Direct Console I/O call */ X rg.dx = 255; /* does console input */ X flags = sysint(33, &rg, &rg); X c = rg.ax & 255; /* grab the character */ X X /* no character pending */ X if ((flags & 64) != 0) X return(FALSE); X X /* save the character and return true */ X nxtchar = c; X return(TRUE); X#endif X X#if V7 & BSD X int x; /* holds # of pending chars */ X X return((ioctl(0,FIONREAD,&x) < 0) ? 0 : x); X#endif X return(FALSE); X} X#endif X *-*-END-of-termio.c-*-* echo x - vmsvt.c sed 's/^X//' >vmsvt.c <<'*-*-END-of-vmsvt.c-*-*' X/* X * VMS terminal handling routines X * X * Known types are: X * VT52, VT100, and UNKNOWN (which is defined to be an ADM3a) X * written by Curtis Smith X */ X X#include X#include "estruct.h" X#include "edef.h" X X#if VMSVT X X#define termdef 1 /* don't define "term" external */ X X#include /* Status code definitions */ X#include /* Descriptor structures */ X#include /* IO commands */ X#include /* tty commands */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int vmsopen(); Xextern int vmseeol(); Xextern int vmseeop(); Xextern int vmsbeep(); Xextern int vmsmove(); Xextern int vmsrev(); Xextern int eolexist; X X#define NROWS 24 /* # of screen rolls */ X#define NCOLS 80 /* # of screen columns */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X X/* X * Dispatch table. All the X * hard fields just point into the X * terminal I/O code. X */ XTERM term = { X NROWS - 1, X NCOLS, X MARGIN, X SCRSIZ, X &vmsopen, X &ttclose, X &ttgetc, X &ttputc, X &ttflush, X &vmsmove, X &vmseeol, X &vmseeop, X &vmsbeep, X &vmsrev X}; X Xchar * termeop; /* Erase to end of page string */ Xint eoppad; /* Number of pad characters after eop */ Xchar * termeol; /* Erase to end of line string */ Xint eolpad; /* Number of pad characters after eol */ Xchar termtype; /* Terminal type identifier */ X X X/******* X * ttputs - Send a string to ttputc X *******/ X Xttputs(string) Xchar * string; X{ X while (*string != '\0') X ttputc(*string++); X} X X X/******* X * vmspad - Pad the output after an escape sequence X *******/ X Xvmspad(count) Xint count; X{ X while (count-- > 0) X ttputc('\0'); X} X X X/******* X * vmsmove - Move the cursor X *******/ X Xvmsmove(row, col) X{ X switch (termtype) { X case TT$_UNKNOWN: X ttputc('\033'); X ttputc('='); X ttputc(row+' '); X ttputc(col+' '); X break; X case TT$_VT52: X ttputc('\033'); X ttputc('Y'); X ttputc(row+' '); X ttputc(col+' '); X break; X case TT$_VT100: X { X char buffer[24]; X X sprintf(buffer, "\033[%d;%dH", row+1, col+1); X ttputs(buffer); X vmspad(50); X } X } X} X X/******* X * vmsrev - set the reverse video status X *******/ X Xvmsrev(status) X Xint status; /* TRUE = reverse video, FALSE = normal video */ X{ X switch (termtype) { X case TT$_UNKNOWN: X break; X case TT$_VT52: X break; X case TT$_VT100: X if (status) { X ttputc('\033'); X ttputc('['); X ttputc('7'); X ttputc('m'); X } else { X ttputc('\033'); X ttputc('['); X ttputc('m'); X } X break; X } X} X X/******* X * vmseeol - Erase to end of line X *******/ X Xvmseeol() X{ X ttputs(termeol); X vmspad(eolpad); X} X X X/******* X * vmseeop - Erase to end of page (clear screen) X *******/ X Xvmseeop() X{ X ttputs(termeop); X vmspad(eoppad); X} X X X/******* X * vmsbeep - Ring the bell X *******/ X Xvmsbeep() X{ X ttputc('\007'); X} X X X/******* X * vmsopen - Get terminal type and open terminal X *******/ X Xvmsopen() X{ X termtype = vmsgtty(); X switch (termtype) { X case TT$_UNKNOWN: /* Assume ADM3a */ X eolexist = FALSE; X termeop = "\032"; X eoppad = 0; X break; X case TT$_VT52: X termeol = "\033K"; X eolpad = 0; X termeop = "\033H\033J"; X eoppad = 0; X break; X case TT$_VT100: X revexist = TRUE; X termeol = "\033[K"; X eolpad = 3; X termeop = "\033[;H\033[2J"; X eoppad = 50; X break; X default: X puts("Terminal type not supported"); X exit (SS$_NORMAL); X } X ttopen(); X} X X Xstruct iosb { /* I/O status block */ X short i_cond; /* Condition value */ X short i_xfer; /* Transfer count */ X long i_info; /* Device information */ X}; X Xstruct 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 */ X}; X X/******* X * vmsgtty - Get terminal type from system control block X *******/ X Xvmsgtty() X{ X short fd; X int status; X struct iosb iostatus; X struct termchar tc; X $DESCRIPTOR(devnam, "SYS$INPUT"); X X status = sys$assign(&devnam, &fd, 0, 0); X if (status != SS$_NORMAL) X exit (status); X 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) != SS$_NORMAL) X exit(status); X X if (status != SS$_NORMAL) /* Jump out if bad status */ X exit(status); X if (iostatus.i_cond != SS$_NORMAL) X exit(iostatus.i_cond); X X return tc.t_type; /* Return terminal type */ X} X X#else X Xhellovms() X X{ X} X X#endif VMSVT *-*-END-of-vmsvt.c-*-* echo x - vt52.c sed 's/^X//' >vt52.c <<'*-*-END-of-vt52.c-*-*' X/* 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 */ X#define termdef 1 /* don't define "term" external */ X X#include X#include "estruct.h" X#include "edef.h" X X#if VT52 X X#define NROW 24 /* Screen size. */ X#define NCOL 80 /* Edit if you want to. */ X#define MARGIN 8 /* size of minimim margin and */ X#define SCRSIZ 64 /* scroll size for extended lines */ X#define BIAS 0x20 /* Origin 0 coordinate bias. */ X#define ESC 0x1B /* ESC character. */ X#define BEL 0x07 /* ascii bell character */ X Xextern int ttopen(); /* Forward references. */ Xextern int ttgetc(); Xextern int ttputc(); Xextern int ttflush(); Xextern int ttclose(); Xextern int vt52move(); Xextern int vt52eeol(); Xextern int vt52eeop(); Xextern int vt52beep(); Xextern int vt52open(); Xextern int vt52rev(); X X/* X * Dispatch table. All the X * hard fields just point into the X * terminal I/O code. X */ XTERM term = { X NROW-1, X NCOL, X MARGIN, X SCRSIZ, X &vt52open, X &ttclose, X &ttgetc, X &ttputc, X &ttflush, X &vt52move, X &vt52eeol, X &vt52eeop, X &vt52beep, X &vt52rev X}; X Xvt52move(row, col) X{ X ttputc(ESC); X ttputc('Y'); X ttputc(row+BIAS); X ttputc(col+BIAS); X} X Xvt52eeol() X{ X ttputc(ESC); X ttputc('K'); X} X Xvt52eeop() X{ X ttputc(ESC); X ttputc('J'); X} X Xvt52rev(status) /* set the reverse video state */ X Xint status; /* TRUE = reverse video, FALSE = normal video */ X X{ X /* can't do this here, so we won't */ X} X Xvt52beep() X{ X#ifdef BEL X ttputc(BEL); X ttflush(); X#endif X} X X#endif X Xvt52open() X{ X#if V7 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 } X#endif X ttopen(); X} *-*-END-of-vt52.c-*-* echo x - window.c sed 's/^X//' >window.c <<'*-*-END-of-window.c-*-*' X/* X * Window management. Some of the functions are internal, and some are X * attached to keys that the user actually types. X */ X X#include X#include "estruct.h" X#include "edef.h" X X/* X * Reposition dot in the current window to line "n". 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 (this is what the standard X * redisplay code does). With no argument it defaults to 1. Bound to M-!. X * Because of the default, it works like in Gosling. X */ Xreposition(f, n) X { 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 X/* X * Refresh the screen. With no argument, it just does the refresh. With an X * argument it recenters "." in the current window. Bound to "C-L". X */ Xrefresh(f, n) X { X if (f == FALSE) X sgarbf = TRUE; X else X { X curwp->w_force = 0; /* Center dot. */ X curwp->w_flag |= WFFORCE; X } X X return (TRUE); X } X 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. Bound to "C-X C-N". X */ Xnextwind(f, n) X { X register WINDOW *wp; X X if ((wp = curwp->w_wndp) == NULL) X wp = wheadp; X X curwp = wp; X curbp = wp->w_bufp; X upmode(); X return (TRUE); X } X 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 */ Xprevwind(f, n) X { X register WINDOW *wp1; X register WINDOW *wp2; 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 curbp = wp1->w_bufp; X upmode(); X return (TRUE); X } X 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. Bound to "C-X C-N". X */ Xmvdnwind(f, n) X int n; X { X return (mvupwind(f, -n)); X } X 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 "."; it moves the frame). Bound to X * "C-X C-P". X */ Xmvupwind(f, n) X int n; X { X register LINE *lp; X register int i; X X lp = curwp->w_linep; X X if (n < 0) X { X while (n++ && lp!=curbp->b_linep) X lp = lforw(lp); X } X else X { X while (n-- && lback(lp)!=curbp->b_linep) X lp = lback(lp); X } X X curwp->w_linep = lp; X curwp->w_flag |= WFHARD; /* Mode line is OK. */ X X for (i = 0; i < curwp->w_ntrows; ++i) X { X if (lp == curwp->w_dotp) X return (TRUE); X if (lp == curbp->b_linep) X break; X lp = lforw(lp); X } X X lp = curwp->w_linep; X i = curwp->w_ntrows/2; X X while (i-- && lp != curbp->b_linep) X lp = lforw(lp); X X curwp->w_dotp = lp; X curwp->w_doto = 0; X return (TRUE); X } X X/* X * This command makes the current window the only window on the screen. Bound X * to "C-X 1". 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 */ Xonlywind(f, n) X{ X register WINDOW *wp; X register LINE *lp; X register int i; X X while (wheadp != curwp) { X wp = wheadp; X wheadp = wp->w_wndp; X if (--wp->w_bufp->b_nwnd == 0) { X wp->w_bufp->b_dotp = wp->w_dotp; X wp->w_bufp->b_doto = wp->w_doto; X wp->w_bufp->b_markp = wp->w_markp; X wp->w_bufp->b_marko = wp->w_marko; X } X free((char *) wp); X } X while (curwp->w_wndp != NULL) { X wp = curwp->w_wndp; X curwp->w_wndp = wp->w_wndp; X if (--wp->w_bufp->b_nwnd == 0) { X wp->w_bufp->b_dotp = wp->w_dotp; X wp->w_bufp->b_doto = wp->w_doto; X wp->w_bufp->b_markp = wp->w_markp; X wp->w_bufp->b_marko = wp->w_marko; X } X free((char *) wp); X } 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 X/* X * Split the current window. A window smaller than 3 lines cannot be split. X * The only other error that is possible is a "malloc" failure allocating the X * structure for the new window. Bound to "C-X 2". X */ Xsplitwind(f, n) X{ 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 char *malloc(); 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("Cannot allocate WINDOW block"); 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_markp = curwp->w_markp; X wp->w_marko = curwp->w_marko; X wp->w_flag = 0; X wp->w_force = 0; 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 lp = curwp->w_linep; X if (ntrd <= ntru) { /* Old is upper window. */ X if (ntrd == ntru) /* Hit mode line. */ X lp = lforw(lp); X curwp->w_ntrows = ntru; X wp->w_wndp = curwp->w_wndp; X curwp->w_wndp = wp; X wp->w_toprow = curwp->w_toprow+ntru+1; X wp->w_ntrows = ntrl; X } else { /* 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 while (ntru--) X lp = lforw(lp); X } X curwp->w_linep = lp; /* Adjust the top lines */ X wp->w_linep = lp; /* if necessary. */ X curwp->w_flag |= WFMODE|WFHARD; X wp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X 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 X * all the hard work. You don't just set "force reframe" because dot would X * move. Bound to "C-X Z". X */ Xenlargewind(f, n) X{ X register WINDOW *adjwp; X register LINE *lp; X register int i; X X if (n < 0) X return (shrinkwind(f, -n)); X if (wheadp->w_wndp == NULL) { X mlwrite("Only one window"); X return (FALSE); X } X if ((adjwp=curwp->w_wndp) == NULL) { X adjwp = wheadp; X while (adjwp->w_wndp != curwp) X adjwp = adjwp->w_wndp; X } X if (adjwp->w_ntrows <= n) { X mlwrite("Impossible change"); X return (FALSE); X } X if (curwp->w_wndp == adjwp) { /* Shrink below. */ X lp = adjwp->w_linep; X for (i=0; iw_bufp->b_linep; ++i) X lp = lforw(lp); X adjwp->w_linep = lp; X adjwp->w_toprow += n; X } else { /* Shrink above. */ X lp = curwp->w_linep; X for (i=0; ib_linep; ++i) X lp = lback(lp); X curwp->w_linep = lp; X curwp->w_toprow -= n; X } X curwp->w_ntrows += n; X adjwp->w_ntrows -= n; X curwp->w_flag |= WFMODE|WFHARD; X adjwp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* X * Shrink the current window. Find the window that gains space. Hack at the X * window descriptions. Ask the redisplay to do all the hard work. Bound to X * "C-X C-Z". X */ Xshrinkwind(f, n) X{ X register WINDOW *adjwp; X register LINE *lp; X register int i; X X if (n < 0) X return (enlargewind(f, -n)); X if (wheadp->w_wndp == NULL) { X mlwrite("Only one window"); X return (FALSE); X } X if ((adjwp=curwp->w_wndp) == NULL) { X adjwp = wheadp; X while (adjwp->w_wndp != curwp) X adjwp = adjwp->w_wndp; X } X if (curwp->w_ntrows <= n) { X mlwrite("Impossible change"); X return (FALSE); X } X if (curwp->w_wndp == adjwp) { /* Grow below. */ X lp = adjwp->w_linep; X for (i=0; iw_bufp->b_linep; ++i) X lp = lback(lp); X adjwp->w_linep = lp; X adjwp->w_toprow -= n; X } else { /* Grow above. */ X lp = curwp->w_linep; X for (i=0; ib_linep; ++i) X lp = lforw(lp); X curwp->w_linep = lp; X curwp->w_toprow += n; X } X curwp->w_ntrows -= n; X adjwp->w_ntrows += n; X curwp->w_flag |= WFMODE|WFHARD; X adjwp->w_flag |= WFMODE|WFHARD; X return (TRUE); X} X X/* X * Pick a window for a pop-up. Split the screen if there is only one window. X * Pick the uppermost window that isn't the current window. An LRU algorithm X * might be better. Return a pointer, or NULL on error. X */ XWINDOW * Xwpopup() X{ X register WINDOW *wp; X X if (wheadp->w_wndp == NULL /* Only 1 window */ X && splitwind(FALSE, 0) == FALSE) /* and it won't split */ X return (NULL); X wp = wheadp; /* Find window to use */ X while (wp!=NULL && wp==curwp) X wp = wp->w_wndp; X return (wp); X} X Xscrnextup(f, n) /* scroll the next window up (back) a page */ X X{ X nextwind(FALSE, 1); X backpage(f, n); X prevwind(FALSE, 1); X} X Xscrnextdw(f, n) /* scroll the next window down (forward) a page */ X X{ X nextwind(FALSE, 1); X forwpage(f, n); X prevwind(FALSE, 1); X} *-*-END-of-window.c-*-* echo x - word.c sed 's/^X//' >word.c <<'*-*-END-of-word.c-*-*' X/* X * The routines in this file implement commands that work word at a time. X * There are all sorts of word mode commands. If I do any sentence and/or X * paragraph mode commands, they are likely to be put in this file. X */ X X#include X#include "estruct.h" X#include "edef.h" X X/* Word wrap on n-spaces. Back-over whatever precedes the point on the current X * line and stop on the first word-break or the beginning of the line. If we X * reach the beginning of the line, jump back to the end of the word and start X * a new line. Otherwise, break the line at the word-break, eat it, and jump X * back to the end of the word. X * Returns TRUE on success, FALSE on errors. X */ Xwrapword(n) Xint n; X{ X register int cnt; /* size of word wrapped to next line */ X X /* backup from the 1 char */ X if (!backchar(0, 1)) X return(FALSE); X X /* back up until we aren't in a word, X make sure there is a break in the line */ X cnt = 0; X while (inword()) { X cnt++; X if (!backchar(0, 1)) X return(FALSE); X } X X /* delete the forward space */ X if (!forwdel(0, 1)) X return(FALSE); X X /* put in a end of line */ X if (!newline(0, 1)) X return(FALSE); X X /* and past the first word */ X while (cnt-- > 0) { X if (forwchar(FALSE, 1) == FALSE) X return(FALSE); X } X return(TRUE); X} X X/* X * Move the cursor backward by "n" words. All of the details of motion are X * performed by the "backchar" and "forwchar" routines. Error if you try to X * move beyond the buffers. X */ Xbackword(f, n) X{ X if (n < 0) X return (forwword(f, -n)); X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (forwchar(FALSE, 1)); X} X X/* X * Move the cursor forward by the specified number of words. All of the motion X * is done by "forwchar". Error if you try and move beyond the buffer's end. X */ Xforwword(f, n) X{ X if (n < 0) X return (backword(f, -n)); X while (n--) { X#if NFWORD X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#endif X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#if NFWORD == 0 X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X#endif X } X return(TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move, X * convert any characters to upper case. Error if you try and move beyond the X * end of the buffer. Bound to "M-U". X */ Xupperword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert characters to lower case. Error if you try and move over the end of X * the buffer. Bound to "M-L". X */ Xlowerword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X return (TRUE); X} X X/* X * Move the cursor forward by the specified number of words. As you move X * convert the first character of the word to upper case, and subsequent X * characters to lower case. Error if you try and move past the end of the X * buffer. Bound to "M-C". X */ Xcapword(f, n) X{ X register int c; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X while (n--) { X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X if (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') { X c -= 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X while (inword() != FALSE) { X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='A' && c<='Z') { X c += 'a'-'A'; X lputc(curwp->w_dotp, curwp->w_doto, c); X lchange(WFHARD); X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X } X } X } X return (TRUE); X} X X/* X * Kill forward by "n" words. Remember the location of dot. Move forward by X * the right number of words. Put dot back where it was and issue the kill X * command for the right number of characters. Bound to "M-D". X */ Xdelfword(f, n) X{ X register int size; X register LINE *dotp; X register int doto; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X dotp = curwp->w_dotp; X doto = curwp->w_doto; X size = 0; X while (n--) { X#if NFWORD X while (inword() != FALSE) { X if (forwchar(FALSE,1) == FALSE) X return(FALSE); X ++size; X } X#endif X while (inword() == FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X#if NFWORD == 0 X while (inword() != FALSE) { X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X#endif X } X curwp->w_dotp = dotp; X curwp->w_doto = doto; X return (ldelete(size, TRUE)); X} X X/* X * Kill backwards by "n" words. Move backwards by the desired number of words, X * counting the characters. When dot is finally moved to its resting place, X * fire off the kill command. Bound to "M-Rubout" and to "M-Backspace". X */ Xdelbword(f, n) X{ X register int size; X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (n < 0) X return (FALSE); X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X size = 0; X while (n--) { X while (inword() == FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X while (inword() != FALSE) { X if (backchar(FALSE, 1) == FALSE) X return (FALSE); X ++size; X } X } X if (forwchar(FALSE, 1) == FALSE) X return (FALSE); X return (ldelete(size, TRUE)); X} X X/* X * Return TRUE if the character at dot is a character that is considered to be X * part of a word. The word character list is hard coded. Should be setable. X */ Xinword() X{ X register int c; X X if (curwp->w_doto == llength(curwp->w_dotp)) X return (FALSE); X c = lgetc(curwp->w_dotp, curwp->w_doto); X if (c>='a' && c<='z') X return (TRUE); X if (c>='A' && c<='Z') X return (TRUE); X if (c>='0' && c<='9') X return (TRUE); X if (c=='$' || c=='_') /* For identifiers */ X return (TRUE); X return (FALSE); X} X Xfillpara(f, n) /* Fill the current paragraph according to the current X fill column */ X Xint f, n; /* deFault flag and Numeric argument */ X X{ X register int c; /* current char durring scan */ X register int wordlen; /* length of current word */ X register int clength; /* position on line during fill */ X register int i; /* index during word copy */ X register int newlength; /* tentative new line length */ X register int eopflag; /* Are we at the End-Of-Paragraph? */ X register int firstflag; /* first word? (needs no space) */ X register LINE *eopline; /* pointer to line just past EOP */ X register int dotflag; /* was the last char a period? */ X char wbuf[NSTRING]; /* buffer for current word */ X X if (curbp->b_mode&MDVIEW) /* don't allow this command if */ X return(rdonly()); /* we are in read only mode */ X if (fillcol == 0) { /* no fill column set */ X mlwrite("No fill column set"); X return(FALSE); X } X X /* record the pointer to the line just past the EOP */ X gotoeop(FALSE, 1); X eopline = lforw(curwp->w_dotp); X X /* and back top the begining of the paragraph */ X gotobop(FALSE, 1); X X /* initialize various info */ X clength = curwp->w_doto; X if (clength && curwp->w_dotp->l_text[0] == TAB) X clength = 8; X wordlen = 0; X dotflag = FALSE; X X /* scan through lines, filling words */ X firstflag = TRUE; X eopflag = FALSE; X while (!eopflag) { X /* get the next character in the paragraph */ X if (curwp->w_doto == llength(curwp->w_dotp)) { X c = ' '; X if (lforw(curwp->w_dotp) == eopline) X eopflag = TRUE; X } else X c = lgetc(curwp->w_dotp, curwp->w_doto); X X /* and then delete it */ X ldelete(1, FALSE); X X /* if not a separator, just add it in */ X if (c != ' ' && c != ' ') { X dotflag = (c == '.'); /* was it a dot */ X if (wordlen < NSTRING - 1) X wbuf[wordlen++] = c; X } else if (wordlen) { X /* at a word break with a word waiting */ X /* calculate tantitive new length with word added */ X newlength = clength + 1 + wordlen; X if (newlength <= fillcol) { X /* add word to current line */ X if (!firstflag) { X linsert(1, ' '); /* the space */ X ++clength; X } X firstflag = FALSE; X } else { X /* start a new line */ X lnewline(); X clength = 0; X } X X /* and add the word in in either case */ X for (i=0; iw_markp = curwp->w_dotp; X curwp->w_marko = curwp->w_doto; X X /* go to the begining of the paragraph */ X gotobop(FALSE, 1); X curwp->w_doto = 0; /* force us to the begining of line */ X X /* and delete it */ X if ((status = killregion(FALSE, 1)) != TRUE) X return(status); X X /* and clean up the 2 extra lines */ X ldelete(2, TRUE); X } X return(TRUE); X} *-*-END-of-word.c-*-* exit