tChange 9wm to look like rio. - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 038e9089b354385cada2a35663c863d43dd5b20d
 (DIR) parent ba9ffa53c4825e115078ed098205d75aa7a77eb0
 (HTM) Author: rsc <devnull@localhost>
       Date:   Sun, 21 Mar 2004 04:27:28 +0000
       
       Change 9wm to look like rio.
       
       Diffstat:
         A src/cmd/rio/9wm.man                 |     118 +++++++++++++++++++++++++++++++
         A src/cmd/rio/README                  |     203 +++++++++++++++++++++++++++++++
         A src/cmd/rio/client.c                |     242 +++++++++++++++++++++++++++++++
         A src/cmd/rio/color.c                 |      44 +++++++++++++++++++++++++++++++
         A src/cmd/rio/cursor.c                |     368 +++++++++++++++++++++++++++++++
         A src/cmd/rio/dat.h                   |     148 +++++++++++++++++++++++++++++++
         A src/cmd/rio/error.c                 |      98 +++++++++++++++++++++++++++++++
         A src/cmd/rio/event.c                 |     465 +++++++++++++++++++++++++++++++
         A src/cmd/rio/fns.h                   |      96 +++++++++++++++++++++++++++++++
         A src/cmd/rio/grab.c                  |     498 +++++++++++++++++++++++++++++++
         A src/cmd/rio/main.c                  |     437 +++++++++++++++++++++++++++++++
         A src/cmd/rio/manage.c                |     482 +++++++++++++++++++++++++++++++
         A src/cmd/rio/menu.c                  |     258 +++++++++++++++++++++++++++++++
         A src/cmd/rio/patchlevel.h            |       1 +
       
       14 files changed, 3458 insertions(+), 0 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/rio/9wm.man b/src/cmd/rio/9wm.man
       t@@ -0,0 +1,118 @@
       +.if t .ds 85 8\(12
       +.if n .ds 85 8-1/2
       +.TH 9wm 1
       +.SH NAME
       +9wm \- \*(85-like Window Manager for X
       +.SH SYNOPSIS
       +.B 9wm
       +[
       +.B \-grey
       +] [
       +.B \-version
       +] [
       +.B \-font
       +.I fname
       +] [
       +.B \-term
       +.I termprog
       +] [
       +.BR exit | restart
       +]
       +.SH DESCRIPTION
       +.I 9wm
       +is a window manager for X which attempts to emulate the window management
       +policies of Plan 9's 
       +.I \*(85
       +window manager.
       +.PP
       +The
       +.B \-grey
       +option makes the background light grey, as does \*(85.
       +Use this option for maximum authenticity.
       +.B \-font
       +.I fname
       +sets the font in
       +.IR 9wm 's
       +menu to
       +.IR fname ,
       +overriding the default.
       +.B \-term
       +.I termprog
       +specifies an alternative program to run when the
       +.I New
       +menu item is selected.
       +.B \-version
       +prints the current version on standard error, then exits.
       +.PP
       +To make 
       +.I 9wm
       +exit, you have to run
       +.B "9wm exit"
       +on the command line.  There is no ``exit'' menu item.
       +.PP
       +.I 9wm
       +is click-to-type: it has a notion of the current window,
       +which is usually on top, and always has its border darkened.
       +Characters typed at the keyboard go to the current window,
       +and mouse clicks outside the current window are swallowed up
       +by
       +.IR 9wm .
       +To make another window the current one, click on it with button 1.
       +Unlike other X window managers, 9wm implements `mouse focus': mouse events
       +are sent only to the current window.
       +.PP
       +A menu of window operations is available by pressing button 3
       +outside the current window.
       +The first of these,
       +.IR New ,
       +attempts to spawn a
       +.I 9term
       +process (or
       +.I xterm
       +if
       +.I 9term
       +is not available).
       +The new
       +.I 9term
       +will request that its outline be swept using button 3
       +of the mouse, by changing the cursor.
       +.RI ( xterm
       +defaults to a fixed size, and thus wants to be dragged; pressing
       +button 3 places it.)
       +.PP
       +The next four menu items are
       +.IR Reshape ,
       +.IR Move ,
       +.IR Delete ,
       +and
       +.IR Hide .
       +All of the operations change the cursor into a target, prompting the user
       +to click button 3 on one of the windows to select it for the operation.
       +At this stage, clicking button 1 or 2 will abort the operation.
       +Otherwise, if the operation was
       +.IR Resize ,
       +the user is prompted to sweep out the new outline with button 3.
       +If it was
       +.IR Move ,
       +the user should keep the button held down after the initial click that selected
       +the window, and drag the window to the right place before releasing.
       +In either case, button 1 or 2 will abort the operation.
       +.PP
       +If the
       +.I Delete
       +operation is selected, the window will be deleted when the button is released.
       +This typically kills the client that owns the window.
       +The
       +.I Hide
       +operation just makes the window invisible.  While hidden, the window's
       +name appears on the bottom of the button 3 menu.  Selecting that item
       +brings the window back (unhides it).
       +This operation replaces the iconification feature provided by other
       +window managers.
       +.SH BUGS
       +Is not completely compatible with \*(85.
       +.PP
       +There is a currently a compiled-in limit of 32 hidden windows.
       +.SH "SEE ALSO"
       +.IR 9term (1),
       +.IR xterm (1).
 (DIR) diff --git a/src/cmd/rio/README b/src/cmd/rio/README
       t@@ -0,0 +1,203 @@
       +This is David Hogan's 9wm updated to behave more like 
       +Plan 9's rio.  Since I cannot get approval for the changes
       +and I'd prefer not to resort to patches, I have renamed it "rio".
       +
       +Current incompatibilities that would be nice to fix:
       +
       +- Rio uses X11 fonts for the menu, and there aren't any good ones!
       +I'm tempted to hard-code the Plan 9 default font bitmap.
       +
       +- The command-line options should be made more like Plan 9.
       +
       +- Should work out a protocol between 9term and rio so that:
       +        * 9term can tell rio to blue its border during hold mode
       +        * rio can tell 9term to fade its text when it loses focus
       +        * rio can tell 9term to unfade its text when it regains focus
       +
       +- Should change window focus on b2/b3 clicks and then
       +  pass along the click event to the now-focused window.
       +
       +- Should change 9term to redirect b3 clicks to rio so that rio
       +  can put up the usual b3 menu.
       +
       +The original README is below.
       +
       +- russ cox
       +rsc@swtch.com
       +20 march 2004
       +
       +
       +                           9wm Version 1.2
       +                   Copyright 1994-1996 David Hogan.
       +
       +What is 9wm?
       +============
       +
       +9wm is an X window manager which attempts to emulate the Plan 9 window
       +manager 8-1/2 as far as possible within the constraints imposed by X.
       +It provides a simple yet comfortable user interface, without garish
       +decorations or title-bars. Or icons.  And it's click-to-type.  This
       +will not appeal to everybody, but if you're not put off yet then read
       +on.  (And don't knock it until you've tried it.)
       +
       +One major difference between 9wm and 8-1/2 is that the latter provides
       +windows of text with a typescript interface, and doesn't need to run a
       +separate program to emulate a terminal.  9wm, as an X window manager,
       +does require a separate program.  For better 8-1/2 emulation, you should
       +obtain Matthew Farrow's "9term" program (ftp://ftp.cs.su.oz.au/matty/unicode),
       +version 1.6 or later (earlier versions don't cooperate with 9wm in
       +implementing "hold mode").  Of course, you can run xterm under 9wm as well.
       +
       +What is 9wm not?
       +================
       +
       +9wm is not a virtual window manager.  It is not customisable to any
       +great extent.  It is not large and unwieldy, and doesn't use the X
       +toolkit.  Requests to make it any of these things will be silently
       +ignored (or flamed if I have had a bad day :-)  If you want tvtwm
       +or mwm, you know where to get them...
       +
       +Where do I get it?
       +==================
       +
       +The latest version of 9wm is held at ftp://ftp.cs.su.oz.au/dhog/9wm
       +
       +Author
       +======
       +
       +9wm was written by David Hogan (dhog@cs.su.oz.au), a postgraduate
       +student at the Basser Department of Computer Science, University
       +of Sydney (http://www.cs.su.oz.au/~dhog/).
       +
       +Licence
       +=======
       +
       +  9wm is free software, and is Copyright (c) 1994-1996 by David Hogan.
       +  Permission is granted to all sentient beings to use this software,
       +  to make copies of it, and to distribute those copies, provided
       +  that:
       +
       +      (1) the copyright and licence notices are left intact
       +      (2) the recipients are aware that it is free software
       +      (3) any unapproved changes in functionality are either
       +            (i) only distributed as patches
       +        or (ii) distributed as a new program which is not called 9wm
       +                and whose documentation gives credit where it is due
       +      (4) the author is not held responsible for any defects
       +          or shortcomings in the software, or damages caused by it.
       +
       +  There is no warranty for this software.  Have a nice day.
       +
       +How do I compile/install it?
       +============================
       +
       +Assuming your system is correctly configured, you should only need to
       +run xmkmf to generate the Makefile, and then run make or make install.
       +make install.man should copy the manpage (9wm.man) to the appropriate
       +directory.
       +
       +If the make fails, complaining that the function _XShapeQueryExtension
       +does not exist, try removing the "-DSHAPE" from the Imakefile, and
       +run xmkmf and make again.
       +
       +If you don't have imake, or it is misconfigured, or you would prefer
       +not to use it, try copying the file "Makefile.no-imake" to "Makefile",
       +then edit the definitions in this Makefile to suit your system.  This
       +may require defining suitable compilation flags for your system
       +(normally imake does this for you).  For instance, on AIX you must
       +include "-DBSD_INCLUDES" in CFLAGS.
       +
       +How do I use it?
       +================
       +
       +See the manual page for details.  You should probably read the
       +man page for 9term as well.
       +
       +What if I find a bug?
       +=====================
       +
       +Please mail all bug reports to 9wm-bugs@plan9.cs.su.oz.au, so
       +that I can incorporate fixes into the next release.  If you can
       +tell me how to fix it, all the better.
       +
       +Known Problems/Bugs
       +===================
       +
       +9wm tries hard to emulate 8-1/2, but isn't 100% compatible.  If
       +you are an experienced 8-1/2 user, please be patient with it.
       +
       +One intentional difference between 9wm and 8-1/2 is in the behaviour
       +of the menu when the last hidden item is unhidden.  Under 8-1/2, when
       +the menu is next used, it pops up with "New" selected.  Under 9wm,
       +the (new) last menu item will be selected.  This is a feature.  It
       +may be confusing if you frequently switch between 9wm and 8-1/2.
       +If you don't like this feature, email me for the one line fix.
       +
       +There have been some problems encountered when resizing 9term on
       +some platforms.  This turns out to be a problem in 9term (actually
       +in libXg, to be precise).  Newer versions of 9term should be
       +immune to this, see matty@cs.su.oz.au if your 9term needs fixing.
       +
       +Some client programs do weird things.  One of these is Frame Maker.
       +It appears that if it has a modal dialog on the screen, then if any
       +of its windows are current, all keypresses are redirected to the
       +modal dialog.  This is not 9wm's fault -- Frame Maker is doing this.
       +
       +Programs like Netscape Navigator like to put riddiculously long
       +icon name properties on their windows, of the form "Netscape: blah blah".
       +There is no way that I know of to stop netscape from doing this.  For this
       +reason, 9wm truncates labels at the first colon it finds.  This keeps the
       +button 3 menu from becoming excessively wide.  Note that with same
       +applications, you can use an iconName resource to set the label; this
       +works well for "xman", whose default icon name of "Manual Browser"
       +is a tad too long.
       +
       +See Also
       +========
       +
       +http://www.cs.su.oz.au/~dhog/
       +    The 9wm Home Page
       +
       +ftp://ftp.cs.su.oz.au/matty/unicode/
       +    for source to 9term (get README first)
       +
       +ftp://plan9.att.com/plan9/unixsrc/sam/
       +    for source && info on Rob Pike's editor "sam"
       +
       +ftp://rtfm.mit.edu/pub/usenet/news.answers/unix-faq/shell/rc
       +    for information on a publically available implementation
       +    of the Plan 9 shell "rc" for unix (or look in comp.unix.shell).
       +
       +ftp://viz.tamu.edu/pub/rc
       +    for source to the abovementioned implementation of rc.
       +
       +http://plan9.att.com/plan9/
       +http://plan9.att.com/magic/man2html/1/8%c2%bd
       +    for information on Plan 9 (including the 8-1/2 manual entry)
       +
       +Acknowledgements
       +================
       +
       +Thanks to Rob Pike for writing the original 8-1/2 program (and
       +before that, mux) which inspired the writing of 9wm.
       +
       +Thanks to John Mackin, whose gwm "wool code" for emulating mux
       +was also an inspiration: I used it (and hacked it) until I got
       +too frustrated with gwm's large memory requirements and lack of
       +speed (sorry Colas!), and decided to write a dedicated program.
       +
       +Thanks to Matthew Farrow for writing 9term.
       +
       +A big thanks to Dave Edmondson for adding support for
       +multi-screen displays.
       +
       +The following people helped beta test 9wm:
       +
       +        John Mackin
       +        Noel Hunt
       +        Fred Curtis
       +        James Matthew Farrow
       +        Danny Yee
       +        Arnold Robbins
       +        Byron Rakitzis
       +        micro@cooper.edu
 (DIR) diff --git a/src/cmd/rio/client.c b/src/cmd/rio/client.c
       t@@ -0,0 +1,242 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +#include <stdio.h>
       +#include <X11/X.h>
       +#include <X11/Xlib.h>
       +#include <X11/Xutil.h>
       +#include "dat.h"
       +#include "fns.h"
       +
       +Client        *clients;
       +Client        *current;
       +
       +void
       +setactive(Client *c, int on)
       +{
       +        if (c->parent == c->screen->root) {
       +                fprintf(stderr, "9wm: bad parent in setactive; dumping core\n");
       +                abort();
       +        }
       +        if (on) {
       +                XUngrabButton(dpy, AnyButton, AnyModifier, c->parent);
       +                XSetInputFocus(dpy, c->window, RevertToPointerRoot, timestamp());
       +                if (c->proto & Ptakefocus)
       +                        sendcmessage(c->window, wm_protocols, wm_take_focus, 0);
       +                cmapfocus(c);
       +        }
       +        else
       +                XGrabButton(dpy, AnyButton, AnyModifier, c->parent, False,
       +                        ButtonMask, GrabModeAsync, GrabModeSync, None, None);
       +        draw_border(c, on);
       +}
       +
       +void
       +draw_border(Client *c, int active)
       +{
       +        unsigned long pixel;
       +
       +        if(active){
       +                if(c->hold)
       +                        pixel = c->screen->activeholdborder;
       +                else
       +                        pixel = c->screen->activeborder;
       +        }else{
       +                if(c->hold)
       +                        pixel = c->screen->inactiveholdborder;
       +                else
       +                        pixel = c->screen->inactiveborder;
       +        }
       +
       +        XSetWindowBackground(dpy, c->parent, pixel);
       +        XClearWindow(dpy, c->parent);
       +}
       +
       +void
       +active(Client *c)
       +{
       +        Client *cc;
       +
       +        if (c == 0) {
       +                fprintf(stderr, "9wm: active(c==0)\n");
       +                return;
       +        }
       +        if (c == current)
       +                return;
       +        if (current) {
       +                setactive(current, 0);
       +                if (current->screen != c->screen)
       +                        cmapnofocus(current->screen);
       +        }
       +        setactive(c, 1);
       +        for (cc = clients; cc; cc = cc->next)
       +                if (cc->revert == c)
       +                        cc->revert = c->revert;
       +        c->revert = current;
       +        while (c->revert && !normal(c->revert))
       +                c->revert = c->revert->revert;
       +        current = c;
       +#ifdef        DEBUG
       +        if (debug)
       +                dump_revert();
       +#endif
       +}
       +
       +void
       +nofocus(void)
       +{
       +        static Window w = 0;
       +        int mask;
       +        XSetWindowAttributes attr;
       +        Client *c;
       +
       +        if (current) {
       +                setactive(current, 0);
       +                for (c = current->revert; c; c = c->revert)
       +                        if (normal(c)) {
       +                                active(c);
       +                                return;
       +                        }
       +                cmapnofocus(current->screen);
       +                /* if no candidates to revert to, fall through */
       +        }
       +        current = 0;
       +        if (w == 0) {
       +                mask = CWOverrideRedirect;
       +                attr.override_redirect = 1;
       +                w = XCreateWindow(dpy, screens[0].root, 0, 0, 1, 1, 0,
       +                        CopyFromParent, InputOnly, CopyFromParent, mask, &attr);
       +                XMapWindow(dpy, w);
       +        }
       +        XSetInputFocus(dpy, w, RevertToPointerRoot, timestamp());
       +}
       +
       +void
       +top(Client *c)
       +{
       +        Client **l, *cc;
       +
       +        l = &clients;
       +        for (cc = *l; cc; cc = *l) {
       +                if (cc == c) {
       +                        *l = c->next;
       +                        c->next = clients;
       +                        clients = c;
       +                        return;
       +                }
       +                l = &cc->next;
       +        }
       +        fprintf(stderr, "9wm: %x not on client list in top()\n", c);
       +}
       +
       +Client *
       +getclient(Window w, int create)
       +{
       +        Client *c;
       +
       +        if (w == 0 || getscreen(w))
       +                return 0;
       +
       +        for (c = clients; c; c = c->next)
       +                if (c->window == w || c->parent == w)
       +                        return c;
       +
       +        if (!create)
       +                return 0;
       +
       +        c = (Client *)malloc(sizeof(Client));
       +        memset(c, 0, sizeof(Client));
       +        c->window = w;
       +        /* c->parent will be set by the caller */
       +        c->parent = None;
       +        c->reparenting = 0;
       +        c->state = WithdrawnState;
       +        c->init = 0;
       +        c->cmap = None;
       +        c->label = c->class = 0;
       +        c->revert = 0;
       +        c->is9term = 0;
       +        c->hold = 0;
       +        c->ncmapwins = 0;
       +        c->cmapwins = 0;
       +        c->wmcmaps = 0;
       +        c->next = clients;
       +        clients = c;
       +        return c;
       +}
       +
       +void
       +rmclient(Client *c)
       +{
       +        Client *cc;
       +
       +        for (cc = current; cc && cc->revert; cc = cc->revert)
       +                if (cc->revert == c)
       +                        cc->revert = cc->revert->revert;
       +
       +        if (c == clients)
       +                clients = c->next;
       +        for (cc = clients; cc && cc->next; cc = cc->next)
       +                if (cc->next == c)
       +                        cc->next = cc->next->next;
       +
       +        if (hidden(c))
       +                unhidec(c, 0);
       +
       +        if (c->parent != c->screen->root)
       +                XDestroyWindow(dpy, c->parent);
       +
       +        c->parent = c->window = None;                /* paranoia */
       +        if (current == c) {
       +                current = c->revert;
       +                if (current == 0)
       +                        nofocus();
       +                else {
       +                        if (current->screen != c->screen)
       +                                cmapnofocus(c->screen);
       +                        setactive(current, 1);
       +                }
       +        }
       +        if (c->ncmapwins != 0) {
       +                XFree((char *)c->cmapwins);
       +                free((char *)c->wmcmaps);
       +        }
       +        if (c->iconname != 0)
       +                XFree((char*) c->iconname);
       +        if (c->name != 0)
       +                XFree((char*) c->name);
       +        if (c->instance != 0)
       +                XFree((char*) c->instance);
       +        if (c->class != 0)
       +                XFree((char*) c->class);
       +        memset(c, 0, sizeof(Client));                /* paranoia */
       +        free(c);
       +}
       +
       +#ifdef        DEBUG
       +void
       +dump_revert(void)
       +{
       +        Client *c;
       +        int i;
       +
       +        i = 0;
       +        for (c = current; c; c = c->revert) {
       +                fprintf(stderr, "%s(%x:%d)", c->label ? c->label : "?", c->window, c->state);
       +                if (i++ > 100)
       +                        break;
       +                if (c->revert)
       +                        fprintf(stderr, " -> ");
       +        }
       +        if (current == 0)
       +                fprintf(stderr, "empty");
       +        fprintf(stderr, "\n");
       +}
       +
       +void
       +dump_clients(void)
       +{
       +        Client *c;
       +
       +        for (c = clients; c; c = c->next)
       +                fprintf(stderr, "w 0x%x parent 0x%x @ (%d, %d)\n", c->window, c->parent, c->x, c->y);
       +}
       +#endif
 (DIR) diff --git a/src/cmd/rio/color.c b/src/cmd/rio/color.c
       t@@ -0,0 +1,44 @@
       +/* Copyright (c) 2004 Russ Cox, see README for licence details */
       +#include <stdio.h>
       +#include <signal.h>
       +#include <X11/X.h>
       +#include <X11/Xlib.h>
       +#include <X11/Xutil.h>
       +#include "dat.h"
       +#include "fns.h"
       +
       +unsigned long
       +colorpixel(Display *dpy, int depth, ulong rgb)
       +{
       +        int r, g, b;
       +
       +        r = rgb>>16;
       +        g = (rgb>>8)&0xFF;
       +        b = rgb&0xFF;
       +
       +        switch(depth){
       +        case 1:
       +        case 2:
       +        case 4:
       +        case 8:
       +        default:
       +                /* not going to waste color map entries */
       +                if(rgb == 0xFFFFFF)
       +                        return WhitePixel(dpy, DefaultScreen(dpy));
       +                return BlackPixel(dpy, DefaultScreen(dpy));
       +        case 15:
       +                r >>= 3;
       +                g >>= 3;
       +                b >>= 3;
       +                return (r<<10) | (g<<5) | b;
       +        case 16:
       +                r >>= 3;
       +                g >>= 2;
       +                b >>= 3;
       +                return (r<<11) | (g<<5) | b;
       +        case 24:
       +        case 32:
       +                return rgb;
       +        }
       +}
       +
 (DIR) diff --git a/src/cmd/rio/cursor.c b/src/cmd/rio/cursor.c
       t@@ -0,0 +1,368 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +#include <stdio.h>
       +#include <X11/X.h>
       +#include <X11/Xlib.h>
       +#include <X11/Xutil.h>
       +#include "dat.h"
       +#include "fns.h"
       +
       +typedef struct {
       +        int                width;
       +        int                hot[2];
       +        unsigned char        mask[64];
       +        unsigned char        fore[64];
       +} Cursordata;
       +
       +Cursordata bigarrow = {
       +        16,
       +        {0, 0},
       +        { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x3F, 
       +          0xFF, 0x0F, 0xFF, 0x0F, 0xFF, 0x1F, 0xFF, 0x3F, 
       +          0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0x3F, 
       +          0xCF, 0x1F, 0x8F, 0x0F, 0x07, 0x07, 0x03, 0x02, 
       +        },
       +        { 0x00, 0x00, 0xFE, 0x7F, 0xFE, 0x3F, 0xFE, 0x0F, 
       +          0xFE, 0x07, 0xFE, 0x07, 0xFE, 0x0F, 0xFE, 0x1F, 
       +          0xFE, 0x3F, 0xFE, 0x7F, 0xFE, 0x3F, 0xCE, 0x1F, 
       +          0x86, 0x0F, 0x06, 0x07, 0x02, 0x02, 0x00, 0x00, 
       +        },
       +};
       +
       +Cursordata sweep0data = {
       +        16,
       +        {7, 7},
       +        {0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03,
       +         0xC0, 0x03, 0xC0, 0x03, 0xFF, 0xFF, 0xFF, 0xFF,
       +         0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0xC0, 0x03,
       +         0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03},
       +        {0x00, 0x00, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
       +         0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xFE, 0x7F,
       +         0xFE, 0x7F, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01,
       +         0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x00, 0x00}
       +};
       +
       +Cursordata boxcursdata = {
       +        16,
       +        {7, 7},
       +        {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
       +         0xFF, 0xFF, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8,
       +         0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0xFF, 0xFF,
       +         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
       +        {0x00, 0x00, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F,
       +         0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70,
       +         0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70,
       +         0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0x00, 0x00}
       +};
       +
       +Cursordata sightdata = {
       +        16,
       +        {7, 7},
       +        {0xF8, 0x1F, 0xFC, 0x3F, 0xFE, 0x7F, 0xDF, 0xFB,
       +         0xCF, 0xF3, 0xC7, 0xE3, 0xFF, 0xFF, 0xFF, 0xFF,
       +         0xFF, 0xFF, 0xFF, 0xFF, 0xC7, 0xE3, 0xCF, 0xF3,
       +         0xDF, 0x7B, 0xFE, 0x7F, 0xFC, 0x3F, 0xF8, 0x1F,},
       +        {0x00, 0x00, 0xF0, 0x0F, 0x8C, 0x31, 0x84, 0x21,
       +         0x82, 0x41, 0x82, 0x41, 0x82, 0x41, 0xFE, 0x7F,
       +         0xFE, 0x7F, 0x82, 0x41, 0x82, 0x41, 0x82, 0x41,
       +         0x84, 0x21, 0x8C, 0x31, 0xF0, 0x0F, 0x00, 0x00,}
       +};
       +
       +Cursordata arrowdata = {
       +        16,
       +        {1, 1},
       +        {0xFF, 0x07, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x00,
       +         0xFF, 0x00, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0x07,
       +         0xE7, 0x0F, 0xC7, 0x1F, 0x83, 0x3F, 0x00, 0x7F,
       +         0x00, 0xFE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10,},
       +        {0x00, 0x00, 0xFE, 0x03, 0xFE, 0x00, 0x3E, 0x00,
       +         0x7E, 0x00, 0xFE, 0x00, 0xF6, 0x01, 0xE6, 0x03,
       +         0xC2, 0x07, 0x82, 0x0F, 0x00, 0x1F, 0x00, 0x3E,
       +         0x00, 0x7C, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00,}
       +};
       +
       +Cursordata whitearrow = {
       +        16,
       +        {0, 0},
       +        {0xFF, 0x07, 0xFF, 0x07, 0xFF, 0x03, 0xFF, 0x00,
       +         0xFF, 0x00, 0xFF, 0x01, 0xFF, 0x03, 0xFF, 0x07,
       +         0xE7, 0x0F, 0xC7, 0x1F, 0x83, 0x3F, 0x00, 0x7F,
       +         0x00, 0xFE, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x10,},
       +        {0xFF, 0x07, 0xFF, 0x07, 0x83, 0x03, 0xC3, 0x00,
       +         0xC3, 0x00, 0x83, 0x01, 0x1B, 0x03, 0x3F, 0x06,
       +         0x67, 0x0C, 0xC7, 0x18, 0x83, 0x31, 0x00, 0x63,
       +         0x00, 0xC6, 0x00, 0x6C, 0x00, 0x38, 0x00, 0x10,}
       +};
       +
       +Cursordata blittarget = {
       +        18,
       +        {8, 8},
       +        {0xe0, 0x1f, 0x00, 0xf0, 0x3f, 0x00, 0xf8, 0x7f, 0x00,
       +         0xfc, 0xff, 0x00, 0xfe, 0xff, 0x01, 0xff, 0xff, 0x03,
       +         0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03,
       +         0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03,
       +         0xff, 0xff, 0x03, 0xfe, 0xff, 0x01, 0xfc, 0xff, 0x00,
       +         0xf8, 0x7f, 0x00, 0xf0, 0x3f, 0x00, 0xe0, 0x1f, 0x00},
       +        {0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x3f, 0x00,
       +         0x38, 0x73, 0x00, 0x8c, 0xc7, 0x00, 0xec, 0xdf, 0x00,
       +         0x66, 0x9b, 0x01, 0x36, 0xb3, 0x01, 0xfe, 0xff, 0x01,
       +         0xfe, 0xff, 0x01, 0x36, 0xb3, 0x01, 0x66, 0x9b, 0x01,
       +         0xec, 0xdf, 0x00, 0x8c, 0xc7, 0x00, 0x38, 0x73, 0x00,
       +         0xf0, 0x3f, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00}
       +};
       +
       +Cursordata blitarrow = {
       +        18,
       +        {1, 1},
       +        {0xff, 0x0f, 0x00, 0xff, 0x07, 0x00, 0xff, 0x03, 0x00,
       +         0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x01, 0x00,
       +         0xff, 0x03, 0x00, 0xff, 0x07, 0x00, 0xe7, 0x0f, 0x00,
       +         0xc7, 0x1f, 0x00, 0x87, 0x3f, 0x00, 0x03, 0x7f, 0x00,
       +         0x01, 0xfe, 0x00, 0x00, 0xfc, 0x01, 0x00, 0xf8, 0x03,
       +         0x00, 0xf0, 0x01, 0x00, 0xe0, 0x00, 0x00, 0x40, 0x00},
       +        {0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0xfe, 0x00, 0x00,
       +         0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0xfe, 0x00, 0x00,
       +         0xf6, 0x01, 0x00, 0xe6, 0x03, 0x00, 0xc2, 0x07, 0x00,
       +         0x82, 0x0f, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3e, 0x00,
       +         0x00, 0x7c, 0x00, 0x00, 0xf8, 0x00, 0x00, 0xf0, 0x01,
       +         0x00, 0xe0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00}
       +};
       +
       +Cursordata blitsweep = {
       +        18,
       +        {8, 8},
       +        {0xc4, 0xff, 0x03, 0xce, 0xff, 0x03, 0xdf, 0xff, 0x03,
       +         0x3e, 0x80, 0x03, 0x7c, 0x83, 0x03, 0xf8, 0x83, 0x03,
       +         0xf7, 0x83, 0x03, 0xe7, 0x83, 0x03, 0xf7, 0x83, 0x03,
       +         0xf7, 0x83, 0x03, 0x07, 0x80, 0x03, 0x07, 0x80, 0x03,
       +         0x07, 0x80, 0x03, 0x07, 0x80, 0x03, 0x07, 0x80, 0x03,
       +         0xff, 0xff, 0x03, 0xff, 0xff, 0x03, 0xff, 0xff, 0x03},
       +        {0x00, 0x00, 0x00, 0x84, 0xff, 0x01, 0x0e, 0x00, 0x01,
       +         0x1c, 0x00, 0x01, 0x38, 0x00, 0x01, 0x70, 0x01, 0x01,
       +         0xe0, 0x01, 0x01, 0xc2, 0x01, 0x01, 0xe2, 0x01, 0x01,
       +         0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01,
       +         0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01,
       +         0x02, 0x00, 0x01, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00}
       +};
       +
       +/*
       + *        Grey tile pattern for root background
       + */
       +
       +#define grey_width 4
       +#define grey_height 2
       +static char grey_bits[] = {
       +        0x01, 0x04,
       +};
       +
       +static XColor        bl, wh;
       +
       +Cursor
       +getcursor(c, s)
       +Cursordata *c;
       +ScreenInfo *s;
       +{
       +        Pixmap f, m;
       +
       +        f = XCreatePixmapFromBitmapData(dpy, s->root, (char *)c->fore,
       +                c->width, c->width, 1, 0, 1);
       +        m = XCreatePixmapFromBitmapData(dpy, s->root, (char *)c->mask,
       +                c->width, c->width, 1, 0, 1);
       +        return XCreatePixmapCursor(dpy, f, m, &bl, &wh,
       +                        c->hot[0], c->hot[1]);
       +}
       +
       +void
       +initcurs(s)
       +ScreenInfo *s;
       +{
       +        XColor dummy;
       +
       +        XAllocNamedColor(dpy, DefaultColormap(dpy, s->num),
       +                        "black", &bl, &dummy);
       +        XAllocNamedColor(dpy, DefaultColormap(dpy, s->num),
       +                        "white", &wh, &dummy);
       +
       +        if (nostalgia) {
       +                s->arrow = getcursor(&blitarrow, s);
       +                s->target = getcursor(&blittarget, s);
       +                s->sweep0 = getcursor(&blitsweep, s);
       +                s->boxcurs = getcursor(&blitsweep, s);
       +        }
       +        else {
       +                s->arrow = getcursor(&bigarrow, s);
       +                s->target = getcursor(&sightdata, s);
       +                s->sweep0 = getcursor(&sweep0data, s);
       +                s->boxcurs = getcursor(&boxcursdata, s);
       +        }
       +
       +        s->root_pixmap = XCreatePixmapFromBitmapData(dpy,
       +                s->root, grey_bits, grey_width, grey_height,
       +                s->black, s->white, DefaultDepth(dpy, s->num));
       +}
       +
       +
       +/* RIO
       +
       +Cursor crosscursor = {
       +        {-7, -7},
       +        {0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0,
       +         0x03, 0xC0, 0x03, 0xC0, 0xFF, 0xFF, 0xFF, 0xFF,
       +         0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0xC0, 0x03, 0xC0,
       +         0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, 0x03, 0xC0, },
       +        {0x00, 0x00, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
       +         0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x7F, 0xFE,
       +         0x7F, 0xFE, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80,
       +         0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x00, 0x00, }
       +};
       +
       +Cursor boxcursor = {
       +        {-7, -7},
       +        {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
       +         0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F,
       +         0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF,
       +         0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, },
       +        {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE,
       +         0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
       +         0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
       +         0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00, }
       +};
       +
       +Cursor sightcursor = {
       +        {-7, -7},
       +        {0x1F, 0xF8, 0x3F, 0xFC, 0x7F, 0xFE, 0xFB, 0xDF,
       +         0xF3, 0xCF, 0xE3, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,
       +         0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xC7, 0xF3, 0xCF,
       +         0x7B, 0xDF, 0x7F, 0xFE, 0x3F, 0xFC, 0x1F, 0xF8, },
       +        {0x00, 0x00, 0x0F, 0xF0, 0x31, 0x8C, 0x21, 0x84,
       +         0x41, 0x82, 0x41, 0x82, 0x41, 0x82, 0x7F, 0xFE,
       +         0x7F, 0xFE, 0x41, 0x82, 0x41, 0x82, 0x41, 0x82,
       +         0x21, 0x84, 0x31, 0x8C, 0x0F, 0xF0, 0x00, 0x00, }
       +};
       +
       +Cursor whitearrow = {
       +        {0, 0},
       +        {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 
       +         0xFF, 0xF0, 0xFF, 0xF0, 0xFF, 0xF8, 0xFF, 0xFC, 
       +         0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC, 
       +         0xF3, 0xF8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, },
       +        {0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x06, 0xC0, 0x1C, 
       +         0xC0, 0x30, 0xC0, 0x30, 0xC0, 0x38, 0xC0, 0x1C, 
       +         0xC0, 0x0E, 0xC0, 0x07, 0xCE, 0x0E, 0xDF, 0x1C, 
       +         0xD3, 0xB8, 0xF1, 0xF0, 0xE0, 0xE0, 0xC0, 0x40, }
       +};
       +
       +Cursor query = {
       +        {-7,-7},
       +        {0x0f, 0xf0, 0x1f, 0xf8, 0x3f, 0xfc, 0x7f, 0xfe, 
       +         0x7c, 0x7e, 0x78, 0x7e, 0x00, 0xfc, 0x01, 0xf8, 
       +         0x03, 0xf0, 0x07, 0xe0, 0x07, 0xc0, 0x07, 0xc0, 
       +         0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xc0, },
       +        {0x00, 0x00, 0x0f, 0xf0, 0x1f, 0xf8, 0x3c, 0x3c, 
       +         0x38, 0x1c, 0x00, 0x3c, 0x00, 0x78, 0x00, 0xf0, 
       +         0x01, 0xe0, 0x03, 0xc0, 0x03, 0x80, 0x03, 0x80, 
       +         0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }
       +};
       +
       +Cursor tl = {
       +        {-4, -4},
       +        {0xfe, 0x00, 0x82, 0x00, 0x8c, 0x00, 0x87, 0xff, 
       +         0xa0, 0x01, 0xb0, 0x01, 0xd0, 0x01, 0x11, 0xff, 
       +         0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 
       +         0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x1f, 0x00, },
       +        {0x00, 0x00, 0x7c, 0x00, 0x70, 0x00, 0x78, 0x00, 
       +         0x5f, 0xfe, 0x4f, 0xfe, 0x0f, 0xfe, 0x0e, 0x00, 
       +         0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 
       +         0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x00, 0x00, }
       +};
       +
       +Cursor t = {
       +        {-7, -8},
       +        {0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x06, 0xc0, 
       +         0x1c, 0x70, 0x10, 0x10, 0x0c, 0x60, 0xfc, 0x7f, 
       +         0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xff, 0xff, 
       +         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
       +        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 
       +         0x03, 0x80, 0x0f, 0xe0, 0x03, 0x80, 0x03, 0x80, 
       +         0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 0x00, 0x00, 
       +         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
       +};
       +
       +Cursor tr = {
       +        {-11, -4},
       +        {0x00, 0x7f, 0x00, 0x41, 0x00, 0x31, 0xff, 0xe1, 
       +         0x80, 0x05, 0x80, 0x0d, 0x80, 0x0b, 0xff, 0x88, 
       +         0x00, 0x88, 0x0, 0x88, 0x00, 0x88, 0x00, 0x88, 
       +         0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0xf8, },
       +        {0x00, 0x00, 0x00, 0x3e, 0x00, 0x0e, 0x00, 0x1e, 
       +         0x7f, 0xfa, 0x7f, 0xf2, 0x7f, 0xf0, 0x00, 0x70, 
       +         0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 
       +         0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x00, }
       +};
       +
       +Cursor r = {
       +        {-8, -7},
       +        {0x07, 0xc0, 0x04, 0x40, 0x04, 0x40, 0x04, 0x58, 
       +         0x04, 0x68, 0x04, 0x6c, 0x04, 0x06, 0x04, 0x02, 
       +         0x04, 0x06, 0x04, 0x6c, 0x04, 0x68, 0x04, 0x58, 
       +         0x04, 0x40, 0x04, 0x40, 0x04, 0x40, 0x07, 0xc0, },
       +        {0x00, 0x00, 0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 
       +         0x03, 0x90, 0x03, 0x90, 0x03, 0xf8, 0x03, 0xfc, 
       +         0x03, 0xf8, 0x03, 0x90, 0x03, 0x90, 0x03, 0x80, 
       +         0x03, 0x80, 0x03, 0x80, 0x03, 0x80, 0x00, 0x00, }
       +};
       +
       +Cursor br = {
       +        {-11, -11},
       +        {0x00, 0xf8, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 
       +         0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 0x00, 0x88, 
       +         0xff, 0x88, 0x80, 0x0b, 0x80, 0x0d, 0x80, 0x05, 
       +         0xff, 0xe1, 0x00, 0x31, 0x00, 0x41, 0x00, 0x7f, },
       +        {0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 
       +         0x0, 0x70, 0x00, 0x70, 0x00, 0x70, 0x00, 0x70, 
       +         0x00, 0x70, 0x7f, 0xf0, 0x7f, 0xf2, 0x7f, 0xfa, 
       +         0x00, 0x1e, 0x00, 0x0e, 0x00, 0x3e, 0x00, 0x00, }
       +};
       +
       +Cursor b = {
       +        {-7, -7},
       +        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
       +         0xff, 0xff, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 
       +         0xfc, 0x7f, 0x0c, 0x60, 0x10, 0x10, 0x1c, 0x70, 
       +         0x06, 0xc0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, },
       +        {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
       +         0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfe, 0x7f, 0xfe, 
       +         0x03, 0x80, 0x03, 0x80, 0x0f, 0xe0, 0x03, 0x80, 
       +         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }
       +};
       +
       +Cursor bl = {
       +        {-4, -11},
       +        {0x1f, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 
       +         0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 0x11, 0x00, 
       +         0x11, 0xff, 0xd0, 0x01, 0xb0, 0x01, 0xa0, 0x01, 
       +         0x87, 0xff, 0x8c, 0x00, 0x82, 0x00, 0xfe, 0x00, },
       +        {0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 
       +         0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0e, 0x00, 
       +         0x0e, 0x00, 0x0f, 0xfe, 0x4f, 0xfe, 0x5f, 0xfe, 
       +         0x78, 0x00, 0x70, 0x00, 0x7c, 0x00, 0x00, 0x0, }
       +};
       +
       +Cursor l = {
       +        {-7, -7},
       +        {0x03, 0xe0, 0x02, 0x20, 0x02, 0x20, 0x1a, 0x20, 
       +         0x16, 0x20, 0x36, 0x20, 0x60, 0x20, 0x40, 0x20, 
       +         0x60, 0x20, 0x36, 0x20, 0x16, 0x20, 0x1a, 0x20, 
       +         0x02, 0x20, 0x02, 0x20, 0x02, 0x20, 0x03, 0xe0, },
       +        {0x00, 0x00, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 
       +         0x09, 0xc0, 0x09, 0xc0, 0x1f, 0xc0, 0x3f, 0xc0, 
       +         0x1f, 0xc0, 0x09, 0xc0, 0x09, 0xc0, 0x01, 0xc0, 
       +         0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x00, 0x00, }
       +};
       +
       +Cursor *corners[9] = {
       +        &tl,        &t,        &tr,
       +        &l,        nil,        &r,
       +        &bl,        &b,        &br,
       +};
       +
       +*/
 (DIR) diff --git a/src/cmd/rio/dat.h b/src/cmd/rio/dat.h
       t@@ -0,0 +1,148 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +
       +#define BORDER                _border
       +#define        INSET                _inset
       +#define MAXHIDDEN        32
       +#define B3FIXED         5
       +
       +#define AllButtonMask        (Button1Mask|Button2Mask|Button3Mask \
       +                        |Button4Mask|Button5Mask)
       +#define ButtonMask        (ButtonPressMask|ButtonReleaseMask)
       +#define MenuMask        (ButtonMask|ButtonMotionMask|ExposureMask)
       +#define MenuGrabMask        (ButtonMask|ButtonMotionMask|StructureNotifyMask)
       +
       +#ifdef        Plan9
       +#define DEFSHELL        "/bin/rc"
       +#else
       +#define DEFSHELL        "/bin/sh"
       +#endif
       +
       +typedef struct Client Client;
       +typedef struct Menu Menu;
       +typedef struct ScreenInfo ScreenInfo;
       +
       +struct Client {
       +        Window                window;
       +        Window                parent;
       +        Window                trans;
       +        Client                *next;
       +        Client                *revert;
       +
       +        int                 x;
       +        int                 y;
       +        int                 dx;
       +        int                 dy;
       +        int                 border;
       +
       +        XSizeHints        size;
       +        int                 min_dx;
       +        int                 min_dy;
       +
       +        int                 state;
       +        int                 init;
       +        int                 reparenting;
       +        int                 is9term;
       +        int                 hold;
       +        int                 proto;
       +
       +        char                *label;
       +        char                *instance;
       +        char                *class;
       +        char                *name;
       +        char                *iconname;
       +
       +        Colormap        cmap;
       +        int                 ncmapwins;
       +        Window                *cmapwins;
       +        Colormap        *wmcmaps;
       +        ScreenInfo        *screen;
       +};
       +
       +#define hidden(c)        ((c)->state == IconicState)
       +#define withdrawn(c)        ((c)->state == WithdrawnState)
       +#define normal(c)        ((c)->state == NormalState)
       +
       +/* c->proto */
       +#define Pdelete         1
       +#define Ptakefocus        2
       +
       +struct Menu {
       +        char        **item;
       +        char        *(*gen)();
       +        int        lasthit;
       +};
       +
       +struct ScreenInfo {
       +        int                        num;
       +        int                        depth;
       +        int                        width;
       +        int                        height;
       +        Window                root;
       +        Window                menuwin;
       +        Window                sweepwin;
       +        Colormap                def_cmap;
       +        GC                        gc;
       +        GC                        gccopy;
       +        GC                        gcred;
       +        GC                        gcsweep;
       +        GC                        gcmenubg;
       +        GC                        gcmenubgs;
       +        GC                        gcmenufg;
       +        GC                        gcmenufgs;
       +        unsigned long        black;
       +        unsigned long        white;
       +        unsigned long        activeholdborder;
       +        unsigned long        inactiveholdborder;
       +        unsigned long        activeborder;
       +        unsigned long        inactiveborder;
       +        unsigned long        red;
       +        Pixmap                bkup[2];
       +        int                        min_cmaps;
       +        Cursor                target;
       +        Cursor                sweep0;
       +        Cursor                boxcurs;
       +        Cursor                arrow;
       +        Pixmap                root_pixmap;
       +        char                        display[256];        /* arbitrary limit */
       +};
       +
       +/* main.c */
       +extern Display                *dpy;
       +extern ScreenInfo        *screens;
       +extern int                        num_screens;
       +extern int                        initting;
       +extern XFontStruct        *font;
       +extern int                        nostalgia;
       +extern char                **myargv;
       +extern Bool                 shape;
       +extern char                 *termprog;
       +extern char                 *shell;
       +extern char                 *version[];
       +extern int                        _border;
       +extern int                        _inset;
       +extern int                        curtime;
       +extern int                        debug;
       +extern int                        solidsweep;
       +
       +extern Atom                exit_9wm;
       +extern Atom                restart_9wm;
       +extern Atom                 wm_state;
       +extern Atom                wm_change_state;
       +extern Atom                 _9wm_hold_mode;
       +extern Atom                 wm_protocols;
       +extern Atom                 wm_delete;
       +extern Atom                 wm_take_focus;
       +extern Atom                 wm_colormaps;
       +
       +/* client.c */
       +extern Client                *clients;
       +extern Client                *current;
       +
       +/* menu.c */
       +extern Client                *hiddenc[];
       +extern int                         numhidden;
       +extern char                 *b3items[];
       +extern Menu                 b3menu;
       +
       +/* error.c */
       +extern int                         ignore_badwindow;
 (DIR) diff --git a/src/cmd/rio/error.c b/src/cmd/rio/error.c
       t@@ -0,0 +1,98 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +#include <stdio.h>
       +#include <X11/X.h>
       +#include <X11/Xlib.h>
       +#include <X11/Xutil.h>
       +#include <X11/Xproto.h>
       +#include "dat.h"
       +#include "fns.h"
       +
       +int         ignore_badwindow;
       +
       +void
       +fatal(char *s)
       +{
       +        fprintf(stderr, "9wm: ");
       +        perror(s);
       +        fprintf(stderr, "\n");
       +        exit(1);
       +}
       +
       +int
       +handler(Display *d, XErrorEvent *e)
       +{
       +        char msg[80], req[80], number[80];
       +
       +        if (initting && (e->request_code == X_ChangeWindowAttributes) && (e->error_code == BadAccess)) {
       +                fprintf(stderr, "9wm: it looks like there's already a window manager running;  9wm not started\n");
       +                exit(1);
       +        }
       +
       +        if (ignore_badwindow && (e->error_code == BadWindow || e->error_code == BadColor))
       +                return 0;
       +
       +        XGetErrorText(d, e->error_code, msg, sizeof(msg));
       +        sprintf(number, "%d", e->request_code);
       +        XGetErrorDatabaseText(d, "XRequest", number, "", req, sizeof(req));
       +        if (req[0] == '\0')
       +                sprintf(req, "<request-code-%d>", e->request_code);
       +
       +        fprintf(stderr, "9wm: %s(0x%x): %s\n", req, e->resourceid, msg);
       +
       +        if (initting) {
       +                fprintf(stderr, "9wm: failure during initialisation; aborting\n");
       +                exit(1);
       +        }
       +        return 0;
       +}
       +
       +void
       +graberror(char *f, int err)
       +{
       +#ifdef        DEBUG        /* sick of "bug" reports; grab errors "just happen" */
       +        char *s;
       +
       +        switch (err) {
       +        case GrabNotViewable:
       +                s = "not viewable";
       +                break;
       +        case AlreadyGrabbed:
       +                s = "already grabbed";
       +                break;
       +        case GrabFrozen:
       +                s = "grab frozen";
       +                break;
       +        case GrabInvalidTime:
       +                s = "invalid time";
       +                break;
       +        case GrabSuccess:
       +                return;
       +        default:
       +                fprintf(stderr, "9wm: %s: grab error: %d\n", f, err);
       +                return;
       +        }
       +        fprintf(stderr, "9wm: %s: grab error: %s\n", f, s);
       +#endif
       +}
       +
       +#ifdef        DEBUG_EV
       +#include "showevent/ShowEvent.c"
       +#endif
       +
       +#ifdef        DEBUG
       +
       +void
       +dotrace(char *s, Client *c, XEvent *e)
       +{
       +        fprintf(stderr, "9wm: %s: c=0x%x", s, c);
       +        if (c)
       +                fprintf(stderr, " x %d y %d dx %d dy %d w 0x%x parent 0x%x", c->x, c->y, c->dx, c->dy, c->window, c->parent);
       +#ifdef        DEBUG_EV
       +        if (e) {
       +                fprintf(stderr, "\n\t");
       +                ShowEvent(e);
       +        }
       +#endif
       +        fprintf(stderr, "\n");
       +}
       +#endif
 (DIR) diff --git a/src/cmd/rio/event.c b/src/cmd/rio/event.c
       t@@ -0,0 +1,465 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +#include <stdio.h>
       +#include <X11/X.h>
       +#include <X11/Xos.h>
       +#include <X11/Xlib.h>
       +#include <X11/Xutil.h>
       +#include <X11/Xatom.h>
       +#include <X11/extensions/shape.h>
       +#include "dat.h"
       +#include "fns.h"
       +#include "patchlevel.h"
       +
       +void
       +mainloop(int shape_event)
       +{
       +        XEvent ev;
       +
       +        for (;;) {
       +                getevent(&ev);
       +
       +#ifdef        DEBUG_EV
       +                if (debug) {
       +                        ShowEvent(&ev);
       +                        printf("\n");
       +                }
       +#endif
       +                switch (ev.type) {
       +                default:
       +#ifdef        SHAPE
       +                        if (shape && ev.type == shape_event)
       +                                shapenotify((XShapeEvent *)&ev);
       +                        else
       +#endif
       +                                fprintf(stderr, "9wm: unknown ev.type %d\n", ev.type);
       +                        break;
       +                case ButtonPress:
       +                        button(&ev.xbutton);
       +                        break;
       +                case ButtonRelease:
       +                        break;
       +                case MapRequest:
       +                        mapreq(&ev.xmaprequest);
       +                        break;
       +                case ConfigureRequest:
       +                        configurereq(&ev.xconfigurerequest);
       +                        break;
       +                case CirculateRequest:
       +                        circulatereq(&ev.xcirculaterequest);
       +                        break;
       +                case UnmapNotify:
       +                        unmap(&ev.xunmap);
       +                        break;
       +                case CreateNotify:
       +                        newwindow(&ev.xcreatewindow);
       +                        break;
       +                case DestroyNotify:
       +                        destroy(ev.xdestroywindow.window);
       +                        break;
       +                case ClientMessage:
       +                        clientmesg(&ev.xclient);
       +                        break;
       +                case ColormapNotify:
       +                        cmap(&ev.xcolormap);
       +                        break;
       +                case PropertyNotify:
       +                        property(&ev.xproperty);
       +                        break;
       +                case SelectionClear:
       +                        fprintf(stderr, "9wm: SelectionClear (this should not happen)\n");
       +                        break;
       +                case SelectionNotify:
       +                        fprintf(stderr, "9wm: SelectionNotify (this should not happen)\n");
       +                        break;
       +                case SelectionRequest:
       +                        fprintf(stderr, "9wm: SelectionRequest (this should not happen)\n");
       +                        break;
       +                case EnterNotify:
       +                        enter(&ev.xcrossing);
       +                        break;
       +                case ReparentNotify:
       +                        reparent(&ev.xreparent);
       +                        break;
       +                case FocusIn:
       +                        focusin(&ev.xfocus);
       +                        break;
       +                case MotionNotify:
       +                case Expose:
       +                case NoExpose:
       +                case FocusOut:
       +                case ConfigureNotify:
       +                case MapNotify:
       +                case MappingNotify:
       +                        /* not interested */
       +                        trace("ignore", 0, &ev);
       +                        break;
       +                }
       +        }
       +}
       +
       +
       +void
       +configurereq(XConfigureRequestEvent *e)
       +{
       +        XWindowChanges wc;
       +        Client *c;
       +
       +        /* we don't set curtime as nothing here uses it */
       +        c = getclient(e->window, 0);
       +        trace("configurereq", c, e);
       +
       +        e->value_mask &= ~CWSibling;
       +
       +        if (c) {
       +                gravitate(c, 1);
       +                if (e->value_mask & CWX)
       +                        c->x = e->x;
       +                if (e->value_mask & CWY)
       +                        c->y = e->y;
       +                if (e->value_mask & CWWidth)
       +                        c->dx = e->width;
       +                if (e->value_mask & CWHeight)
       +                        c->dy = e->height;
       +                if (e->value_mask & CWBorderWidth)
       +                        c->border = e->border_width;
       +                gravitate(c, 0);
       +                if (e->value_mask & CWStackMode) {
       +                        if (wc.stack_mode == Above)
       +                                top(c);
       +                        else
       +                                e->value_mask &= ~CWStackMode;
       +                }
       +                if (c->parent != c->screen->root && c->window == e->window) {
       +                        wc.x = c->x-BORDER;
       +                        wc.y = c->y-BORDER;
       +                        wc.width = c->dx+2*BORDER;
       +                        wc.height = c->dy+2*BORDER;
       +                        wc.border_width = 1;
       +                        wc.sibling = None;
       +                        wc.stack_mode = e->detail;
       +                        XConfigureWindow(dpy, c->parent, e->value_mask, &wc);
       +                        sendconfig(c);
       +                }
       +        }
       +
       +        if (c && c->init) {
       +                wc.x = BORDER;
       +                wc.y = BORDER;
       +        }
       +        else {
       +                wc.x = e->x;
       +                wc.y = e->y;
       +        }
       +        wc.width = e->width;
       +        wc.height = e->height;
       +        wc.border_width = 0;
       +        wc.sibling = None;
       +        wc.stack_mode = Above;
       +        e->value_mask &= ~CWStackMode;
       +        e->value_mask |= CWBorderWidth;
       +
       +        XConfigureWindow(dpy, e->window, e->value_mask, &wc);
       +}
       +
       +void
       +mapreq(XMapRequestEvent *e)
       +{
       +        Client *c;
       +        int i;
       +
       +        curtime = CurrentTime;
       +        c = getclient(e->window, 0);
       +        trace("mapreq", c, e);
       +
       +        if (c == 0 || c->window != e->window) {
       +                /* workaround for stupid NCDware */
       +                fprintf(stderr, "9wm: bad mapreq c %x w %x, rescanning\n",
       +                        c, e->window);
       +                for (i = 0; i < num_screens; i++)
       +                        scanwins(&screens[i]);
       +                c = getclient(e->window, 0);
       +                if (c == 0 || c->window != e->window) {
       +                        fprintf(stderr, "9wm: window not found after rescan\n");
       +                        return;
       +                }
       +        }
       +
       +        switch (c->state) {
       +        case WithdrawnState:
       +                if (c->parent == c->screen->root) {
       +                        if (!manage(c, 0))
       +                                return;
       +                        break;
       +                }
       +                XReparentWindow(dpy, c->window, c->parent, BORDER-1, BORDER-1);
       +                XAddToSaveSet(dpy, c->window);
       +                /* fall through... */
       +        case NormalState:
       +                XMapWindow(dpy, c->window);
       +                XMapRaised(dpy, c->parent);
       +                top(c);
       +                setstate(c, NormalState);
       +                if (c->trans != None && current && c->trans == current->window)
       +                                active(c);
       +                break;
       +        case IconicState:
       +                unhidec(c, 1);
       +                break;
       +        }
       +}
       +
       +void
       +unmap(XUnmapEvent *e)
       +{
       +        Client *c;
       +
       +        curtime = CurrentTime;
       +        c = getclient(e->window, 0);
       +        if (c) {
       +                switch (c->state) {
       +                case IconicState:
       +                        if (e->send_event) {
       +                                unhidec(c, 0);
       +                                withdraw(c);
       +                        }
       +                        break;
       +                case NormalState:
       +                        if (c == current)
       +                                nofocus();
       +                        if (!c->reparenting)
       +                                withdraw(c);
       +                        break;
       +                }
       +                c->reparenting = 0;
       +        }
       +}
       +
       +void
       +circulatereq(XCirculateRequestEvent *e)
       +{
       +        fprintf(stderr, "It must be the warlock Krill!\n");  /* ☺ */
       +}
       +
       +void
       +newwindow(XCreateWindowEvent *e)
       +{
       +        Client *c;
       +        ScreenInfo *s;
       +
       +        /* we don't set curtime as nothing here uses it */
       +        if (e->override_redirect)
       +                return;
       +        c = getclient(e->window, 1);
       +        if (c && c->window == e->window && (s = getscreen(e->parent))) {
       +                c->x = e->x;
       +                c->y = e->y;
       +                c->dx = e->width;
       +                c->dy = e->height;
       +                c->border = e->border_width;
       +                c->screen = s;
       +                if (c->parent == None)
       +                        c->parent = c->screen->root;
       +        }
       +}
       +
       +void
       +destroy(Window w)
       +{
       +        Client *c;
       +
       +        curtime = CurrentTime;
       +        c = getclient(w, 0);
       +        if (c == 0)
       +                return;
       +
       +        rmclient(c);
       +
       +        /* flush any errors generated by the window's sudden demise */
       +        ignore_badwindow = 1;
       +        XSync(dpy, False);
       +        ignore_badwindow = 0;
       +}
       +
       +void
       +clientmesg(XClientMessageEvent *e)
       +{
       +        Client *c;
       +
       +        curtime = CurrentTime;
       +        if (e->message_type == exit_9wm) {
       +                cleanup();
       +                exit(0);
       +        }
       +        if (e->message_type == restart_9wm) {
       +                fprintf(stderr, "*** 9wm restarting ***\n");
       +                cleanup();
       +                execvp(myargv[0], myargv);
       +                perror("9wm: exec failed");
       +                exit(1);
       +        }
       +        if (e->message_type == wm_change_state) {
       +                c = getclient(e->window, 0);
       +                if (e->format == 32 && e->data.l[0] == IconicState && c != 0) {
       +                        if (normal(c))
       +                                hide(c);
       +                }
       +                else
       +                        fprintf(stderr, "9wm: WM_CHANGE_STATE: format %d data %d w 0x%x\n",
       +                                e->format, e->data.l[0], e->window);
       +                return;
       +        }
       +        fprintf(stderr, "9wm: strange ClientMessage, type 0x%x window 0x%x\n",
       +                e->message_type, e->window);
       +}
       +
       +void
       +cmap(XColormapEvent *e)
       +{
       +        Client *c;
       +        int i;
       +
       +        /* we don't set curtime as nothing here uses it */
       +        if (e->new) {
       +                c = getclient(e->window, 0);
       +                if (c) {
       +                        c->cmap = e->colormap;
       +                        if (c == current)
       +                                cmapfocus(c);
       +                }
       +                else
       +                        for (c = clients; c; c = c->next) {
       +                                for (i = 0; i < c->ncmapwins; i++)
       +                                        if (c->cmapwins[i] == e->window) {
       +                                                c->wmcmaps[i] = e->colormap;
       +                                                if (c == current)
       +                                                        cmapfocus(c);
       +                                                return;
       +                                        }
       +                        }
       +        }
       +}
       +
       +void
       +property(XPropertyEvent *e)
       +{
       +        Atom a;
       +        int delete;
       +        Client *c;
       +
       +        /* we don't set curtime as nothing here uses it */
       +        a = e->atom;
       +        delete = (e->state == PropertyDelete);
       +        c = getclient(e->window, 0);
       +        if (c == 0)
       +                return;
       +
       +        switch (a) {
       +        case XA_WM_ICON_NAME:
       +                if (c->iconname != 0)
       +                        XFree((char*) c->iconname);
       +                c->iconname = delete ? 0 : getprop(c->window, a);
       +                setlabel(c);
       +                renamec(c, c->label);
       +                return;
       +        case XA_WM_NAME:
       +                if (c->name != 0)
       +                        XFree((char*) c->name);
       +                c->name = delete ? 0 : getprop(c->window, a);
       +                setlabel(c);
       +                renamec(c, c->label);
       +                return;
       +        case XA_WM_TRANSIENT_FOR:
       +                gettrans(c);
       +                return;
       +        }
       +        if (a == _9wm_hold_mode) {
       +                c->hold = getiprop(c->window, _9wm_hold_mode);
       +                if (c == current)
       +                        draw_border(c, 1);
       +        }
       +        else if (a == wm_colormaps) {
       +                getcmaps(c);
       +                if (c == current)
       +                        cmapfocus(c);
       +        }
       +}
       +
       +void
       +reparent(XReparentEvent *e)
       +{
       +        Client *c;
       +        XWindowAttributes attr;
       +        ScreenInfo *s;
       +
       +        /* we don't set curtime as nothing here uses it */
       +        if (!getscreen(e->event) || e->override_redirect)
       +                return;
       +        if ((s = getscreen(e->parent)) != 0) {
       +                c = getclient(e->window, 1);
       +                if (c != 0 && (c->dx == 0 || c->dy == 0)) {
       +                        XGetWindowAttributes(dpy, c->window, &attr);
       +                        c->x = attr.x;
       +                        c->y = attr.y;
       +                        c->dx = attr.width;
       +                        c->dy = attr.height;
       +                        c->border = attr.border_width;
       +                        c->screen = s;
       +                        if (c->parent == None)
       +                                c->parent = c->screen->root;
       +                }
       +        }
       +        else {
       +                c = getclient(e->window, 0);
       +                if (c != 0 && (c->parent == c->screen->root || withdrawn(c)))
       +                        rmclient(c);
       +        }
       +}
       +
       +#ifdef        SHAPE
       +void
       +shapenotify(XShapeEvent *e)
       +{
       +        Client *c;
       +
       +        /* we don't set curtime as nothing here uses it */
       +        c = getclient(e->window, 0);
       +        if (c == 0)
       +                return;
       +
       +        setshape(c);
       +}
       +#endif
       +
       +void
       +enter(XCrossingEvent *e)
       +{
       +        Client *c;
       +
       +        curtime = e->time;
       +        if (e->mode != NotifyGrab || e->detail != NotifyNonlinearVirtual)
       +                return;
       +        c = getclient(e->window, 0);
       +        if (c != 0 && c != current) {
       +                /* someone grabbed the pointer; make them current */
       +                XMapRaised(dpy, c->parent);
       +                top(c);
       +                active(c);
       +        }
       +}
       +
       +void
       +focusin(XFocusChangeEvent *e)
       +{
       +        Client *c;
       +
       +        curtime = CurrentTime;
       +        if (e->detail != NotifyNonlinearVirtual)
       +                return;
       +        c = getclient(e->window, 0);
       +        if (c != 0 && c->window == e->window && c != current) {
       +                /* someone grabbed keyboard or seized focus; make them current */
       +                XMapRaised(dpy, c->parent);
       +                top(c);
       +                active(c);
       +        }
       +}
 (DIR) diff --git a/src/cmd/rio/fns.h b/src/cmd/rio/fns.h
       t@@ -0,0 +1,96 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +
       +#ifdef        DEBUG
       +#define        trace(s, c, e)        dotrace((s), (c), (e))
       +#else
       +#define        trace(s, c, e)
       +#endif
       +
       +/* color.c */
       +unsigned long colorpixel(Display*, int, unsigned long);
       +
       +/* main.c */
       +void        usage();
       +void        initscreen();
       +ScreenInfo *getscreen();
       +Time        timestamp();
       +void        sendcmessage();
       +void        sendconfig();
       +void        sighandler();
       +void        getevent();
       +void        cleanup();
       +
       +/* event.c */
       +void        mainloop();
       +void        configurereq();
       +void        mapreq();
       +void        circulatereq();
       +void        unmap();
       +void        newwindow();
       +void        destroy();
       +void        clientmesg();
       +void        cmap();
       +void        property();
       +void        shapenotify();
       +void        enter();
       +void        focusin();
       +void        reparent();
       +
       +/* manage.c */
       +int         manage();
       +void        scanwins();
       +void        setshape();
       +void        withdraw();
       +void        gravitate();
       +void        cmapfocus();
       +void        cmapnofocus();
       +void        getcmaps();
       +int         _getprop();
       +char        *getprop();
       +Window        getwprop();
       +int         getiprop();
       +int         getstate();
       +void        setstate();
       +void        setlabel();
       +void        getproto();
       +void        gettrans();
       +
       +/* menu.c */
       +void        button();
       +void        spawn();
       +void        reshape();
       +void        move();
       +void        delete();
       +void        hide();
       +void        unhide();
       +void        unhidec();
       +void        renamec();
       +
       +/* client.c */
       +void        setactive();
       +void        draw_border();
       +void        active();
       +void        nofocus();
       +void        top();
       +Client        *getclient();
       +void        rmclient();
       +void        dump_revert();
       +void        dump_clients();
       +
       +/* grab.c */
       +int         menuhit();
       +Client        *selectwin();
       +int         sweep();
       +int         drag();
       +void        getmouse();
       +void        setmouse();
       +
       +/* error.c */
       +int         handler();
       +void        fatal();
       +void        graberror();
       +void        showhints();
       +void        dotrace();
       +
       +/* cursor.c */
       +void        initcurs();
 (DIR) diff --git a/src/cmd/rio/grab.c b/src/cmd/rio/grab.c
       t@@ -0,0 +1,498 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +#include <stdio.h>
       +#include <X11/X.h>
       +#include <X11/Xos.h>
       +#include <X11/Xlib.h>
       +#include <X11/Xutil.h>
       +#include "dat.h"
       +#include "fns.h"
       +
       +int
       +nobuttons(XButtonEvent *e)        /* Einstuerzende */
       +{
       +        int state;
       +
       +        state = (e->state & AllButtonMask);
       +        return (e->type == ButtonRelease) && (state & (state - 1)) == 0;
       +}
       +
       +int
       +grab(Window w, Window constrain, int mask, Cursor curs, int t)
       +{
       +        int status;
       +
       +        if (t == 0)
       +                t = timestamp();
       +        status = XGrabPointer(dpy, w, False, mask,
       +                GrabModeAsync, GrabModeAsync, constrain, curs, t);
       +        return status;
       +}
       +
       +void
       +ungrab(XButtonEvent *e)
       +{
       +        XEvent ev;
       +
       +        if (!nobuttons(e))
       +                for (;;) {
       +                        XMaskEvent(dpy, ButtonMask | ButtonMotionMask, &ev);
       +                        if (ev.type == MotionNotify)
       +                                continue;
       +                        e = &ev.xbutton;
       +                        if (nobuttons(e))
       +                                break;
       +                }
       +        XUngrabPointer(dpy, e->time);
       +        curtime = e->time;
       +}
       +
       +static void
       +drawstring(Display *dpy, ScreenInfo *s, Menu *m, int wide, int high, int i, int selected)
       +{
       +        int tx, ty;
       +
       +        tx = (wide - XTextWidth(font, m->item[i], strlen(m->item[i])))/2;
       +        ty = i*high + font->ascent + 1;
       +        XFillRectangle(dpy, s->menuwin, selected ? s->gcmenubgs : s->gcmenubg, 0, i*high, wide, high);
       +        XDrawString(dpy, s->menuwin, selected ? s->gcmenufgs : s->gcmenufg, tx, ty, m->item[i], strlen(m->item[i]));
       +}
       +
       +int
       +menuhit(XButtonEvent *e, Menu *m)
       +{
       +        XEvent ev;
       +        int i, n, cur, old, wide, high, status, drawn, warp;
       +        int x, y, dx, dy, xmax, ymax;
       +        int tx, ty;
       +        ScreenInfo *s;
       +
       +        if (font == 0)
       +                return -1;
       +        s = getscreen(e->root);
       +        if (s == 0 || e->window == s->menuwin)           /* ugly event mangling */
       +                return -1;
       +
       +        dx = 0;
       +        for (n = 0; m->item[n]; n++) {
       +                wide = XTextWidth(font, m->item[n], strlen(m->item[n])) + 4;
       +                if (wide > dx)
       +                        dx = wide;
       +        }
       +        wide = dx;
       +        cur = m->lasthit;
       +        if (cur >= n)
       +                cur = n - 1;
       +
       +        high = font->ascent + font->descent + 1;
       +        dy = n*high;
       +        x = e->x - wide/2;
       +        y = e->y - cur*high - high/2;
       +        warp = 0;
       +        xmax = DisplayWidth(dpy, s->num);
       +        ymax = DisplayHeight(dpy, s->num);
       +        if (x < 0) {
       +                e->x -= x;
       +                x = 0;
       +                warp++;
       +        }
       +        if (x+wide >= xmax) {
       +                e->x -= x+wide-xmax;
       +                x = xmax-wide;
       +                warp++;
       +        }
       +        if (y < 0) {
       +                e->y -= y;
       +                y = 0;
       +                warp++;
       +        }
       +        if (y+dy >= ymax) {
       +                e->y -= y+dy-ymax;
       +                y = ymax-dy;
       +                warp++;
       +        }
       +        if (warp)
       +                setmouse(e->x, e->y, s);
       +        XMoveResizeWindow(dpy, s->menuwin, x, y, dx, dy);
       +        XSelectInput(dpy, s->menuwin, MenuMask);
       +        XMapRaised(dpy, s->menuwin);
       +        status = grab(s->menuwin, None, MenuGrabMask, None, e->time);
       +        if (status != GrabSuccess) {
       +                /* graberror("menuhit", status); */
       +                XUnmapWindow(dpy, s->menuwin);
       +                return -1;
       +        }
       +        drawn = 0;
       +        for (;;) {
       +                XMaskEvent(dpy, MenuMask, &ev);
       +                switch (ev.type) {
       +                default:
       +                        fprintf(stderr, "9wm: menuhit: unknown ev.type %d\n", ev.type);
       +                        break;
       +                case ButtonPress:
       +                        break;
       +                case ButtonRelease:
       +                        if (ev.xbutton.button != e->button)
       +                                break;
       +                        x = ev.xbutton.x;
       +                        y = ev.xbutton.y;
       +                        i = y/high;
       +                        if (cur >= 0 && y >= cur*high-3 && y < (cur+1)*high+3)
       +                                i = cur;
       +                        if (x < 0 || x > wide || y < -3)
       +                                i = -1;
       +                        else if (i < 0 || i >= n)
       +                                i = -1;
       +                        else
       +                                m->lasthit = i;
       +                        if (!nobuttons(&ev.xbutton))
       +                                i = -1;
       +                        ungrab(&ev.xbutton);
       +                        XUnmapWindow(dpy, s->menuwin);
       +                        return i;
       +                case MotionNotify:
       +                        if (!drawn)
       +                                break;
       +                        x = ev.xbutton.x;
       +                        y = ev.xbutton.y;
       +                        old = cur;
       +                        cur = y/high;
       +                        if (old >= 0 && y >= old*high-3 && y < (old+1)*high+3)
       +                                cur = old;
       +                        if (x < 0 || x > wide || y < -3)
       +                                cur = -1;
       +                        else if (cur < 0 || cur >= n)
       +                                cur = -1;
       +                        if (cur == old)
       +                                break;
       +                        if (old >= 0 && old < n)
       +                                drawstring(dpy, s, m, wide, high, old, 0);
       +                        if (cur >= 0 && cur < n)
       +                                drawstring(dpy, s, m, wide, high, cur, 1);
       +                        break;
       +                case Expose:
       +                        XClearWindow(dpy, s->menuwin);
       +                        for (i = 0; i < n; i++)
       +                                drawstring(dpy, s, m, wide, high, i, cur==i);
       +                        drawn = 1;
       +                }
       +        }
       +}
       +
       +Client *
       +selectwin(int release, int *shift, ScreenInfo *s)
       +{
       +        XEvent ev;
       +        XButtonEvent *e;
       +        int status;
       +        Window w;
       +        Client *c;
       +
       +        status = grab(s->root, s->root, ButtonMask, s->target, 0);
       +        if (status != GrabSuccess) {
       +                graberror("selectwin", status); /* */
       +                return 0;
       +        }
       +        w = None;
       +        for (;;) {
       +                XMaskEvent(dpy, ButtonMask, &ev);
       +                e = &ev.xbutton;
       +                switch (ev.type) {
       +                case ButtonPress:
       +                        if (e->button != Button3) {
       +                                ungrab(e);
       +                                return 0;
       +                        }
       +                        w = e->subwindow;
       +                        if (!release) {
       +                                c = getclient(w, 0);
       +                                if (c == 0)
       +                                        ungrab(e);
       +                                if (shift != 0)
       +                                        *shift = (e->state&ShiftMask) != 0;
       +                                return c;
       +                        }
       +                        break;
       +                case ButtonRelease:
       +                        ungrab(e);
       +                        if (e->button != Button3 || e->subwindow != w)
       +                                return 0;
       +                        if (shift != 0)
       +                                *shift = (e->state&ShiftMask) != 0;
       +                        return getclient(w, 0);
       +                }
       +        }
       +}
       +
       +void
       +sweepcalc(Client *c, int x, int y)
       +{
       +        int dx, dy, sx, sy;
       +
       +        dx = x - c->x;
       +        dy = y - c->y;
       +        sx = sy = 1;
       +        if (dx < 0) {
       +                dx = -dx;
       +                sx = -1;
       +        }
       +        if (dy < 0) {
       +                dy = -dy;
       +                sy = -1;
       +        }
       +
       +        dx -= 2*BORDER;
       +        dy -= 2*BORDER;
       +
       +        if (!c->is9term) {
       +                if (dx < c->min_dx)
       +                        dx = c->min_dx;
       +                if (dy < c->min_dy)
       +                        dy = c->min_dy;
       +        }
       +
       +        if (c->size.flags & PResizeInc) {
       +                dx = c->min_dx + (dx-c->min_dx)/c->size.width_inc*c->size.width_inc;
       +                dy = c->min_dy + (dy-c->min_dy)/c->size.height_inc*c->size.height_inc;
       +        }
       +
       +        if (c->size.flags & PMaxSize) {
       +                if (dx > c->size.max_width)
       +                        dx = c->size.max_width;
       +                if (dy > c->size.max_height)
       +                        dy = c->size.max_height;
       +        }
       +        c->dx = sx*(dx + 2*BORDER);
       +        c->dy = sy*(dy + 2*BORDER);
       +}
       +
       +void
       +dragcalc(Client *c, int x, int y)
       +{
       +        c->x = x;
       +        c->y = y;
       +}
       +
       +static void
       +xcopy(int fwd, Display *dpy, Drawable src, Drawable dst, GC gc, int x, int y, int dx, int dy, int x1, int y1)
       +{
       +        if(fwd)
       +                XCopyArea(dpy, src, dst, gc, x, y, dx, dy, x1, y1);
       +        else
       +                XCopyArea(dpy, dst, src, gc, x1, y1, dx, dy, x, y);
       +}
       +
       +void
       +drawbound(Client *c, int drawing)
       +{
       +        int x, y, dx, dy;
       +        ScreenInfo *s;
       +        
       +        s = c->screen;
       +        x = c->x;
       +        y = c->y;
       +        dx = c->dx;
       +        dy = c->dy;
       +        if (dx < 0) {
       +                x += dx;
       +                dx = -dx;
       +        }
       +        if (dy < 0) {
       +                y += dy;
       +                dy = -dy;
       +        }
       +        if (dx <= 2 || dy <= 2)
       +                return;
       +
       +        if(solidsweep){
       +                if(drawing == -1){
       +                        XUnmapWindow(dpy, s->sweepwin);
       +                        return;
       +                }
       +                
       +                x += BORDER;
       +                y += BORDER;
       +                dx -= 2*BORDER;
       +                dy -= 2*BORDER;
       +
       +                if(drawing){
       +                        XMoveResizeWindow(dpy, s->sweepwin, x, y, dx, dy);
       +                        XSelectInput(dpy, s->sweepwin, MenuMask);
       +                        XMapRaised(dpy, s->sweepwin);
       +                }
       +                return;
       +        }
       +
       +        if(drawing == -1)
       +                return;
       +
       +        xcopy(drawing, dpy, s->root, s->bkup[0], s->gccopy, x, y, dx, BORDER, 0, 0);
       +        xcopy(drawing, dpy, s->root, s->bkup[0], s->gccopy, x, y+dy-BORDER, dx, BORDER, dx, 0);
       +        xcopy(drawing, dpy, s->root, s->bkup[1], s->gccopy, x, y, BORDER, dy, 0, 0);
       +        xcopy(drawing, dpy, s->root, s->bkup[1], s->gccopy, x+dx-BORDER, y, BORDER, dy, 0, dy);
       +
       +        if(drawing){
       +                XFillRectangle(dpy, s->root, s->gcred, x, y, dx, BORDER);
       +                XFillRectangle(dpy, s->root, s->gcred, x, y+dy-BORDER, dx, BORDER);
       +                XFillRectangle(dpy, s->root, s->gcred, x, y, BORDER, dy);
       +                XFillRectangle(dpy, s->root, s->gcred, x+dx-BORDER, y, BORDER, dy);
       +        }
       +}
       +
       +void
       +misleep(int msec)
       +{
       +        struct timeval t;
       +
       +        t.tv_sec = msec/1000;
       +        t.tv_usec = (msec%1000)*1000;
       +        select(0, 0, 0, 0, &t);
       +}
       +
       +int
       +sweepdrag(Client *c, XButtonEvent *e0, void (*recalc)(Client*, int, int))
       +{
       +        XEvent ev;
       +        int idle;
       +        int cx, cy, rx, ry;
       +        int ox, oy, odx, ody;
       +        XButtonEvent *e;
       +
       +        ox = c->x;
       +        oy = c->y;
       +        odx = c->dx;
       +        ody = c->dy;
       +        c->x -= BORDER;
       +        c->y -= BORDER;
       +        c->dx += 2*BORDER;
       +        c->dy += 2*BORDER;
       +        if (e0) {
       +                c->x = cx = e0->x;
       +                c->y = cy = e0->y;
       +                recalc(c, e0->x, e0->y);
       +        }
       +        else
       +                getmouse(&cx, &cy, c->screen);
       +        XGrabServer(dpy);
       +        drawbound(c, 1);
       +        idle = 0;
       +        for (;;) {
       +                if (XCheckMaskEvent(dpy, ButtonMask, &ev) == 0) {
       +                        getmouse(&rx, &ry, c->screen);
       +                        if (rx != cx || ry != cy || ++idle > 300) {
       +                                drawbound(c, 0);
       +                                if (rx == cx && ry == cy) {
       +                                        XUngrabServer(dpy);
       +                                        XFlush(dpy);
       +                                        misleep(500);
       +                                        XGrabServer(dpy);
       +                                        idle = 0;
       +                                }
       +                                recalc(c, rx, ry);
       +                                cx = rx;
       +                                cy = ry;
       +                                drawbound(c, 1);
       +                                XFlush(dpy);
       +                        }
       +                        misleep(50);
       +                        continue;
       +                }
       +                e = &ev.xbutton;
       +                switch (ev.type) {
       +                case ButtonPress:
       +                case ButtonRelease:
       +                        drawbound(c, 0);
       +                        ungrab(e);
       +                        XUngrabServer(dpy);
       +                        if (e->button != Button3 && c->init)
       +                                goto bad;
       +                        recalc(c, ev.xbutton.x, ev.xbutton.y);
       +                        if (c->dx < 0) {
       +                                c->x += c->dx;
       +                                c->dx = -c->dx;
       +                        }
       +                        if (c->dy < 0) {
       +                                c->y += c->dy;
       +                                c->dy = -c->dy;
       +                        }
       +                        c->x += BORDER;
       +                        c->y += BORDER;
       +                        c->dx -= 2*BORDER;
       +                        c->dy -= 2*BORDER;
       +                        if (c->dx < 4 || c->dy < 4 || c->dx < c->min_dx || c->dy < c->min_dy)
       +                                goto bad;
       +                        return 1;
       +                }
       +        }
       +bad:
       +        c->x = ox;
       +        c->y = oy;
       +        c->dx = odx;
       +        c->dy = ody;
       +        drawbound(c, -1);
       +        return 0;
       +}
       +
       +int
       +sweep(Client *c)
       +{
       +        XEvent ev;
       +        int status;
       +        XButtonEvent *e;
       +        ScreenInfo *s;
       +
       +        s = c->screen;
       +        status = grab(s->root, s->root, ButtonMask, s->sweep0, 0);
       +        if (status != GrabSuccess) {
       +                graberror("sweep", status); /* */
       +                return 0;
       +        }
       +
       +        XMaskEvent(dpy, ButtonMask, &ev);
       +        e = &ev.xbutton;
       +        if (e->button != Button3) {
       +                ungrab(e);
       +                return 0;
       +        }
       +        if (c->size.flags & (PMinSize|PBaseSize))
       +                 setmouse(e->x+c->min_dx, e->y+c->min_dy, s);
       +        XChangeActivePointerGrab(dpy, ButtonMask, s->boxcurs, e->time);
       +        return sweepdrag(c, e, sweepcalc);
       +}
       +
       +int
       +drag(Client *c)
       +{
       +        int status;
       +        ScreenInfo *s;
       +
       +        s = c->screen;
       +        if (c->init)
       +                setmouse(c->x-BORDER, c->y-BORDER, s);
       +        else {
       +                getmouse(&c->x, &c->y, s);                   /* start at current mouse pos */
       +                c->x += BORDER;
       +                c->y += BORDER;
       +        }
       +        status = grab(s->root, s->root, ButtonMask, s->boxcurs, 0);
       +        if (status != GrabSuccess) {
       +                graberror("drag", status); /* */
       +                return 0;
       +        }
       +        return sweepdrag(c, 0, dragcalc);
       +}
       +
       +void
       +getmouse(int *x, int *y, ScreenInfo *s)
       +{
       +        Window dw1, dw2;
       +        int t1, t2;
       +        unsigned int t3;
       +
       +        XQueryPointer(dpy, s->root, &dw1, &dw2, x, y, &t1, &t2, &t3);
       +}
       +
       +void
       +setmouse(int x, int y, ScreenInfo *s)
       +{
       +        XWarpPointer(dpy, None, s->root, None, None, None, None, x, y);
       +}
 (DIR) diff --git a/src/cmd/rio/main.c b/src/cmd/rio/main.c
       t@@ -0,0 +1,437 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +#include <stdio.h>
       +#include <signal.h>
       +#include <errno.h>
       +#include <X11/X.h>
       +#include <X11/Xos.h>
       +#include <X11/Xlib.h>
       +#include <X11/Xutil.h>
       +#include <X11/Xatom.h>
       +#include "dat.h"
       +#include "fns.h"
       +#include "patchlevel.h"
       +
       +char        *version[] =
       +{
       +        "rio version 1.0, Copyright (c) 1994-1996 David Hogan, (c) 2004 Russ Cox", 0,
       +};
       +
       +Display                 *dpy;
       +ScreenInfo        *screens;
       +int                         initting;
       +XFontStruct         *font;
       +int                         nostalgia;
       +char                        **myargv;
       +char                        *termprog;
       +char                        *shell;
       +Bool                        shape;
       +int                         _border = 4;
       +int                         _inset = 1;
       +int                         curtime;
       +int                         debug;
       +int                         signalled;
       +int                         num_screens;
       +int                        solidsweep = 0;
       +
       +Atom                exit_9wm;
       +Atom                restart_9wm;
       +Atom                wm_state;
       +Atom                wm_change_state;
       +Atom                wm_protocols;
       +Atom                wm_delete;
       +Atom                wm_take_focus;
       +Atom                wm_colormaps;
       +Atom                _9wm_running;
       +Atom                _9wm_hold_mode;
       +
       +char        *fontlist[] = {
       +        "lucm.latin1.9",
       +        "blit",
       +        "lucidasanstypewriter-bold-10",
       +        "9x15bold",
       +        "fixed",
       +        "*",
       +        0,
       +};
       +
       +void
       +usage(void)
       +{
       +        fprintf(stderr, "usage: rio [-grey] [-version] [-font fname] [-term prog] [exit|restart]\n");
       +        exit(1);
       +}
       +
       +int
       +main(int argc, char *argv[])
       +{
       +        int i, background, do_exit, do_restart;
       +        char *fname;
       +        int shape_event, dummy;
       +
       +        myargv = argv;                        /* for restart */
       +
       +        do_exit = do_restart = 0;
       +        background = 1;
       +        font = 0;
       +        fname = 0;
       +        for (i = 1; i < argc; i++)
       +                if (strcmp(argv[i], "-nostalgia") == 0)
       +                        nostalgia++;
       +                else if (strcmp(argv[i], "-grey") == 0)
       +                        background = 1;
       +                else if (strcmp(argv[i], "-debug") == 0)
       +                        debug++;
       +                else if (strcmp(argv[i], "-font") == 0 && i+1<argc) {
       +                        i++;
       +                        fname = argv[i];
       +                }
       +                else if (strcmp(argv[i], "-term") == 0 && i+1<argc)
       +                        termprog = argv[++i];
       +                else if (strcmp(argv[i], "-version") == 0) {
       +                        fprintf(stderr, "%s", version[0]);
       +                        if (PATCHLEVEL > 0)
       +                                fprintf(stderr, "; patch level %d", PATCHLEVEL);
       +                        fprintf(stderr, "\n");
       +                        exit(0);
       +                }
       +                else if (argv[i][0] == '-')
       +                        usage();
       +                else
       +                        break;
       +        for (; i < argc; i++)
       +                if (strcmp(argv[i], "exit") == 0)
       +                        do_exit++;
       +                else if (strcmp(argv[i], "restart") == 0)
       +                        do_restart++;
       +                else
       +                        usage();
       +
       +        if (do_exit && do_restart)
       +                usage();
       +
       +        shell = (char *)getenv("SHELL");
       +        if (shell == NULL)
       +                shell = DEFSHELL;
       +
       +        dpy = XOpenDisplay("");
       +        if (dpy == 0)
       +                fatal("can't open display");
       +
       +        initting = 1;
       +        XSetErrorHandler(handler);
       +        if (signal(SIGTERM, sighandler) == SIG_IGN)
       +                signal(SIGTERM, SIG_IGN);
       +        if (signal(SIGINT, sighandler) == SIG_IGN)
       +                signal(SIGINT, SIG_IGN);
       +        if (signal(SIGHUP, sighandler) == SIG_IGN)
       +                signal(SIGHUP, SIG_IGN);
       +
       +        exit_9wm = XInternAtom(dpy, "9WM_EXIT", False);
       +        restart_9wm = XInternAtom(dpy, "9WM_RESTART", False);
       +
       +        curtime = -1;                /* don't care */
       +        if (do_exit) {
       +                sendcmessage(DefaultRootWindow(dpy), exit_9wm, 0L, 1);
       +                XSync(dpy, False);
       +                exit(0);
       +        }
       +        if (do_restart) {
       +                sendcmessage(DefaultRootWindow(dpy), restart_9wm, 0L, 1);
       +                XSync(dpy, False);
       +                exit(0);
       +        }
       +
       +        wm_state = XInternAtom(dpy, "WM_STATE", False);
       +        wm_change_state = XInternAtom(dpy, "WM_CHANGE_STATE", False);
       +        wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
       +        wm_delete = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
       +        wm_take_focus = XInternAtom(dpy, "WM_TAKE_FOCUS", False);
       +        wm_colormaps = XInternAtom(dpy, "WM_COLORMAP_WINDOWS", False);
       +        _9wm_running = XInternAtom(dpy, "_9WM_RUNNING", False);
       +        _9wm_hold_mode = XInternAtom(dpy, "_9WM_HOLD_MODE", False);
       +
       +        if (fname != 0)
       +                if ((font = XLoadQueryFont(dpy, fname)) == 0)
       +                        fprintf(stderr, "9wm: warning: can't load font %s\n", fname);
       +
       +        if (font == 0) {
       +                i = 0;
       +                for (;;) {
       +                        fname = fontlist[i++];
       +                        if (fname == 0) {
       +                                fprintf(stderr, "9wm: warning: can't find a font\n");
       +                                break;
       +                        }
       +                        font = XLoadQueryFont(dpy, fname);
       +                        if (font != 0)
       +                                break;
       +                }
       +        }
       +        if (nostalgia) {
       +                _border--;
       +                _inset--;
       +        }
       +
       +#ifdef        SHAPE
       +        shape = XShapeQueryExtension(dpy, &shape_event, &dummy);
       +#endif
       +
       +        num_screens = ScreenCount(dpy);
       +        screens = (ScreenInfo *)malloc(sizeof(ScreenInfo) * num_screens);
       +
       +        for (i = 0; i < num_screens; i++)
       +                initscreen(&screens[i], i, background);
       +
       +        /* set selection so that 9term knows we're running */
       +        curtime = CurrentTime;
       +        XSetSelectionOwner(dpy, _9wm_running, screens[0].menuwin, timestamp());
       +
       +        XSync(dpy, False);
       +        initting = 0;
       +
       +        nofocus();
       +
       +        for (i = 0; i < num_screens; i++)
       +                scanwins(&screens[i]);
       +
       +        mainloop(shape_event);
       +}
       +
       +void
       +initscreen(ScreenInfo *s, int i, int background)
       +{
       +        char *ds, *colon, *dot1;
       +        unsigned long mask;
       +        XGCValues gv;
       +        XSetWindowAttributes attr;
       +
       +        s->num = i;
       +        s->root = RootWindow(dpy, i);
       +        s->def_cmap = DefaultColormap(dpy, i);
       +        s->min_cmaps = MinCmapsOfScreen(ScreenOfDisplay(dpy, i));
       +        s->depth = DefaultDepth(dpy, i);
       +
       +        ds = DisplayString(dpy);
       +        colon = rindex(ds, ':');
       +        if (colon && num_screens > 1) {
       +                strcpy(s->display, "DISPLAY=");
       +                strcat(s->display, ds);
       +                colon = s->display + 8 + (colon - ds);        /* use version in buf */
       +                dot1 = index(colon, '.');        /* first period after colon */
       +                if (!dot1)
       +                        dot1 = colon + strlen(colon);        /* if not there, append */
       +                sprintf(dot1, ".%d", i);
       +        }
       +        else
       +                s->display[0] = '\0';
       +
       +        s->activeholdborder = colorpixel(dpy, s->depth, 0x000099);
       +        s->inactiveholdborder = colorpixel(dpy, s->depth, 0x005DBB);
       +        s->activeborder = colorpixel(dpy, s->depth ,0x55AAAA);
       +        s->inactiveborder = colorpixel(dpy, s->depth, 0x9EEEEE);
       +        s->red = colorpixel(dpy, s->depth, 0xDD0000);
       +        s->black = BlackPixel(dpy, i);
       +        s->white = WhitePixel(dpy, i);
       +        s->width = WidthOfScreen(ScreenOfDisplay(dpy, i));
       +        s->height = HeightOfScreen(ScreenOfDisplay(dpy, i));
       +        s->bkup[0] = XCreatePixmap(dpy, s->root, 2*s->width, BORDER, DefaultDepth(dpy, i));
       +        s->bkup[1] = XCreatePixmap(dpy, s->root, BORDER, 2*s->height, DefaultDepth(dpy, i));
       +
       +        gv.foreground = s->black^s->white;
       +        gv.background = s->white;
       +        gv.function = GXxor;
       +        gv.line_width = 0;
       +        gv.subwindow_mode = IncludeInferiors;
       +        mask = GCForeground | GCBackground | GCFunction | GCLineWidth
       +                | GCSubwindowMode;
       +        if (font != 0) {
       +                gv.font = font->fid;
       +                mask |= GCFont;
       +        }
       +        s->gc = XCreateGC(dpy, s->root, mask, &gv);
       +
       +        gv.function = GXcopy;
       +        s->gccopy = XCreateGC(dpy, s->root, mask, &gv);
       +
       +        gv.foreground = s->red;
       +        s->gcred = XCreateGC(dpy, s->root, mask, &gv);
       +
       +        gv.foreground = colorpixel(dpy, s->depth, 0xEEEEEE);
       +        s->gcsweep = XCreateGC(dpy, s->root, mask, &gv);
       +
       +        gv.foreground = colorpixel(dpy, s->depth, 0xE9FFE9);
       +        s->gcmenubg = XCreateGC(dpy, s->root, mask, &gv);
       +
       +        gv.foreground = colorpixel(dpy, s->depth, 0x448844);
       +        s->gcmenubgs = XCreateGC(dpy, s->root, mask, &gv);
       +
       +        gv.foreground = s->black;
       +        gv.background = colorpixel(dpy, s->depth, 0xE9FFE9);
       +        s->gcmenufg = XCreateGC(dpy, s->root, mask, &gv);
       +
       +        gv.foreground = colorpixel(dpy, s->depth, 0xE9FFE9);
       +        gv.background = colorpixel(dpy, s->depth, 0x448844);
       +        s->gcmenufgs = XCreateGC(dpy, s->root, mask, &gv);
       +
       +        initcurs(s);
       +
       +        attr.cursor = s->arrow;
       +        attr.event_mask = SubstructureRedirectMask
       +                | SubstructureNotifyMask | ColormapChangeMask
       +                | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask;
       +        mask = CWCursor|CWEventMask;
       +        XChangeWindowAttributes(dpy, s->root, mask, &attr);
       +        XSync(dpy, False);
       +
       +        if (background) {
       +/*
       +                XSetWindowBackgroundPixmap(dpy, s->root, s->root_pixmap);
       +                XClearWindow(dpy, s->root);
       +*/
       +                system("xsetroot -solid grey30");
       +        }
       +        s->menuwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 2, colorpixel(dpy, s->depth, 0xAAFFAA), colorpixel(dpy, s->depth, 0xE9FFE9));
       +        s->sweepwin = XCreateSimpleWindow(dpy, s->root, 0, 0, 1, 1, 4, s->red, colorpixel(dpy, s->depth, 0xEEEEEE));
       +}
       +
       +ScreenInfo*
       +getscreen(Window w)
       +{
       +        int i;
       +
       +        for (i = 0; i < num_screens; i++)
       +                if (screens[i].root == w)
       +                        return &screens[i];
       +
       +        return 0;
       +}
       +
       +Time
       +timestamp(void)
       +{
       +        XEvent ev;
       +
       +        if (curtime == CurrentTime) {
       +                XChangeProperty(dpy, screens[0].root, _9wm_running, _9wm_running, 8,
       +                                PropModeAppend, (unsigned char *)"", 0);
       +                XMaskEvent(dpy, PropertyChangeMask, &ev);
       +                curtime = ev.xproperty.time;
       +        }
       +        return curtime;
       +}
       +
       +void
       +sendcmessage(Window w, Atom a, long x, int isroot)
       +{
       +        XEvent ev;
       +        int status;
       +        long mask;
       +
       +        memset(&ev, 0, sizeof(ev));
       +        ev.xclient.type = ClientMessage;
       +        ev.xclient.window = w;
       +        ev.xclient.message_type = a;
       +        ev.xclient.format = 32;
       +        ev.xclient.data.l[0] = x;
       +        ev.xclient.data.l[1] = timestamp();
       +        mask = 0L;
       +        if (isroot)
       +                mask = SubstructureRedirectMask;                /* magic! */
       +        status = XSendEvent(dpy, w, False, mask, &ev);
       +        if (status == 0)
       +                fprintf(stderr, "9wm: sendcmessage failed\n");
       +}
       +
       +void
       +sendconfig(Client *c)
       +{
       +        XConfigureEvent ce;
       +
       +        ce.type = ConfigureNotify;
       +        ce.event = c->window;
       +        ce.window = c->window;
       +        ce.x = c->x;
       +        ce.y = c->y;
       +        ce.width = c->dx;
       +        ce.height = c->dy;
       +        ce.border_width = c->border;
       +        ce.above = None;
       +        ce.override_redirect = 0;
       +        XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent*)&ce);
       +}
       +
       +void
       +sighandler(void)
       +{
       +        signalled = 1;
       +}
       +
       +void
       +getevent(XEvent *e)
       +{
       +        int fd;
       +        fd_set rfds;
       +        struct timeval t;
       +
       +        if (!signalled) {
       +                if (QLength(dpy) > 0) {
       +                        XNextEvent(dpy, e);
       +                        return;
       +                }
       +                fd = ConnectionNumber(dpy);
       +                FD_ZERO(&rfds);
       +                FD_SET(fd, &rfds);
       +                t.tv_sec = t.tv_usec = 0;
       +                if (select(fd+1, &rfds, NULL, NULL, &t) == 1) {
       +                        XNextEvent(dpy, e);
       +                        return;
       +                }
       +                XFlush(dpy);
       +                FD_SET(fd, &rfds);
       +                if (select(fd+1, &rfds, NULL, NULL, NULL) == 1) {
       +                        XNextEvent(dpy, e);
       +                        return;
       +                }
       +                if (errno != EINTR || !signalled) {
       +                        perror("9wm: select failed");
       +                        exit(1);
       +                }
       +        }
       +        fprintf(stderr, "9wm: exiting on signal\n");
       +        cleanup();
       +        exit(1);
       +}
       +
       +void
       +cleanup(void)
       +{
       +        Client *c, *cc[2], *next;
       +        XWindowChanges wc;
       +        int i;
       +
       +        /* order of un-reparenting determines final stacking order... */
       +        cc[0] = cc[1] = 0;
       +        for (c = clients; c; c = next) {
       +                next = c->next;
       +                i = normal(c);
       +                c->next = cc[i];
       +                cc[i] = c;
       +        }
       +
       +        for (i = 0; i < 2; i++) {
       +                for (c = cc[i]; c; c = c->next) {
       +                        if (!withdrawn(c)) {
       +                                gravitate(c, 1);
       +                                XReparentWindow(dpy, c->window, c->screen->root,
       +                                                c->x, c->y);
       +                        }
       +                        wc.border_width = c->border;
       +                        XConfigureWindow(dpy, c->window, CWBorderWidth, &wc);
       +                }
       +        }
       +
       +        XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, timestamp());
       +        for (i = 0; i < num_screens; i++)
       +                cmapnofocus(&screens[i]);
       +        XCloseDisplay(dpy);
       +}
 (DIR) diff --git a/src/cmd/rio/manage.c b/src/cmd/rio/manage.c
       t@@ -0,0 +1,482 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +#include <stdio.h>
       +#include <X11/X.h>
       +#include <X11/Xos.h>
       +#include <X11/Xlib.h>
       +#include <X11/Xutil.h>
       +#include <X11/Xatom.h>
       +#include <X11/extensions/shape.h>
       +#include "dat.h"
       +#include "fns.h"
       +
       +int
       +manage(Client *c, int mapped)
       +{
       +        int fixsize, dohide, doreshape, state;
       +        long msize;
       +        XClassHint class;
       +        XWMHints *hints;
       +
       +        trace("manage", c, 0);
       +        XSelectInput(dpy, c->window, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | FocusChangeMask);
       +
       +        /* Get loads of hints */
       +
       +        if (XGetClassHint(dpy, c->window, &class) != 0) {        /* ``Success'' */
       +                c->instance = class.res_name;
       +                c->class = class.res_class;
       +                c->is9term = (strcmp(c->class, "9term") == 0);
       +        }
       +        else {
       +                c->instance = 0;
       +                c->class = 0;
       +                c->is9term = 0;
       +        }
       +        c->iconname = getprop(c->window, XA_WM_ICON_NAME);
       +        c->name = getprop(c->window, XA_WM_NAME);
       +        setlabel(c);
       +
       +        hints = XGetWMHints(dpy, c->window);
       +        if (XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
       +                c->size.flags = PSize;                /* not specified - punt */
       +
       +        getcmaps(c);
       +        getproto(c);
       +        gettrans(c);
       +        if (c->is9term)
       +                c->hold = getiprop(c->window, _9wm_hold_mode);
       +
       +        /* Figure out what to do with the window from hints */
       +
       +        if (!getstate(c->window, &state))
       +                state = hints ? hints->initial_state : NormalState;
       +        dohide = (state == IconicState);
       +
       +        fixsize = 0;
       +        if ((c->size.flags & (USSize|PSize)))
       +                fixsize = 1;
       +        if ((c->size.flags & (PMinSize|PMaxSize)) == (PMinSize|PMaxSize) && c->size.min_width == c->size.max_width && c->size.min_height == c->size.max_height)
       +                fixsize = 1;
       +        doreshape = !mapped;
       +        if (fixsize) {
       +                if (c->size.flags & USPosition)
       +                        doreshape = 0;
       +                if (dohide && (c->size.flags & PPosition))
       +                        doreshape = 0;
       +                if (c->trans != None)
       +                        doreshape = 0;
       +        }
       +        if (c->is9term)
       +                fixsize = 0;
       +        if (c->size.flags & PBaseSize) {
       +                c->min_dx = c->size.base_width;
       +                c->min_dy = c->size.base_height;
       +        }
       +        else if (c->size.flags & PMinSize) {
       +                c->min_dx = c->size.min_width;
       +                c->min_dy = c->size.min_height;
       +        }
       +        else if (c->is9term) {
       +                c->min_dx = 100;
       +                c->min_dy = 50;
       +        }
       +        else
       +                c->min_dx = c->min_dy = 0;
       +
       +        if (hints)
       +                XFree(hints);
       +
       +        /* Now do it!!! */
       +
       +        if (doreshape) {
       +                if (current && current->screen == c->screen)
       +                        cmapnofocus(c->screen);
       +                if (!c->is9term && c->x==0 && c->y==0) {
       +                        static int nwin;
       +
       +                        c->x = 20*nwin+BORDER;
       +                        c->y = 20*nwin+BORDER;
       +                        nwin++;
       +                        nwin %= 10;
       +                }
       +
       +                if (c->is9term && !(fixsize ? drag(c) : sweep(c))) {
       +                        XKillClient(dpy, c->window);
       +                        rmclient(c);
       +                        if (current && current->screen == c->screen)
       +                                cmapfocus(current);
       +                        return 0;
       +                }
       +        }
       +        else
       +                gravitate(c, 0);
       +
       +        c->parent = XCreateSimpleWindow(dpy, c->screen->root,
       +                        c->x - BORDER, c->y - BORDER,
       +                        c->dx + 2*BORDER, c->dy + 2*BORDER,
       +                        0, c->screen->black, c->screen->white);
       +        XSelectInput(dpy, c->parent, SubstructureRedirectMask | SubstructureNotifyMask);
       +        if (mapped)
       +                c->reparenting = 1;
       +        if (doreshape && !fixsize)
       +                XResizeWindow(dpy, c->window, c->dx, c->dy);
       +        XSetWindowBorderWidth(dpy, c->window, 0);
       +        XReparentWindow(dpy, c->window, c->parent, BORDER, BORDER);
       +#ifdef        SHAPE
       +        if (shape) {
       +                XShapeSelectInput(dpy, c->window, ShapeNotifyMask);
       +                ignore_badwindow = 1;                /* magic */
       +                setshape(c);
       +                ignore_badwindow = 0;
       +        }
       +#endif
       +        XAddToSaveSet(dpy, c->window);
       +        if (dohide)
       +                hide(c);
       +        else {
       +                XMapWindow(dpy, c->window);
       +                XMapWindow(dpy, c->parent);
       +                XUnmapWindow(dpy, c->screen->sweepwin);
       +                if (nostalgia || doreshape)
       +                        active(c);
       +                else if (c->trans != None && current && current->window == c->trans)
       +                        active(c);
       +                else
       +                        setactive(c, 0);
       +                setstate(c, NormalState);
       +        }
       +        if (current && (current != c))
       +                cmapfocus(current);
       +        c->init = 1;
       +        return 1;
       +}
       +
       +void
       +scanwins(ScreenInfo *s)
       +{
       +        unsigned int i, nwins;
       +        Client *c;
       +        Window dw1, dw2, *wins;
       +        XWindowAttributes attr;
       +
       +        XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins);
       +        for (i = 0; i < nwins; i++) {
       +                XGetWindowAttributes(dpy, wins[i], &attr);
       +                if (attr.override_redirect || wins[i] == s->menuwin)
       +                        continue;
       +                c = getclient(wins[i], 1);
       +                if (c != 0 && c->window == wins[i] && !c->init) {
       +                        c->x = attr.x;
       +                        c->y = attr.y;
       +                        c->dx = attr.width;
       +                        c->dy = attr.height;
       +                        c->border = attr.border_width;
       +                        c->screen = s;
       +                        c->parent = s->root;
       +                        if (attr.map_state == IsViewable)
       +                                manage(c, 1);
       +                }
       +        }
       +        XFree((void *) wins);        /* cast is to shut stoopid compiler up */
       +}
       +
       +void
       +gettrans(Client *c)
       +{
       +        Window trans;
       +
       +        trans = None;
       +        if (XGetTransientForHint(dpy, c->window, &trans) != 0)
       +                c->trans = trans;
       +        else
       +                c->trans = None;
       +}
       +
       +void
       +withdraw(Client *c)
       +{
       +        XUnmapWindow(dpy, c->parent);
       +        gravitate(c, 1);
       +        XReparentWindow(dpy, c->window, c->screen->root, c->x, c->y);
       +        gravitate(c, 0);
       +        XRemoveFromSaveSet(dpy, c->window);
       +        setstate(c, WithdrawnState);
       +
       +        /* flush any errors */
       +        ignore_badwindow = 1;
       +        XSync(dpy, False);
       +        ignore_badwindow = 0;
       +}
       +
       +void
       +gravitate(Client *c, int invert)
       +{
       +        int gravity, dx, dy, delta;
       +
       +        gravity = NorthWestGravity;
       +        if (c->size.flags & PWinGravity)
       +                gravity = c->size.win_gravity;
       +
       +        delta = c->border-BORDER;
       +        switch (gravity) {
       +        case NorthWestGravity:
       +                dx = 0;
       +                dy = 0;
       +                break;
       +        case NorthGravity:
       +                dx = delta;
       +                dy = 0;
       +                break;
       +        case NorthEastGravity:
       +                dx = 2*delta;
       +                dy = 0;
       +                break;
       +        case WestGravity:
       +                dx = 0;
       +                dy = delta;
       +                break;
       +        case CenterGravity:
       +        case StaticGravity:
       +                dx = delta;
       +                dy = delta;
       +                break;
       +        case EastGravity:
       +                dx = 2*delta;
       +                dy = delta;
       +                break;
       +        case SouthWestGravity:
       +                dx = 0;
       +                dy = 2*delta;
       +                break;
       +        case SouthGravity:
       +                dx = delta;
       +                dy = 2*delta;
       +                break;
       +        case SouthEastGravity:
       +                dx = 2*delta;
       +                dy = 2*delta;
       +                break;
       +        default:
       +                fprintf(stderr, "9wm: bad window gravity %d for 0x%x\n", gravity, c->window);
       +                return;
       +        }
       +        dx += BORDER;
       +        dy += BORDER;
       +        if (invert) {
       +                dx = -dx;
       +                dy = -dy;
       +        }
       +        c->x += dx;
       +        c->y += dy;
       +}
       +
       +static void
       +installcmap(ScreenInfo *s, Colormap cmap)
       +{
       +        if (cmap == None)
       +                XInstallColormap(dpy, s->def_cmap);
       +        else
       +                XInstallColormap(dpy, cmap);
       +}
       +
       +void
       +cmapfocus(Client *c)
       +{
       +        int i, found;
       +        Client *cc;
       +
       +        if (c == 0)
       +                return;
       +        else if (c->ncmapwins != 0) {
       +                found = 0;
       +                for (i = c->ncmapwins-1; i >= 0; i--) {
       +                        installcmap(c->screen, c->wmcmaps[i]);
       +                        if (c->cmapwins[i] == c->window)
       +                                found++;
       +                }
       +                if (!found)
       +                        installcmap(c->screen, c->cmap);
       +        }
       +        else if (c->trans != None && (cc = getclient(c->trans, 0)) != 0 && cc->ncmapwins != 0)
       +                cmapfocus(cc);
       +        else
       +                installcmap(c->screen, c->cmap);
       +}
       +
       +void
       +cmapnofocus(ScreenInfo *s)
       +{
       +        installcmap(s, None);
       +}
       +
       +void
       +getcmaps(Client *c)
       +{
       +        int n, i;
       +        Window *cw;
       +        XWindowAttributes attr;
       +
       +        if (!c->init) {
       +                XGetWindowAttributes(dpy, c->window, &attr);
       +                c->cmap = attr.colormap;
       +        }
       +
       +        n = _getprop(c->window, wm_colormaps, XA_WINDOW, 100L, (unsigned char **)&cw);
       +        if (c->ncmapwins != 0) {
       +                XFree((char *)c->cmapwins);
       +                free((char *)c->wmcmaps);
       +        }
       +        if (n <= 0) {
       +                c->ncmapwins = 0;
       +                return;
       +        }
       +
       +        c->ncmapwins = n;
       +        c->cmapwins = cw;
       +
       +        c->wmcmaps = (Colormap*)malloc(n*sizeof(Colormap));
       +        for (i = 0; i < n; i++) {
       +                if (cw[i] == c->window)
       +                        c->wmcmaps[i] = c->cmap;
       +                else {
       +                        XSelectInput(dpy, cw[i], ColormapChangeMask);
       +                        XGetWindowAttributes(dpy, cw[i], &attr);
       +                        c->wmcmaps[i] = attr.colormap;
       +                }
       +        }
       +}
       +
       +void
       +setlabel(Client *c)
       +{
       +        char *label, *p;
       +
       +        if (c->iconname != 0)
       +                label = c->iconname;
       +        else if (c->name != 0)
       +                label = c->name;
       +        else if (c->instance != 0)
       +                label = c->instance;
       +        else if (c->class != 0)
       +                label = c->class;
       +        else
       +                label = "no label";
       +        if ((p = index(label, ':')) != 0)
       +                *p = '\0';
       +        c->label = label;
       +}
       +
       +#ifdef        SHAPE
       +void
       +setshape(Client *c)
       +{
       +        int n, order;
       +        XRectangle *rect;
       +
       +        /* don't try to add a border if the window is non-rectangular */
       +        rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order);
       +        if (n > 1)
       +                XShapeCombineShape(dpy, c->parent, ShapeBounding, BORDER, BORDER,
       +                        c->window, ShapeBounding, ShapeSet);
       +        XFree((void*)rect);
       +}
       +#endif
       +
       +int
       +_getprop(Window w, Atom a, Atom type, long len, unsigned char **p)
       +{
       +        Atom real_type;
       +        int format;
       +        unsigned long n, extra;
       +        int status;
       +
       +        status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p);
       +        if (status != Success || *p == 0)
       +                return -1;
       +        if (n == 0)
       +                XFree((void*) *p);
       +        /* could check real_type, format, extra here... */
       +        return n;
       +}
       +
       +char *
       +getprop(Window w, Atom a)
       +{
       +        unsigned char *p;
       +
       +        if (_getprop(w, a, XA_STRING, 100L, &p) <= 0)
       +                return 0;
       +        return (char *)p;
       +}
       +
       +int
       +get1prop(Window w, Atom a, Atom type)
       +{
       +        char **p, *x;
       +
       +        if (_getprop(w, a, type, 1L, (unsigned char**)&p) <= 0)
       +                return 0;
       +        x = *p;
       +        XFree((void*) p);
       +        return (int)x;
       +}
       +
       +Window
       +getwprop(Window w, Atom a)
       +{
       +        return get1prop(w, a, XA_WINDOW);
       +}
       +
       +int
       +getiprop(Window w, Atom a)
       +{
       +        return get1prop(w, a, XA_INTEGER);
       +}
       +
       +void
       +setstate(Client *c, int state)
       +{
       +        long data[2];
       +
       +        data[0] = (long) state;
       +        data[1] = (long) None;
       +
       +        c->state = state;
       +        XChangeProperty(dpy, c->window, wm_state, wm_state, 32,
       +                PropModeReplace, (unsigned char *)data, 2);
       +}
       +
       +int
       +getstate(Window w, int *state)
       +{
       +        long *p = 0;
       +
       +        if (_getprop(w, wm_state, wm_state, 2L, (unsigned char**)&p) <= 0)
       +                return 0;
       +
       +        *state = (int) *p;
       +        XFree((char *) p);
       +        return 1;
       +}
       +
       +void
       +getproto(Client *c)
       +{
       +        Atom *p;
       +        int i;
       +        long n;
       +        Window w;
       +
       +        w = c->window;
       +        c->proto = 0;
       +        if ((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (unsigned char**)&p)) <= 0)
       +                return;
       +
       +        for (i = 0; i < n; i++)
       +                if (p[i] == wm_delete)
       +                        c->proto |= Pdelete;
       +                else if (p[i] == wm_take_focus)
       +                        c->proto |= Ptakefocus;
       +
       +        XFree((char *) p);
       +}
 (DIR) diff --git a/src/cmd/rio/menu.c b/src/cmd/rio/menu.c
       t@@ -0,0 +1,258 @@
       +/* Copyright (c) 1994-1996 David Hogan, see README for licence details */
       +#include <stdio.h>
       +#include <signal.h>
       +#include <X11/X.h>
       +#include <X11/Xlib.h>
       +#include <X11/Xutil.h>
       +#include "dat.h"
       +#include "fns.h"
       +
       +Client        *hiddenc[MAXHIDDEN];
       +
       +int        numhidden;
       +
       +char        *b3items[B3FIXED+MAXHIDDEN+1] =
       +{
       +        "New",
       +        "Reshape",
       +        "Move",
       +        "Delete",
       +        "Hide",
       +        0,
       +};
       +
       +Menu        b3menu =
       +{
       +        b3items,
       +};
       +
       +Menu        egg =
       +{
       +        version,
       +};
       +
       +void
       +button(XButtonEvent *e)
       +{
       +        int n, shift;
       +        Client *c;
       +        Window dw;
       +        ScreenInfo *s;
       +
       +        curtime = e->time;
       +        s = getscreen(e->root);
       +        if (s == 0)
       +                return;
       +        c = getclient(e->window, 0);
       +        if (c) {
       +                e->x += c->x - BORDER;
       +                e->y += c->y - BORDER;
       +        }
       +        else if (e->window != e->root)
       +                XTranslateCoordinates(dpy, e->window, s->root, e->x, e->y,
       +                                &e->x, &e->y, &dw);
       +        switch (e->button) {
       +        case Button1:
       +                if (c) {
       +                        XMapRaised(dpy, c->parent);
       +                        top(c);
       +                        active(c);
       +                }
       +                return;
       +        case Button2:
       +                if ((e->state&(ShiftMask|ControlMask))==(ShiftMask|ControlMask))
       +                        menuhit(e, &egg);
       +                return;
       +        default:
       +                return;
       +        case Button3:
       +                break;
       +        }
       +
       +        if (current && current->screen == s)
       +                cmapnofocus(s);
       +        switch (n = menuhit(e, &b3menu)) {
       +        case 0:         /* New */
       +                spawn(s);
       +                break;
       +        case 1:         /* Reshape */
       +                reshape(selectwin(1, 0, s));
       +                break;
       +        case 2:         /* Move */
       +                move(selectwin(0, 0, s));
       +                break;
       +        case 3:         /* Delete */
       +                shift = 0;
       +                c = selectwin(1, &shift, s);
       +                delete(c, shift);
       +                break;
       +        case 4:         /* Hide */
       +                hide(selectwin(1, 0, s));
       +                break;
       +        default:        /* unhide window */
       +                unhide(n - B3FIXED, 1);
       +                break;
       +        case -1:        /* nothing */
       +                break;
       +        }
       +        if (current && current->screen == s)
       +                cmapfocus(current);
       +}
       +
       +void
       +spawn(ScreenInfo *s)
       +{
       +        /*
       +         * ugly dance to avoid leaving zombies.  Could use SIGCHLD,
       +         * but it's not very portable.
       +         */
       +        if (fork() == 0) {
       +                if (fork() == 0) {
       +                        close(ConnectionNumber(dpy));
       +                        if (s->display[0] != '\0')
       +                                putenv(s->display);
       +                        if (termprog != NULL) {
       +                                execl(shell, shell, "-c", termprog, 0);
       +                                fprintf(stderr, "9wm: exec %s", shell);
       +                                perror(" failed");
       +                        }
       +                        execlp("9term", "9term", "-w", 0);
       +                        execlp("xterm", "xterm", "-ut", 0);
       +                        perror("9wm: exec 9term/xterm failed");
       +                        exit(1);
       +                }
       +                exit(0);
       +        }
       +        wait((int *) 0);
       +}
       +
       +void
       +reshape(Client *c)
       +{
       +        int odx, ody;
       +
       +        if (c == 0)
       +                return;
       +        odx = c->dx;
       +        ody = c->dy;
       +        if (sweep(c) == 0)
       +                return;
       +        active(c);
       +        top(c);
       +        XRaiseWindow(dpy, c->parent);
       +        XMoveResizeWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER,
       +                                        c->dx+2*BORDER, c->dy+2*BORDER);
       +        if (c->dx == odx && c->dy == ody)
       +                sendconfig(c);
       +        else
       +                XMoveResizeWindow(dpy, c->window, BORDER, BORDER, c->dx, c->dy);
       +}
       +
       +void
       +move(Client *c)
       +{
       +        if (c == 0)
       +                return;
       +        if (drag(c) == 0)
       +                return;
       +        active(c);
       +        top(c);
       +        XRaiseWindow(dpy, c->parent);
       +        XMoveWindow(dpy, c->parent, c->x-BORDER, c->y-BORDER);
       +        sendconfig(c);
       +}
       +
       +void
       +delete(Client *c, int shift)
       +{
       +        if (c == 0)
       +                return;
       +        if ((c->proto & Pdelete) && !shift)
       +                sendcmessage(c->window, wm_protocols, wm_delete, 0);
       +        else
       +                XKillClient(dpy, c->window);                /* let event clean up */
       +}
       +
       +void
       +hide(Client *c)
       +{
       +        if (c == 0 || numhidden == MAXHIDDEN)
       +                return;
       +        if (hidden(c)) {
       +                fprintf(stderr, "9wm: already hidden: %s\n", c->label);
       +                return;
       +        }
       +        XUnmapWindow(dpy, c->parent);
       +        XUnmapWindow(dpy, c->window);
       +        setstate(c, IconicState);
       +        if (c == current)
       +                nofocus();
       +        hiddenc[numhidden] = c;
       +        b3items[B3FIXED+numhidden] = c->label;
       +        numhidden++;
       +        b3items[B3FIXED+numhidden] = 0;
       +}
       +
       +void
       +unhide(int n, int map)
       +{
       +        Client *c;
       +        int i;
       +
       +        if (n >= numhidden) {
       +                fprintf(stderr, "9wm: unhide: n %d numhidden %d\n", n, numhidden);
       +                return;
       +        }
       +        c = hiddenc[n];
       +        if (!hidden(c)) {
       +                fprintf(stderr, "9wm: unhide: not hidden: %s(0x%x)\n",
       +                        c->label, c->window);
       +                return;
       +        }
       +
       +        if (map) {
       +                XMapWindow(dpy, c->window);
       +                XMapRaised(dpy, c->parent);
       +                setstate(c, NormalState);
       +                active(c);
       +                top(c);
       +        }
       +
       +        numhidden--;
       +        for (i = n; i < numhidden; i ++) {
       +                hiddenc[i] = hiddenc[i+1];
       +                b3items[B3FIXED+i] = b3items[B3FIXED+i+1];
       +        }
       +        b3items[B3FIXED+numhidden] = 0;
       +}
       +
       +void
       +unhidec(Client *c, int map)
       +{
       +        int i;
       +
       +        for (i = 0; i < numhidden; i++)
       +                if (c == hiddenc[i]) {
       +                        unhide(i, map);
       +                        return;
       +                }
       +        fprintf(stderr, "9wm: unhidec: not hidden: %s(0x%x)\n",
       +                c->label, c->window);
       +}
       +
       +void
       +renamec(Client *c, char *name)
       +{
       +        int i;
       +
       +        if (name == 0)
       +                name = "???";
       +        c->label = name;
       +        if (!hidden(c))
       +                return;
       +        for (i = 0; i < numhidden; i++)
       +                if (c == hiddenc[i]) {
       +                        b3items[B3FIXED+i] = name;
       +                        return;
       +                }
       +}
 (DIR) diff --git a/src/cmd/rio/patchlevel.h b/src/cmd/rio/patchlevel.h
       t@@ -0,0 +1 @@
       +#define PATCHLEVEL 0