home *** CD-ROM | disk | FTP | other *** search
- From: wjh12!pixel!pixutl!chris
- Newsgroups: mod.sources
- Subject: updated window manager - wm
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 45
- Submitted by: wjh12!pixel!pixutl!chris
-
-
- Quite a while ago, Rob Jacob from NRL posted a window manager to the net.
- It sat on my machine for a long time until I decided to play with it.
- Eventually, I did. I enjoyed using it but I found some problems with it
- and starting modifying it. Later someone else here got interested too
- and we now have this version which we think is very nice. The list of
- modifications is at the top of 'wm.c'. The compile options are described
- in the makefile.
-
- This version runs on our systems, which run a mostly 4.1 kernel. It compiled
- on a 2.9 system, but ran very slowly. The main area that might cause problems
- on non 68K systems is the code included by the 'FAST' #define. 'wm' runs a
- lot faster if it is defined but that stuff is not necessarily portable (it
- doesn't work on the PDP, for example).
-
- Adapting it to 4.2 should require very little work and if someone does it and
- enjoys 'wm', I would appreciate getting the changes back. I would also like
- hearing about problems, bugs, improvements, etc...
-
- The archive contains the following files:
- Makefile
- read.c
- win.c
- wm.1
- wm.c
- wm.h
- This is a complete posting, not just the diff's because the changes are
- everywhere and it was ran through 'cb' very early.
-
- Warning: the format of the .wmrc file is different from that of the original
- version, mostly because the control character is saved from one session to the
- next so be sure to remove older .wmrc's or to used the '-' option on the first
- run, if you plan on using it.
-
- NOTE: This new version is posted with the authorization of the original author.
-
- ---------------------------- cut here -------------------------------
- echo 'sh - Makefile'
- sed 's/^X//' <<'________This_Is_The_END________' >>Makefile
- X#
- X# Note: Set NUMSUFFIX, PTYBASENAME, PTSBASENAME, PTFIRST, and PTLAST
- X# in wm.h according to the instructions there before compiling
- X#
- X# If REVVIDEO is defined, the windows will handle reverse video.
- X# If FAST is defined, some possibly non-portable routines will be used
- X# for string copy.
- X# If SHOWMAP is defined, the 'M' command will display the window layout.
- X# If SMOOTHIO is defined, programs that do a lot of cursor motions run
- X# smoother but hog system.
- X#
- X
- XCFLAGS=-O -DREVVIDEO -DSHOWMAP -DFAST -DSMOOTHIO
- XLDFLAGS=-n
- XOBJS=wm.o read.o win.o
- X
- Xall: wm
- X
- Xwm: ${OBJS}
- X cc $(LDFLAGS) -o wm wm.o read.o win.o -lcurses -ltermcap
- X
- X${OBJS}: wm.h
- X
- Xinstall: all
- X install -s wm ${DESTDIR}/usr/local/bin
- X
- Xclean:
- X rm -f *.o wm core a.out mon.out
- ________This_Is_The_END________
- echo 'sh - read.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>read.c
- X/*
- X * read.c R. Jacob
- X * This is the code that does all kinds of reading.
- X *
- X * Modified by Chris Bertin and Mike Tellier, October 1985.
- X */
- X
- X#include <stdio.h>
- X#include "wm.h" /* includes sgtty.h */
- X#include <signal.h>
- X
- X/*
- X * Old-fashioned blocking version of getchar
- X * But uses unbuffered system call read
- X * and strips parity bit
- X */
- Xbgetch(fildes)
- Xint fildes;
- X{
- X char c;
- X
- X if (read(fildes, &c, 1) <= 0)
- X return(EOF);
- X else
- X return((int)(c&0177));
- X}
- X
- X/*
- X * Returns the number of characters to be read.
- X */
- Xttychars(fildes)
- Xint fildes;
- X{
- X long int count;
- X
- X ioctl(fildes, FIONREAD, &count);
- X return(count);
- X}
- X
- X/*
- X * Key definitions used only by routine getpos
- X * These keys are used only for entering position of new window
- X */
- X# define RIGHTCHAR 'r'
- X# define UPCHAR 'u'
- X# define LEFTCHAR 'l'
- X# define DOWNCHAR 'd'
- X# define BIGRIGHTCHAR 'R' /* jump */
- X# define BIGUPCHAR 'U' /* one-fifth of the */
- X# define BIGLEFTCHAR 'L' /* way across */
- X# define BIGDOWNCHAR 'D' /* the screen */
- X# define EXECCHAR 'x'
- X
- X/*
- X * obtain a y, x position using UPCHAR, etc.
- X * and return it as integers *yptr and *xptr
- X * start off at position y0, x0
- X * Does not permit bottom (y = LINES - 1) line, as it is saved for messages
- X */
- Xgetpos(yptr, xptr, y0, x0)
- Xint *yptr, *xptr;
- Xregister int y0, x0;
- X{
- X register char c;
- X register int bigvert, bighoriz;
- X extern char cmdchar;
- X
- X bigvert = LINES / 5 + 1;
- X bighoriz = COLS / 5 + 1;
- X showcursor(y0, x0);
- X while ((c = bgetch(0)) != EXECCHAR) {
- X if (c == RIGHTCHAR)
- X x0 = MIN(x0 + 1, COLS - 1);
- X else if (c == UPCHAR)
- X y0 = MAX(y0 - 1, 0);
- X else if (c == LEFTCHAR)
- X x0 = MAX(x0 - 1, 0);
- X else if (c == DOWNCHAR)
- X y0 = MIN(y0 + 1, LINES - 2);
- X else if (c == BIGRIGHTCHAR)
- X x0 = MIN(x0 + bighoriz, COLS - 1);
- X else if (c == BIGUPCHAR)
- X y0 = MAX(y0 - bigvert, 0);
- X else if (c == BIGLEFTCHAR)
- X x0 = MAX(x0 - bighoriz, 0);
- X else if (c == BIGDOWNCHAR)
- X y0 = MIN(y0 + bigvert, LINES - 2);
- X else if (c == cmdchar || c == 'q') {
- X showmsg("");
- X return(1);
- X }
- X showcursor(y0, x0);
- X }
- X *xptr = x0;
- X *yptr = y0;
- X return(0);
- X}
- ________This_Is_The_END________
- echo 'sh - win.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>win.c
- X/*
- X * win.c R. Jacob
- X * This is the code for manipulating the window and curses data structures
- X *
- X * Modified by Chris Bertin and Mike Tellier, October 1985.
- X */
- X
- X#include "wm.h"
- X#include <ctype.h>
- X
- Xmap_t *winmap;
- X
- Xinit() {}
- Xcloseup() {}
- X
- X/*
- X * create byte-mapped top window image.
- X */
- Xmakemap()
- X{
- X register struct win_struct *wsp;
- X register x, y, n, atlast;
- X register map_t *cp;
- X char c, lastc;
- X
- X#ifdef FAST
- X zero(winmap, LINES * COLS * sizeof *winmap);
- X#else
- X for (y = LINES * COLS; --y >= 0; )
- X winmap[y] = 0;
- X#endif
- X for (wsp = topw->prev, atlast = 0; atlast == 0; wsp = wsp->prev) {
- X atlast = (wsp == topw);
- X if (wsp->flags & WERASED)
- X continue;
- X mapwindow(wsp->boxleft, wsp->id, 1);
- X mapwindow(wsp->boxright, wsp->id, 1);
- X mapwindow(wsp->boxtop, wsp->id, 0);
- X mapwindow(wsp->boxbot, wsp->id, 0);
- X mapwindow(wsp->wptr, wsp->id, 0);
- X }
- X for (y = LINES - 1; y >= 0; y--) {
- X cp = &winmap[y * COLS] + COLS - 1;
- X for (n = 0, lastc = 0, c = 0, x = 0; x < COLS; x++, cp--) {
- X if ((c = mapchar(*cp)) != 0
- X#ifdef FAST
- X && (maptocount(*cp) == 0)
- X#endif
- X ) {
- X if (c != lastc) {
- X n = 0;
- X lastc = c;
- X }
- X#ifdef FAST
- X *cp = chartomap(c, ++n);
- X#else
- X *cp = c;
- X#endif
- X }
- X }
- X }
- X}
- X
- X/*
- X * Map window onto byte-mapped image
- X */
- Xmapwindow(wp, id, flag)
- Xregister WINDOW *wp;
- Xchar id;
- X{
- X register x, y;
- X register map_t *cp;
- X
- X if (wp == NULL)
- X return;
- X for (y = wp->_begy; y < wp->_maxy + wp->_begy; y++) {
- X cp = &winmap[y * COLS];
- X for (x = wp->_begx; x < wp->_maxx + wp->_begx; x++)
- X#ifdef FAST
- X cp[x] = chartomap(id, flag);
- X#else
- X cp[x] = id;
- X#endif
- X }
- X}
- X
- X/*
- X * make wsp the top window by changing topw and adjusting linked list
- X */
- Xchgwin(wsp)
- Xregister struct win_struct *wsp;
- X{
- X if (wsp == topw)
- X return;
- X wsp->flags &= ~WERASED;
- X wsp->flags |= WTOUCHED;
- X if (wsp->next) {
- X wsp->prev->next = wsp->next;
- X wsp->next->prev = wsp->prev;
- X }
- X if (topw) {
- X wsp->next = topw;
- X wsp->prev = topw->prev;
- X topw->prev = wsp;
- X wsp->prev->next = wsp;
- X }
- X else
- X wsp->next = wsp->prev = wsp;
- X topw = wsp;
- X makemap();
- X}
- X
- X#define doscroll(w) scrollok(w, TRUE), scroll(w), scrollok(w, FALSE), wmove(w, w->_maxy - 1, w->_curx)
- X/*
- X * Add character c to window wsp and to corresponding virtual window
- X * and interpret virtual terminal commands
- X */
- Xadd(wsp, c)
- Xstruct win_struct *wsp;
- Xchar c;
- X{
- X register WINDOW *wp, *vp;
- X register wpy, wpx, vpy, vpx;
- X int doit, moveit;
- X
- X wp = wsp->wptr;
- X vp = wsp->virt;
- X getyx(wp, wpy, wpx);
- X getyx(vp, vpy, vpx);
- X doit = FALSE;
- X moveit = FALSE;
- X
- X if (wsp->pend[0] == CODE && wsp->pend[1] == 'Y') { /* cursor motion */
- X if (wsp->pend[2] != '\0') { /* ESC-Y-pos */
- X wpy = vpy = (int)(wsp->pend[2] - ' ');
- X wpx = vpy = (int)(c - ' ');
- X moveit = TRUE;
- X wsp->pend[0] = '\0';
- X }
- X else {
- X wsp->pend[2] = c;
- X wsp->pend[3] = '\0';
- X return;
- X } /* ESC-Y */
- X }
- X else if (wsp->pend[0] == CODE) { /* ESC */
- X#ifdef SMOOTHIO
- X wsp->flags |= WTOUCHED;
- X repaint(wsp);
- X#endif
- X if (c == 'Y') {
- X wsp->pend[1] = c;
- X wsp->pend[2] = '\0';
- X }
- X else if (c == 'K') {
- X wclrtoeol(wp);
- X wclrtoeol(vp);
- X wsp->pend[0] = '\0';
- X }
- X else if (c == 'S') {
- X werase(wp);
- X werase(vp);
- X wpx = vpx = 0;
- X wpy = vpy = 0;
- X moveit = TRUE;
- X wsp->pend[0] = '\0';
- X }
- X else if (c == 'C') {
- X wpx++;
- X vpx++;
- X moveit = TRUE;
- X wsp->pend[0] = '\0';
- X }
- X else if (c == 'A') {
- X wpy--;
- X vpy--;
- X moveit = TRUE;
- X wsp->pend[0] = '\0';
- X }
- X#ifdef REVVIDEO
- X else if (c == 'O') {
- X wstandout(wp);
- X wstandout(vp);
- X wsp->pend[0] = '\0';
- X }
- X else if (c == 'E') {
- X wstandend(wp);
- X wstandend(vp);
- X wsp->pend[0] = '\0';
- X }
- X#endif
- X else {
- X doit = TRUE;
- X wsp->pend[0] = '\0';
- X }
- X }
- X else if (c == CODE) {
- X wsp->pend[0] = c;
- X wsp->pend[1] = '\0';
- X }
- X else
- X doit = TRUE;
- X if (moveit || !doit) {
- X if (wpx < 0)
- X wpx = 0;
- X else if (wpx >= wp->_maxx)
- X wpx = wp->_maxx - 1;
- X if (wpy < 0)
- X wpy = 0;
- X else if (wpy >= wp->_maxy)
- X wpy = wp->_maxy - 1;
- X wmove(wp, wpy, wpx);
- X if (vpx < 0)
- X vpx = 0;
- X else if (vpx >= vp->_maxx)
- X vpx = vp->_maxx - 1;
- X if (vpy < 0)
- X vpy = 0;
- X else if (vpy >= vp->_maxy)
- X vpy = vp->_maxy - 1;
- X wmove(vp, vpy, vpx);
- X return;
- X }
- X if (c == '\007') {
- X showmsg(" ");
- X showmsg("");
- X showmsg("Bell");
- X return;
- X }
- X else if (c == '\b') {
- X if (wp->_curx > 0)
- X wp->_curx--;
- X if (vp->_curx > 0)
- X vp->_curx--;
- X }
- X else if (c == '\r') {
- X wp->_curx = 0;
- X vp->_curx = 0;
- X }
- X else if (c == '\n') {
- X wp->_cury++;
- X if (wp->_cury >= wp->_maxy)
- X doscroll(wp);
- X vp->_cury++;
- X if (vp->_cury >= vp->_maxy)
- X doscroll(vp);
- X if (wsp == topw || wp->_cury == wp->_maxy - 1) {
- X wsp->flags |= WTOUCHED;
- X repaint(wsp);
- X }
- X }
- X else if (isprint(c) || c == ' ' || c == '\t') {
- X int corner = (wp->_curx == wp->_maxx - 1) &&
- X (wp->_cury == wp->_maxy - 1);
- X waddch(wp, c);
- X waddch(vp, c);
- X if (corner) {
- X add(wsp, '\n');
- X wmove(wp, wp->_cury, 0);
- X wmove(vp, vp->_cury, 0);
- X }
- X }
- X else if (c != '\0') {
- X if (c < '\040')
- X c += 0100;
- X else if (c == '\177')
- X c = '?';
- X waddch(wp, '^');
- X waddch(vp, '^');
- X waddch(wp, c);
- X waddch(vp, c);
- X }
- X}
- X
- X/*
- X * Creates up to 4 windows making a box to surround window wsp and puts
- X * pointer to the new windows into proper places in global win[].
- X * Sets WFULLSCREEN if applicable.
- X */
- Xsetupbox(wsp)
- Xstruct win_struct *wsp;
- X{
- X WINDOW *wp;
- X int top, bot, left, right;
- X int begx, begy, maxx, maxy;
- X int i;
- X
- X wp = wsp->wptr; /* just to save typing */
- X begx = wp->_begx;
- X begy = wp->_begy;
- X maxx = wp->_maxx;
- X maxy = wp->_maxy;
- X wsp->boxtop = wsp->boxleft = wsp->boxright = wsp->boxbot = 0;
- X left = (begx > 0)? TRUE: FALSE;
- X top = (begy > 0)? TRUE: FALSE;
- X right = (begx+maxx < COLS)? TRUE: FALSE;
- X bot = (begy+maxy < LINES - 1)? TRUE: FALSE;
- X if (top)
- X begy--, maxy++;
- X if (bot)
- X maxy++;
- X if (left)
- X begx--, maxx++;
- X if (right)
- X maxx++;
- X if (top) {
- X wsp->boxtop = newwin(1, maxx, begy, begx);
- X wsp->boxtop->_flags = 0; /* get around curses bug */
- X leaveok(wsp->boxtop, TRUE);
- X for (i = 0; i < maxx; i++)
- X waddch(wsp->boxtop, wsp->id);
- X begy++;
- X maxy--;
- X }
- X if (left) {
- X wsp->boxleft = newwin(maxy, 1, begy, begx);
- X wsp->boxleft->_flags = 0; /* get around curses bug */
- X leaveok(wsp->boxleft, TRUE);
- X for (i = 0; i < maxy - 1; i++)
- X waddch(wsp->boxleft, '|');
- X waddch(wsp->boxleft, wsp->id);
- X begx++;
- X maxx--;
- X }
- X if (right) {
- X wsp->boxright = newwin(maxy, 1, begy, maxx+begx - 1);
- X wsp->boxright->_flags = 0; /* get around curses bug */
- X leaveok(wsp->boxright, TRUE);
- X for (i = 0; i < maxy - 1; i++)
- X waddch(wsp->boxright, '|');
- X waddch(wsp->boxright, wsp->id);
- X maxx--;
- X }
- X if (bot) {
- X wsp->boxbot = newwin(1, maxx, maxy+begy - 1, begx);
- X wsp->boxbot->_flags = 0; /* get around curses bug */
- X leaveok(wsp->boxbot, TRUE);
- X for (i = 0; i < maxx; i++)
- X waddch(wsp->boxbot, '-');
- X }
- X if ((top | bot | right | left) == 0)
- X wsp->flags |= WFULLSCREEN;
- X else
- X wsp->flags &= ~WFULLSCREEN;
- X}
- X
- X/*
- X * Clear the screen and then repaint all windows
- X */
- Xrepaintall()
- X{
- X register struct win_struct *wsp;
- X int atlast;
- X
- X ttyclear();
- X makemap();
- X wsp = (topw->flags & WFULLSCREEN)? topw: topw->prev;
- X for (atlast = 0; atlast == 0; wsp = wsp->prev) {
- X atlast = (wsp == topw);
- X if (wsp->boxtop)
- X touchwin(wsp->boxtop);
- X if (wsp->boxbot)
- X touchwin(wsp->boxbot);
- X if (wsp->boxleft)
- X touchwin(wsp->boxleft);
- X if (wsp->boxright)
- X touchwin(wsp->boxright);
- X touchwin(wsp->wptr);
- X wsp->flags |= WTOUCHED;
- X repaint(wsp);
- X }
- X}
- X
- X/*
- X * Repaint window wsp
- X */
- Xrepaint(wsp)
- Xregister struct win_struct *wsp;
- X{
- X if ((wsp->flags & WERASED) || (wsp->flags & WTOUCHED) == 0 ||
- X ((wsp != topw) && (topw->flags & WFULLSCREEN)))
- X return;
- X wcopy(wsp->boxleft, wsp->id);
- X wcopy(wsp->boxright, wsp->id);
- X wcopy(wsp->boxtop, wsp->id);
- X wcopy(wsp->boxbot, wsp->id);
- X wcopy(wsp->wptr, wsp->id);
- X wsp->flags &= ~WTOUCHED;
- X refresh();
- X}
- X
- X/*
- X * Copy window image into byte-mapped top window
- X */
- Xwcopy(win, id)
- Xregister WINDOW *win;
- Xregister char id;
- X{
- X register char *screen;
- X register map_t *map;
- X register count, x, y, bx, by, my;
- X
- X if (win == NULL)
- X return;
- X bx = win->_begx;
- X by = win->_begy;
- X my = win->_maxy;
- X for (y = 0; y < my; y++) {
- X if ((x = win->_firstch[y]) == _NOCHANGE)
- X continue;
- X screen = &stdscr->_y[y + by][x + bx];
- X map = &winmap[(y + by) * COLS + x + bx];
- X for (; x <= win->_lastch[y]; x++, screen++, map++) {
- X if (mapchar(*map) != id)
- X continue;
- X if (stdscr->_firstch[y + by] == _NOCHANGE) {
- X stdscr->_firstch[y + by] = x + bx;
- X stdscr->_lastch[y + by] = x + bx;
- X }
- X if (stdscr->_firstch[y + by] > x + bx)
- X stdscr->_firstch[y + by] = x + bx;
- X#ifdef FAST
- X if ((count = maptocount(*map)) > 1) {
- X bcopy(&win->_y[y][x], screen, count);
- X x += count - 1;
- X screen += count - 1;
- X map += count - 1;
- X } else
- X#endif
- X *screen = win->_y[y][x];
- X if (stdscr->_lastch[y + by] < x + bx)
- X stdscr->_lastch[y + by] = x + bx;
- X }
- X }
- X}
- X
- X/*
- X * show message at bottom of screen
- X */
- Xshowmsg(s)
- Xchar *s;
- X{
- X extern msg;
- X int l = strlen(s);
- X extern WINDOW *msgwin;
- X
- X wclear(msgwin);
- X wmove(msgwin, 0, 0);
- X wstandout(msgwin);
- X wprintw(msgwin, "%s", s);
- X overwrite(msgwin, stdscr);
- X refresh();
- X showcursor(msgwin->_begy, msgwin->_begx + l + 1);
- X msg = l > 0;
- X}
- X
- X#ifdef FAST
- X/*
- X * copy 'count' bytes from 'from' to 'to'. (optimized)
- X */
- Xbcopy(from, to, count)
- Xregister char *from, *to;
- Xregister count;
- X{
- X register c1;
- X
- X if ((((int)to ^ (int)from) & 1) == 0) {
- X if ((int)to & 1) {
- X count--;
- X *to++ = *from++;
- X }
- X c1 = count >> 2;
- X while (--c1 >= 0)
- X *(long *) to++ = *(long *) from++;
- X count &= 3;
- X }
- X while (--count >= 0)
- X *to++ = *from++;
- X}
- X
- X/*
- X * zero 'count' bytes in 'str'. (optimized)
- X */
- Xzero(str, count)
- Xregister char *str;
- Xregister count;
- X{
- X register c1;
- X
- X if ((int)str & 1) {
- X count--;
- X *str++ = 0;
- X }
- X c1 = count >> 2;
- X while (--c1 >= 0)
- X *(long *) str++ = 0L;
- X count &= 3;
- X while (--count >= 0)
- X *str++ = 0;
- X}
- X#endif
- ________This_Is_The_END________
- echo 'sh - wm.1'
- sed 's/^X//' <<'________This_Is_The_END________' >>wm.1
- X.TH WM 1 wm.v42.1
- X.SH NAME
- Xwm \- window manager
- X.SH SYNOPSIS
- X.B wm
- X[ \- ]
- X.SH DESCRIPTION
- X.I Wm
- Xmanages a collection of windows on a display terminal.
- X.PP
- XIt determines what type of terminal you are using from
- Xthe environment parameter $TERM
- X(see
- X.IR environ (5))
- Xand then uses
- X.IR curses (3)
- Xto adapt to it.
- X.PP
- XEach window has its own UNIX shell
- X.IR sh (1),
- Xrunning in parallel with those in the other windows.
- XThe idea behind this scheme is that you can use each window
- Xfor a series of commands dealing with a single topic.
- XThen, you can change back and forth between the windows without
- Xlosing your place in any of them.
- X.PP
- XAt any time, you can give commands to change the window you are typing in,
- Xto move a window or change its size,
- Xor to create or kill a window.
- XWindows can overlap or completely obscure one another;
- Xobscured windows can subsequently be "lifted" up
- Xand placed on top of the other windows.
- X.PP
- XWhen the program is started,
- Xit will attempt to restore the sizes and positions of the windows
- Xand the control character
- Xin use when you last ran
- X.IR wm .
- XFailing that (or if you give the optional argument \- ),
- Xit will ask you to indicate
- Xthe size and position of the first window.
- XTo do this, move the cursor to the position you want the
- Xlower left corner of your window
- Xto occupy,
- Xusing the keys
- X.B u
- X(up),
- X.B d
- X(down),
- X.B l
- X(left), and
- X.B r
- X(right)
- Xand also
- X.BR U ,
- X.BR D ,
- X.BR L ,
- Xand
- X.B R
- X(for large increments in the respective directions).
- XThen type an
- X.BR x .
- XThen move the cursor (using the same commands) to the upper
- Xright corner, and type another
- X.BR x .
- XNow, you can type UNIX commands in the new window.
- X.PP
- X.I Wm
- Xcommands can be issued at any time.
- XEvery
- X.I wm
- Xcommand consists of a prefix character followed by one
- Xmore character, possibly followed by some arguments.
- XAny other characters typed on the terminal are treated as input
- Xto the program in the current window.
- XTo enter the prefix character itself as input to a program, type it twice.
- XThe prefix character is initially set to ASCII ESC, but can be changed
- Xwith the
- X.I C
- Xcommand. All commands can be interrupted by typing another prefix
- Xcharacter or a
- X.I q .
- X.PP
- XThe available
- X.I wm
- Xcommands are prefix character (ESC) followed by:
- X.IP \fBn\fP
- XCreate a new window.
- X.I Wm
- Xwill ask for the lower left and upper right corners,
- Xusing the same convention described above for creating the first window.
- X.IP \fBc\fP
- XChange the current window.
- XEnter the name (lower-case
- X.BR a ,
- X.BR b ,
- X.BR c ,
- Xetc.) of the
- Xwindow to which you want to change.
- XThe window names are shown in the top row of each window.
- XThe chosen window is placed on "top" of the screen
- X(that is, in front any other windows had been obscuring it).
- XInput from the keyboard will now be sent to this window.
- X(Delayed responses to commands entered in other windows will,
- Xof course, continue to be routed to their correct windows.)
- X.IP \fBl\fP
- XChange to the last-used window.
- XChange back to the window that had most recently been the current window.
- X.IP \fBm\fP
- XMove and/or change the size of a window.
- X.I Wm
- Xasks for the window name (same convention as for changing current window)
- Xand then for the lower left and upper right corners of desired
- Xnew position of the window (same convention as for the first window).
- XIf you enlarge a window, material that had scrolled off the top or been
- Xtruncated at the right margin will become visible again.
- XIt is not advisable to move a window except when
- Xthe program running in it is at the shell prompt level.
- X.IP \fBe\fP
- XErase the named window from the screen.
- XThe window still exists, any pending processing continues in it
- Xinvisibly, and it can be seen again with the change window command.
- X.IP \fBk\fP
- XKill the named window.
- XPermanently kills the processes associated with the window
- Xand erases the window.
- X(The
- X.I name
- Xof this window may later be re-used in creating a new window.)
- X.IP \fBC\fP
- XChange the prefix character.
- X.IP \fBr\fP
- XRedraw the screen.
- XClears the entire screen and redraws what should be there.
- XHelpful after garbage (like a broadcast message) has arrived.
- X.IP \fBp\fP
- XScroll to the top of a new page in the current window.
- XMaterial in a window is normally scrolled, one line at a time.
- XThis command forces the window to scroll forward by a distance equal
- Xto the height of the window, thereby clearing the window.
- X.IP "\fBq\fP or \fBQ\fP"
- XQuit.
- XThis stops all processes associated with
- X.I wm
- Xand exits. If
- X.I Q
- Xis used, the
- X.I .wmrc
- Xfile is not updated.
- X.IP \fBz\fP
- XSuspend
- X.I wm
- Xusing the Berkeley job control system.
- XThis should only be done if
- X.I wm
- Xitself was run from a shell that handles job control, i.e. from
- X.IR csh (1),
- Xrather than from the standard
- X.IR sh (1).
- X.IP \fBL\fP
- XList the windows. The level (top first), name, shell's pid, virtual
- Xdevice, coordinates, lines, columns and state are displayed.
- X.IP \fBM\fP
- XDisplay the map.
- X.IP "\fBh\fP or \fB?\fP"
- XHelp.
- XDisplays a summary of
- X.I wm
- Xcommands.
- X.PP
- XIt is also possible to send data from one window to another.
- XEach window is associated with the file name
- X.B Window?
- Xin the directory from which
- X.I wm
- Xwas run
- X(where the
- X.B ?
- Xis replaced by
- X.BR a ,
- X.BR b ,
- X.BR c ,
- Xetc. for the particular windows).
- XData sent to those file names will appear in the respective
- Xwindows, and data read from those file names will be taken from
- Xsubsequent keyboard input to those windows.
- X(If real files by those names already exist, this feature will
- Xbe disabled.)\
- X.SH FILES
- X.IP $HOME/.wmrc 20
- Xis used to save the arrangement of your
- Xwindows from one run to the next.
- X.IP /dev/vt[sc]? 20
- Xare the virtual terminals.
- X.SH BUGS
- XSome programs assume that their output devices are at
- Xleast some minimum size;
- Xthey will not run well in small windows.
- XAlso, programs that attempt to manipulate the controlling
- Xterminals of process groups will not work properly under
- X.IR wm .
- XFor this reason,
- X.IR csh (1)
- Xcannot be run in the individual windows instead of
- X.IR sh (1).
- X.PP
- XEach window emulates a cursor-control terminal,
- Xbut the emulation is provided largely by
- X.IR curses ,
- Xand it does not always do the same thing that a real terminal
- Xwould do or that a program expects.
- X.PP
- XBecause of a deficiency in the virtual terminal driver in
- Xhandling interrupt characters, the
- X.I interrupt
- Xand
- X.I quit
- Xkeyboard characters always send their
- Xrespective signals to the program in the current window,
- Xregardless of whether that program changed the definitions of
- Xthe keys or not.
- XThus, the program cannot re-map the keys,
- Xeven if it has set raw mode,
- Xbut it can still catch the signal
- Xitself (as is usually done), rather than the character.
- X.PP
- XPrograms that do a lot of character I/O have make every other
- Xwindow run slow.
- X.SH "SEE ALSO"
- XR.J.K. Jacob,
- X"User-Level Window Managers for UNIX,"
- X.I "Proc. UniForum International Conference on UNIX"
- X(January, 1984).
- X.SH AUTHORS
- XRobert J.K. Jacob, Naval Research Laboratory
- X.br
- XChris Bertin and Mike Tellier, Pixel Systems Inc.
- ________This_Is_The_END________
- echo 'sh - wm.c'
- sed 's/^X//' <<'________This_Is_The_END________' >>wm.c
- X/*
- X * wm.c R. Jacob 7/28/1980
- X * Simple multiple-window monitor for Unix -- allows windows to overlap
- X *
- X * This is the code for the main program.
- X * This version runs as only one process (plus the shells)
- X * This is intended for Berkeley Unix with virtual tty's only.
- X *
- X * Modified by Chris Bertin and Mike Tellier, October 1985.
- X * Major changes:
- X * - Use a byte-mapped screen image to keep track of which portions
- X * of the windows should be displayed. This eliminates the jumping
- X * from one window to another when updating hidden portions.
- X * - Read's from virtual tty's are now buffered. This assumes that
- X * your kernel has 'FIONREAD' fixed for virtual tty's.
- X * - Window structures are now a doubly linked list for quicker scans.
- X * - Improved handling of the message window.
- X * - Reverse video handled in windows.
- X * - Improved user interface (Command are now interruptible by a 'q'
- X * or by typing another command character, for example).
- X * - Lines wrap around inside the windows which means you always get
- X * the full output.
- X * - VI's behaviour improved inside windows.
- X * - The command character can be passed to the window's process by
- X * typing it twice.
- X * - The command character is saved from in the .wmrc file.
- X * - New commands: 'Q', 'L' and 'M'. See #define's below or manual.
- X * - WMRC now an environment variable.
- X */
- X
- X#include <signal.h>
- X#include <stdio.h>
- X#include <curses.h>
- X#include <ctype.h>
- X#include "wm.h"
- X
- X/*
- X * Command definitions
- X */
- X# define NEWWINDOW 'n' /* make New window */
- X# define CHGWINDOW 'c' /* Change to another window */
- X# define LASTWINDOW 'l' /* change to Last-used window */
- X# define PAGE 'p' /* Page (vs scroll) the window */
- X# define MOVEWINDOW 'm' /* Move locn and/or change size of window */
- X# define ERASEWINDOW 'e' /* but it can reappear */
- X# define KILLWINDOW 'k' /* get rid of this window forever */
- X# define REDRAW 'r' /* Redraw all windows */
- X# define HELP1 '?' /* Command summary */
- X# define HELP2 'h' /* Command summary */
- X# define SUSPEND 'z' /* suspend wm */
- X# define QUIT 'q' /* close up everything and Quit */
- X# define EXIT 'Q' /* QUIT but exit without updating .wmrc */
- X# define CHGCODE 'C' /* change command character */
- X# define LIST 'L' /* list windows */
- X# ifdef SHOWMAP
- X# define MAP 'M' /* display map */
- X# endif
- X
- X# define DEFCMD '\033' /* default control character */
- X# define INCR 500
- X# define NOWIN (struct win_struct *)0
- X# define RDBSIZE 128
- X# define pause() showmsg("Hit any character to return to WM"),bgetch(0);
- X# define interrupt(sig) ioctl(topw->pty, TIOCFLUSH, 0), killpg(topw->pid, sig)
- X# define setalarm() rcount = 1, signal(SIGALRM, gotalarm), alarm(1)
- X# define freespace(wsp) { if (wsp->buf) free(wsp->buf); free(wsp); }
- X
- Xchar cmdchar = DEFCMD;
- X
- X/*
- X * Real declarations for stuff defined as extern in wm.h
- X */
- Xstruct win_struct *topw, *askwpnt(), *getwpnt();
- X
- Xchar *ptslinkname();
- XWINDOW *msgwin;
- X
- Xchar shellpgm[100], shellname[20], wmrc[100];
- Xstruct sgttyb sgttybuf;
- Xstruct tchars tcharsbuf;
- Xstruct ltchars ltcharsbuf;
- Xint ttymode, ttydisc, timetoquit, nowmrc, rcount, msg;
- X
- Xgotalarm()
- X{
- X signal(SIGALRM, gotalarm);
- X rcount = 0;
- X}
- X
- Xmain(argc)
- Xint argc;
- X{
- X register int alive, atlast, count, x, y;
- X register struct win_struct *wsp;
- X register char *pnt;
- X register WINDOW *wp;
- X FILE *file;
- X char intrc, quitc, c, buf[LINEBUF], *cp;
- X struct sw_buf savewin;
- X
- X init();
- X#ifdef CSHWORKS /* for now force user to use sh cause csh doesn't work */
- X if ((cp = getenv("SHELL")) == (char *)0)
- X strcpy(shellpgm, "sh");
- X else
- X strcpy(shellpgm, cp);
- X if ((cp = rindex(shellpgm,'/')) == (char *)0)
- X strcpy(shellname, shellpgm);
- X else
- X strcpy(shellname, &cp[1]);
- X#else
- X strcpy(shellpgm, "sh");
- X strcpy(shellname, "sh");
- X#endif
- X ioctl(0, TIOCGETD, &ttydisc);
- X gtty(0, &sgttybuf);
- X ioctl(0, TIOCGETC, &tcharsbuf);
- X ioctl(0, TIOCLGET, &ttymode);
- X ioctl(0, TIOCGLTC, <charsbuf);
- X intrc = tcharsbuf.t_intrc;
- X quitc = tcharsbuf.t_quitc;
- X initscr();
- X if ((winmap = (map_t *)malloc(LINES * COLS * sizeof (map_t))) == NULL) {
- X fprintf(stderr, "Can't allocate memory\n");
- X endwin();
- X exit(2);
- X }
- X noecho();
- X raw();
- X msgwin = newwin(1, 0, LINES - 1, 0);
- X msgwin->_flags = 0; /* to get around bug in curses */
- X firstwindow(argc);
- X strcpy(buf, "Ready");
- X if (cmdchar != DEFCMD)
- X sprintf(&buf[strlen(buf)], " (command character is '\\%04o')",
- X cmdchar);
- X showmsg(buf);
- X timetoquit = FALSE;
- X alive = INCR;
- X while (!timetoquit) {
- X for (atlast = 0, wsp = topw; atlast == 0; wsp = wsp->next) {
- X while (ttychars(0)) {
- X alive = INCR;
- X setalarm();
- X c = bgetch(0);
- X alarm(0);
- X if (rcount == 0 || c <= 0)
- X break;
- X if (c == cmdchar && docmd() != cmdchar)
- X break;
- X if (msg-- == 1)
- X showmsg("");
- X /*
- X * We fake quit and interrupt here, since just
- X * sending the characters on the pty doesn't do.
- X * But don't change your intr or quit chars
- X * inside a window!
- X */
- X if (c == intrc)
- X interrupt(SIGINT);
- X else if (c == quitc)
- X interrupt(SIGQUIT);
- X else
- X write(topw->pty, &c, 1);
- X }
- X atlast = (wsp->next == topw);
- X if ((count = ttychars(wsp->pty)) == 0)
- X continue;
- X setalarm();
- X rcount = read(wsp->pty, wsp->buf, MIN(count, RDBSIZE));
- X alarm(0);
- X if (rcount <= 0)
- X continue;
- X wsp->flags |= WTOUCHED;
- X pnt = wsp->buf;
- X while(rcount-- > 0)
- X add(wsp, *pnt++);
- X alive = INCR * 2;
- X if (wsp != topw)
- X repaint(wsp);
- X topw->flags |= WTOUCHED;
- X }
- X if (topw->flags & WTOUCHED)
- X repaint(topw);
- X getyx(topw->wptr, y, x);
- X showcursor(y + topw->wptr->_begy, x + topw->wptr->_begx);
- X if (alive-- < 0)
- X sleep(1);
- X }
- X showmsg("");
- X showcursor(LINES - 1, 0);
- X if (!nowmrc && (file = fopen(wmrc, "w")) != NULL) {
- X for (atlast=0, wsp = topw->prev; atlast == 0; wsp = wsp->prev) {
- X atlast = (wsp == topw);
- X wp = wsp->wptr;
- X savewin.sw_begline = wp->_begy;
- X savewin.sw_begcol = wp->_begx;
- X savewin.sw_lines = wp->_maxy;
- X savewin.sw_cols = wp->_maxx;
- X savewin.sw_cmdchar = cmdchar;
- X fwrite(&savewin, sizeof(savewin), 1, file);
- X }
- X }
- X for (atlast = 0, wsp = topw; atlast == 0; wsp = wsp->next) {
- X atlast = (wsp->next == topw);
- X close(wsp->pty);
- X if (wsp->flags & WPTSLINK)
- X unlink(ptslinkname(wsp->id));
- X if (wsp->pid != 0) {
- X killpg(wsp->pid, SIGHUP);
- X kill(wsp->pid, SIGTERM);
- X }
- X }
- X closeup();
- X endwin();
- X}
- X
- X/*
- X * docmd() handles commands and returns the character it reads so that
- X * the control character can be passed on to the windows.
- X */
- Xdocmd()
- X{
- X register struct win_struct *wsp;
- X register char c;
- X char buf[LINEBUF];
- X int begline, begcol, lines, cols, savey, savex, y, x, x1, y1, x2, y2;
- X register l, lmax;
- X
- X showmsg("Command?");
- X c = bgetch(0);
- X showmsg("");
- X switch(c) {
- X
- X case NEWWINDOW:
- X showmsg("Move to lower left, then type x");
- X if (getpos(&y1, &x1, LINES-2, 0))
- X break;
- X showmsg("Move to upper right, then type x");
- X if (getpos(&y2, &x2, y1, x1))
- X break;
- X begline = y2;
- X begcol = x1;
- X lines = y1 - y2 + 1;
- X cols = x2 - x1 + 1;
- X if (lines > 0 && cols > 0) {
- X if (makewin(lines, cols, begline, begcol)) {
- X repaintall();
- X showmsg("Created new window");
- X }
- X else
- X showmsg("Can't create another shell");
- X }
- X else
- X showmsg("That's an impossible window size");
- X break;
- X
- X case CHGWINDOW:
- X if ((wsp = askwpnt("Change to", 0)) == NOWIN || wsp == topw)
- X break;
- X chgwin(wsp);
- X repaintall();
- X showmsg("Changing windows");
- X break;
- X
- X case LASTWINDOW:
- X if ((wsp = topw->next) == topw)
- X showmsg("No last window");
- X else {
- X chgwin(wsp);
- X repaintall();
- X showmsg("Changing windows");
- X }
- X break;
- X
- X case PAGE:
- X showmsg("Page");
- X getyx(topw->wptr, savey, savex);
- X lmax = savey;
- X wmove(topw->wptr, 0, 0);
- X for (l = 0; l < lmax; l++)
- X wdeleteln(topw->wptr);
- X wmove(topw->wptr, savey - lmax, savex);
- X getyx(topw->virt, savey, savex);
- X wmove(topw->virt, 0, 0);
- X for (l = 0; l < lmax; l++)
- X wdeleteln(topw->virt);
- X wmove(topw->virt, savey - lmax, savex);
- X topw->flags |= WTOUCHED;
- X repaint(topw);
- X break;
- X
- X case MOVEWINDOW:
- X if ((wsp = askwpnt("Move", 1)) == NOWIN)
- X break;
- X showmsg("Move to new lower left, then type x");
- X if (getpos(&y1, &x1, LINES-2, 0))
- X break;
- X showmsg("Move to new upper right, then type x");
- X if (getpos(&y2, &x2, y1, x1))
- X break;
- X begline = y2;
- X begcol = x1;
- X lines = y1 - y2 + 1;
- X cols = x2 - x1 + 1;
- X if (lines > 0 && cols > 0) {
- X int haslink = wsp->flags & WPTSLINK;
- X getyx(wsp->wptr, savey, savex);
- X savey = wsp->wptr->_maxy - savey;
- X delwin(wsp->wptr);
- X if (wsp->boxbot != 0)
- X delwin(wsp->boxbot);
- X if (wsp->boxtop != 0)
- X delwin(wsp->boxtop);
- X if (wsp->boxleft != 0)
- X delwin(wsp->boxleft);
- X if (wsp->boxright != 0)
- X delwin(wsp->boxright);
- X wsp->wptr = newwin(lines, cols, begline, begcol);
- X wsp->wptr->_flags = 0; /* get around curses bug */
- X for (y = 0; y < wsp->wptr->_maxy; y++) {
- X for (x = 0; x < wsp->wptr->_maxx; x++){
- X wmove(wsp->wptr, y, x);
- X wmove(wsp->virt, y + wsp->virt->_maxy - wsp->wptr->_maxy, x);
- X waddch(wsp->wptr, winch(wsp->virt));
- X }
- X }
- X if (haslink)
- X wsp->flags |= WPTSLINK;
- X wmove(wsp->virt, MAX(wsp->virt->_maxy - savey, 0),
- X savex);
- X wmove(wsp->wptr, MAX(wsp->wptr->_maxy - savey, 0),
- X savex);
- X ttyclear();
- X setupbox(wsp);
- X setenv(wsp);
- X makemap();
- X repaintall();
- X showmsg("Moving the window");
- X }
- X else
- X showmsg("That's an impossible window size");
- X break;
- X
- X case ERASEWINDOW:
- X if ((wsp = askwpnt("Erase", 0)) == NOWIN)
- X break;
- X if (wsp == topw)
- X showmsg("Can't erase the top window");
- X else {
- X wsp->flags |= WERASED;
- X ttyclear();
- X repaintall();
- X showmsg("Erasing");
- X }
- X break;
- X
- X case KILLWINDOW:
- X if ((wsp = askwpnt("Kill", 0)) == NOWIN)
- X break;
- X if (wsp == topw)
- X showmsg("Can't kill the top window");
- X else {
- X delwin(wsp->wptr);
- X delwin(wsp->virt);
- X if (wsp->boxbot != 0)
- X delwin(wsp->boxbot);
- X if (wsp->boxtop != 0)
- X delwin(wsp->boxtop);
- X if (wsp->boxleft != 0)
- X delwin(wsp->boxleft);
- X if (wsp->boxright != 0)
- X delwin(wsp->boxright);
- X if (wsp->flags & WPTSLINK)
- X unlink(ptslinkname(wsp->id));
- X close(wsp->pty);
- X if (wsp->pid != 0) {
- X killpg(wsp->pid, SIGHUP);
- X kill(wsp->pid, SIGKILL);
- X }
- X wsp->prev->next = wsp->next;
- X wsp->next->prev = wsp->prev;
- X freespace(wsp);
- X makemap();
- X ttyclear();
- X repaintall();
- X showmsg("Killing the window");
- X }
- X break;
- X
- X case REDRAW:
- X repaintall();
- X showmsg("Redrawing");
- X break;
- X
- X case LIST:
- X ttyclear();
- X refresh();
- X showwindows();
- X pause();
- X repaintall();
- X break;
- X
- X case HELP1:
- X case HELP2:
- X ttyclear();
- X refresh();
- X helpmsg();
- X pause();
- X repaintall();
- X break;
- X
- X#ifdef SHOWMAP
- X case MAP:
- X ttyclear();
- X for (x = 0; x < COLS; x++)
- X for (y = 0; y < LINES; y++)
- X if (winmap[y * COLS + x])
- X mvwaddch(stdscr, y, x, mapchar(winmap[y * COLS + x]));
- X refresh();
- X pause();
- X repaintall();
- X break;
- X#endif
- X
- X case CHGCODE: /* change cmdchar */
- X showmsg("Enter new command character");
- X cmdchar = bgetch(0);
- X sprintf(buf, "New command character is '\\%04o'", cmdchar);
- X showmsg(buf);
- X break;
- X
- X#ifdef SIGTSTP
- X case SUSPEND: /* Berkeley suspend job */
- X showmsg("Suspending");
- X kill(0, SIGTSTP);
- X showmsg("Resuming"); /* resume here */
- X break;
- X#endif
- X
- X case EXIT:
- X nowmrc++;
- X case QUIT: /* quit */
- X timetoquit = TRUE;
- X break;
- X default:
- X if (c != cmdchar) /* bad command */
- X showmsg("No such command -- use 'h' command for help");
- X }
- X return(c);
- X}
- X
- X/*
- X * Read in the file in $HOME/.wmrc if possible
- X * Otherwise prompt for the first window
- X */
- Xfirstwindow(argc)
- Xint argc;
- X{
- X struct sw_buf savewin;
- X FILE *file;
- X int okflg;
- X int x1, y1, x2, y2;
- X int begline, begcol, cols, lines;
- X char *cp;
- X
- X if ((cp = getenv("WMRC")) != (char *)0)
- X strcpy(wmrc, cp);
- X else {
- X if ((cp = getenv("HOME")) == (char *)0)
- X cp = ".";
- X sprintf(wmrc, "%s/.wmrc", cp);
- X }
- X if ((file = fopen(wmrc, "r")) != NULL && argc == 1) {
- X int reads = 0;
- X okflg = FALSE;
- X while (fread(&savewin, sizeof(savewin), 1, file) == 1) {
- X reads++;
- X if ((cmdchar = savewin.sw_cmdchar) == 0)
- X cmdchar = DEFCMD;
- X if (makewin(savewin.sw_lines, savewin.sw_cols,
- X savewin.sw_begline, savewin.sw_begcol))
- X okflg = TRUE;
- X else {
- X if (! okflg) {
- X showmsg("Can't create any shells--sorry");
- X closeup();
- X endwin();
- X exit(1);
- X }
- X }
- X }
- X fclose(file);
- X if (! reads) {
- X unlink(wmrc);
- X return(firstwindow(0));
- X }
- X repaint(topw);
- X }
- X else {
- X showmsg("Please create the first window: Move to lower left, then type x");
- X okflg = FALSE;
- X while (!okflg) {
- X if (getpos(&y1, &x1, LINES-2, 0))
- X closeup(), endwin(), exit(1);
- X showmsg("Move to upper right, then type x");
- X if (getpos(&y2, &x2, y1, x1))
- X closeup(), endwin(), exit(1);
- X begline = y2;
- X begcol = x1;
- X lines = y1 - y2 + 1;
- X cols = x2 - x1 + 1;
- X if (lines > 0 && cols > 0) {
- X if (makewin(lines, cols, begline, begcol)){
- X okflg = TRUE;
- X repaint(topw);
- X showmsg("Created new window");
- X }
- X else {
- X showmsg("Can't create any shells--sorry");
- X closeup();
- X endwin();
- X exit(1);
- X }
- X }
- X else
- X showmsg("Illegal window size: Move to lower left, then type x");
- X }
- X }
- X}
- X
- X/*
- X * Set up win structure and associated junk for new window
- X * Return TRUE if it worked (ie, the pty and fork in shell were ok)
- X * else FALSE
- X */
- Xmakewin(lines, cols, begline, begcol)
- Xint lines, cols, begline, begcol;
- X{
- X register struct win_struct *wsp;
- X
- X if ((wsp = malloc(sizeof (struct win_struct))) == NOWIN)
- X return(FALSE);
- X wsp->next = wsp->prev = 0;
- X wsp->virt = newwin(0, 0, 0, 0);
- X wsp->virt->_flags = 0; /* get around curses bug */
- X werase(wsp->virt);
- X wsp->wptr = newwin(lines, cols, begline, begcol);
- X wsp->wptr->_flags = 0; /* get around curses bug */
- X if ((wsp->buf = (char *)malloc(RDBSIZE)) == 0 || shell(wsp) == FALSE) {
- X werase(wsp->virt);
- X freespace(wsp);
- X return(FALSE);
- X }
- X wmove(wsp->virt, wsp->virt->_maxy - wsp->wptr->_maxy, 0);
- X setupbox(wsp);
- X chgwin(wsp);
- X return(TRUE);
- X}
- X
- X/*
- X * spawn shell process for window wsp
- X * Finds first available pty and its matching pts and opens them
- X * Returns TRUE if it found you some pty's else FALSE
- X */
- Xshell(wsp)
- Xregister struct win_struct *wsp;
- X{
- X char ptyname[100], ptsname[100], pchar;
- X int fpty, fpts;
- X
- X for (pchar = PTFIRST; pchar <= PTLAST; pchar++) {
- X sprintf(ptyname, PTYFORMAT, PTYBASENAME, pchar);
- X fpty = open(ptyname, 2);
- X if (fpty >= 0) {
- X sprintf(ptsname, PTYFORMAT, PTSBASENAME, pchar);
- X fpts = open(ptsname, 2);
- X if (fpts >= 0)
- X break;
- X close(fpty);
- X }
- X }
- X if (pchar > PTLAST)
- X return(FALSE);
- X wsp->suffix = pchar;
- X for (pchar = 'a'; pchar <= 'z'; ++pchar)
- X if (getwpnt(pchar) == NOWIN)
- X break;
- X wsp->id = pchar;
- X ioctl(fpty, TIOCSETD, &ttydisc);
- X stty(fpty, &sgttybuf);
- X ioctl(fpty, TIOCSETC, &tcharsbuf);
- X ioctl(fpty, TIOCLSET, &ttymode);
- X ioctl(fpty, TIOCSLTC, <charsbuf);
- X switch(wsp->pid = fork()) {
- X case 0: /* child */
- X close(fpty);
- X dup2(fpts, 0);
- X dup2(fpts, 1);
- X dup2(fpts, 2);
- X close(fpts);
- X setpgrp(0, getpid());/* set me up in my own new process group */
- X execlp(shellpgm, shellname, 0);
- X exit(1);
- X default:
- X close(fpts);
- X wsp->pty = fpty;
- X wsp->flags = 0;
- X if (symlink(ptsname, ptslinkname(wsp->id)) == 0)
- X wsp->flags = WPTSLINK;
- X setenv(wsp);
- X return(TRUE);
- X case -1: /* error */
- X close(fpty);
- X close(fpts);
- X return(FALSE);
- X }
- X}
- X
- X#define TERMCAP "wm|wmvirt:am:bs:ce=\\EK:cl=\\ES:nd=\\EC:up=\\EA:cm=\\EY%+ %+ :"
- X#ifdef REVVIDEO
- X# define REV "so=\\EO:se=\\EE:"
- X#else
- X# define REV ""
- X#endif
- X
- X/*
- X * send a setenv command for wmvirt terminal to shell in window wsp
- X */
- Xsetenv(wsp)
- Xregister struct win_struct *wsp;
- X{
- X char buf[LINEBUF];
- X
- X if (strcmp(shellname, "csh") == 0)
- X sprintf(buf, "setenv TERM wmvirt;setenv TERMCAP '%sco#%d:li#%d:%s'\n",
- X TERMCAP, wsp->wptr->_maxx, wsp->wptr->_maxy, REV);
- X else
- X sprintf(buf, "TERM=wmvirt; TERMCAP='%sco#%d:li#%d:%s';export TERM TERMCAP\n",
- X TERMCAP, wsp->wptr->_maxx, wsp->wptr->_maxy, REV);
- X write(wsp->pty, buf, strlen(buf));
- X}
- X
- Xchar *
- Xptslinkname(c)
- Xchar c;
- X{
- X static char lnk[100];
- X
- X return(sprintf(lnk, "Window%c", c));
- X}
- X
- Xstruct win_struct *
- Xaskwpnt(str, oneok)
- Xchar *str;
- X{
- X struct win_struct *wsp;
- X char buf[40], c;
- X
- X if (topw->next == topw) {
- X if (oneok)
- X return(topw);
- X showmsg("Only 1 window");
- X return(NOWIN);
- X }
- X showmsg(sprintf(buf, "%s which window?", str));
- X if (isupper(c = bgetch(0)))
- X c = tolower(c);
- X if ((wsp = getwpnt(c)) == NOWIN)
- X showmsg("No such window");
- X return(wsp);
- X}
- X
- X/*
- X * translate window name to window pointer
- X */
- Xstruct win_struct *
- Xgetwpnt(c)
- Xchar c;
- X{
- X register struct win_struct *wsp;
- X int atlast;
- X
- X for (atlast = 0, wsp = topw; topw && atlast == 0; wsp = wsp->next) {
- X atlast = (wsp->next == topw);
- X if (wsp->id == c)
- X return(wsp);
- X }
- X return(NOWIN);
- X}
- X
- X/*
- X * print a command summary over the top of the screen, then redraw
- X */
- Xhelpmsg()
- X{
- Xprintf("All WM commands consist of COMMAND character plus one more character.\r\n");
- Xprintf("The command character is initially ESCAPE, unless you reset it.\r\n");
- Xprintf("To enter the command character itself, type it twice.\r\n\n");
- Xprintf("The WM commands are COMMAND character plus:\r\n");
- Xprintf("q or Q Quit WM. 'Q' doesn't update .wmrc\r\n");
- Xprintf("r Redraw entire screen\r\n");
- Xprintf("c Change to another window\r\n");
- Xprintf("l change to Last-used window\r\n");
- Xprintf("n make a New window\r\n");
- Xprintf("m Move and/or change size of window\r\n");
- Xprintf("e Erase window temporarily\r\n");
- Xprintf("k Kill window permanently\r\n");
- Xprintf("p Page window forward (as opposed to standard scrolling)\r\n");
- X#ifdef SIGTSTP
- Xprintf("z suspend wm (Do this ONLY if you are using CSH)\r\n");
- X#endif
- Xprintf("C change COMMAND character\r\n");
- Xprintf("L list windows\r\n");
- X#ifdef SHOWMAP
- Xprintf("M display map\r\n");
- X#endif
- Xprintf("h or ? print this command summary\r\n\n");
- Xprintf("If you are asked 'which window?' the window names are a, b, c, etc...\r\n");
- Xprintf("The name of each window is shown at the top of the window.\r\n");
- Xprintf("To move cursor, use 'u', 'd', 'r' and 'l' for 'up, 'down', 'right' and 'left'\r\n");
- X}
- X
- Xshowwindows()
- X{
- X register struct win_struct *wsp;
- X register WINDOW *wp;
- X int atlast, n;
- X
- X printf("\n\n\n\r");
- X printf(" # ID PID Device Coord.(X/Y) Lines Cols State\n\r");
- X printf("-- -- ----- ------------ ----------- ----- ---- -----\n\r");
- X for (n = 1, atlast = 0, wsp = topw; atlast == 0; wsp = wsp->next, n++) {
- X atlast = (wsp->next == topw);
- X wp = wsp->wptr;
- X#ifdef NUMSUFFIX
- X printf("%2d %c %5d %11.11s%-2d %5d/%-5d %4d %4d %s%s%s\r\n",
- X#else
- X printf("%2d %c %5d %11.11s%c %5d/%-5d %4d %4d %s%s%s\r\n",
- X#endif
- X n, wsp->id, wsp->pid, PTSBASENAME, wsp->suffix,
- X wp->_begx, wp->_begy, wp->_maxy, wp->_maxx,
- X wsp->flags & WERASED? "Erased": "Live",
- X wsp->flags & WFULLSCREEN? "/Full-screen": "",
- X wsp->flags & WPTSLINK? "/Linked": "");
- X }
- X}
- ________This_Is_The_END________
- echo 'sh - wm.h'
- sed 's/^X//' <<'________This_Is_The_END________' >>wm.h
- X/*
- X * definitions for wm
- X */
- X
- X#include <curses.h>
- X#define MENLO_JCL /* for 2.9 - get SIGTSTP from signal.h */
- X
- X/*
- X * The number of windows for each user is limited by the number of
- X * open files a process (i.e., main) may have, by the number of
- X * processes each user may create and by the number of virtual tty's
- X * available. (PTLAST - PTFIRST) sets a limit on the number of
- X * windows available to each 'wm' process.
- X *
- X *
- X * PTYBASENAME is the special file name of the controlling PTY's
- X * available to wm, sans the last character
- X * PTSBASENAME is the special file name of the slave PTY's,
- X * sans last character
- X * PTFIRST through PTLAST are all the final characters
- X * of the special file names. If the names have a numeric suffix,
- X * define NUMSUFFIX
- X *
- X * Likely names on 4.1bsd would be something like
- X * /dev/ptypA ... for controlling and
- X * /dev/ttypA ... for slave
- X *
- X * These PTY's should be separate from those used by networks,
- X * since these should not automatically run login
- X * (i.e., they should not be enabled in /etc/ttys)
- X */
- X
- X# define PTYBASENAME "/dev/wm/pty" /* must be string */
- X# define PTSBASENAME "/dev/wm/pts" /* must be string */
- X#ifdef NUMSUFFIX
- X# define PTFIRST 0 /* must be int */
- X# define PTLAST 8 /* must be int */
- X# define PTYFORMAT "%s%d"
- X#else
- X# define PTFIRST 'A' /* must be char */
- X# define PTLAST 'F' /* must be char */
- X# define PTYFORMAT "%s%c"
- X#endif
- X
- X# define LINEBUF 256 /* size of line buffers */
- X# define MIN(a,b) (a<b?a:b)
- X# define MAX(a,b) (a>b?a:b)
- X# define showcursor(y, x) move(y, x), refresh()
- X# define ttyclear() clear(), refresh()
- X
- X/*
- X * flags
- X */
- X# define WTOUCHED 0x01 /* The window is modified */
- X# define WERASED 0x02 /* The window is erased */
- X# define WFULLSCREEN 0x04 /* The window is a full screen window */
- X# define WPTSLINK 0x08 /* Slave pty was linked */
- X
- X/*
- X * Global data with miscellaneous information about each window.
- X */
- Xstruct win_struct {
- X struct win_struct *next; /* pointer to next window */
- X struct win_struct *prev; /* pointer to prev window */
- X WINDOW *wptr; /* ptr to small curses win to be displayed */
- X WINDOW *virt; /* ptr to large curses win in case chg size */
- X WINDOW *boxtop, *boxbot; /* ptrs to curses wins for box or 0 */
- X WINDOW *boxleft, *boxright; /* ptrs to curses wins for box or 0 */
- X char pend[4]; /* pending characters from recent add()s */
- X char *buf; /* read buffer */
- X int pid; /* pid of this wondow's shell */
- X int pty; /* fildes of pty to/from this win's shell */
- X char id; /* name of the window */
- X char suffix; /* last character of the virtual tty's name */
- X char flags; /* global flags */
- X};
- X
- Xstruct win_struct *malloc();
- Xextern struct win_struct *botw, *topw;
- X
- X/*
- X * If FAST is defined, the window copy routine will use routines that are
- X * not necessarily portable.
- X */
- X#ifdef FAST
- X typedef short map_t;
- X# define mapchar(c) ((c) & 0xff)
- X# define chartomap(c, n) ((map_t)(c) | ((n) << 8))
- X# define maptocount(c) ((c) >> 8)
- X# else
- X typedef char map_t;
- X# define mapchar(c) (c)
- X#endif
- X
- Xextern map_t *winmap;
- X#define visible(w, x, y) (winmap[(y)*COLS+(x)] == mapchar((w)->id))
- X
- X/*
- X * This is what goes in .wmrc to recreate same layout.
- X */
- Xstruct sw_buf {
- X int sw_begline;
- X int sw_begcol;
- X int sw_lines;
- X int sw_cols;
- X char sw_cmdchar;
- X};
- X
- X/* command char for virtual terminal special functions. Check TERMCAP in wm.c */
- X#define CODE '\033'
- X
- X/*
- X * Forward references
- X */
- Xchar *getenv();
- XFILE *fopen();
- Xint onsusp();
- Xchar *sprintf(), *strcpy(), *strcat(), *rindex();
- Xchar windowname(); int windownum();
- ________This_Is_The_END________
- ---------------------------- cut here -------------------------------
-
- Chris Bertin : (617) 933-7735 x2336
- Pixel Systems Inc. : (800) 325-3342
- 300 Wildwood street : {allegra|ihnp4|cbosgd|ima|genrad|amd|harvard}\
- Woburn, Ma 01801 : !wjh12!pixel!pixutl!chris
-
-
-
-
-