BSD 4_3_Tahoe development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Sun, 24 Apr 1988 10:34:47 +0000 (02:34 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Sun, 24 Apr 1988 10:34:47 +0000 (02:34 -0800)
Work on file usr/src/new/X/xnwm/wmsubs.c

Synthesized-from: CSRG/cd2/4.3tahoe

usr/src/new/X/xnwm/wmsubs.c [new file with mode: 0644]

diff --git a/usr/src/new/X/xnwm/wmsubs.c b/usr/src/new/X/xnwm/wmsubs.c
new file mode 100644 (file)
index 0000000..ab56101
--- /dev/null
@@ -0,0 +1,914 @@
+#include "wm.h"
+
+#include "../cursors/icon.cursor"
+#include "../cursors/xterm.cursor"
+#include "../cursors/xterm_mask.cursor"
+
+#define solid_vcount (1 + 4*2) /* We're goin' around twice */
+#define flash_vcount (1 + 4*4) /* 4 times, if flashing! */
+
+#ifndef lint
+static char *rcsid_wmsubs_c = "$Header: wmsubs.c,v 10.3 86/02/01 16:02:10 tony Rel $";
+#endif
+
+int vcount;
+Vertex solidBox[solid_vcount], flashBox[flash_vcount], *box;
+
+int iconHeight;
+Window sizeWin;
+int sizeWidth, sizeHeight;
+int variableWidth;
+int sizeX, sizeY;              /* Where the size window is */
+Pixmap behindSize = 0;         /* And what it obscures */
+
+Window oldfocus;
+
+InitializeWm()
+{
+       SetUpSizeWindow();
+       SetUpBox();
+       StoreWmCursors();
+
+       FocusOn(RootWindow);
+       oldfocus = 0;
+}
+
+SetUpSizeWindow()
+{
+       FontInfo finfo;
+       register int i, minwid, maxwid;
+       short cwid[10];
+
+       status = XQueryFont(sizefont, &finfo);
+       if (status == 0) Error("Couldn't query size font in SetUpSizeWindow");
+
+       status = XCharWidths("0123456789x", 11, sizefont, cwid);
+       if (status == 0) Error("Couldn't get char widths in SetUpSizeWindow");
+
+       minwid = 99999;
+       maxwid = 0;
+       for (i = 0; i <= 10; i++) {
+           if (cwid[i] < minwid) minwid = cwid[i];
+           else if (cwid[i] > maxwid) maxwid = cwid[i];
+       }
+
+       variableWidth = (minwid != maxwid);
+
+       sizeWidth = 7 * maxwid + 4;
+       sizeHeight = finfo.height + 4;
+
+       sizeWin = XCreateWindow(RootWindow, 0, 0,
+               sizeWidth - 2, sizeHeight - 2,
+               1, bgPixmap, fgPixmap);
+       if (sizeWin == 0) Error("Couldn't create sizeWin in SetUpSizeWindow");
+
+       status = XQueryFont(iconfont, &finfo);
+       if (status == 0) Error("Couldn't query icon font in SetUpSizeWindow");
+
+       iconHeight = finfo.height + 8;
+}
+
+SetUpBox()
+{
+       register int i;
+
+       if (freeze) {
+           vcount = solid_vcount;
+           i = solid_vcount - 1;
+           box = solidBox;
+       } else {
+           vcount = flash_vcount;
+           i = flash_vcount - 1;
+           box = flashBox;
+       }
+
+       box[i--].flags = VertexRelative | VertexDrawLastPoint;
+       while (i > 0) box[i--].flags = VertexRelative;
+       box[0].flags = 0;
+
+       if (!freeze) box[solid_vcount-1].flags |= VertexDrawLastPoint;
+}
+
+StoreWmCursors()
+{
+       iconCursor = XCreateCursor(icon_width, icon_height, 
+               (caddr_t) icon_bits, (caddr_t) NULL,
+               8, 8,
+               WhitePixel, BlackPixel,
+               GXcopyInverted);
+       if (iconCursor == 0) {
+           Error("Couldn't store iconCursor in StoreWmCursors");
+       }
+       textCursor = XCreateCursor(xterm_width, xterm_height, 
+               (caddr_t) xterm_bits, (caddr_t) xterm_mask_bits,
+               8, 8,
+               bgColor, fgColor,
+               GXcopyInverted);
+       if (textCursor == 0) {
+           Error("Couldn't store textCursor in StoreWmCursors");
+       }
+}
+
+/* ARGSUSED */
+
+Raise(which, loc, w, winfo)
+       int which;
+       Locator loc;
+       Window w;
+       WindowInfo *winfo;
+{
+       BEvent newbutton;
+       Window neww;
+
+       if (w == RootWindow) return;
+
+       GetButton(&newbutton);
+       if (!MatchUp(newbutton, which)) return;
+
+       InterpretLocatorW(RootWindow, &neww, newbutton.location);
+       if (neww != w) return;
+
+       if (popup) UnmapPopup();
+
+       XRaiseWindow(w);
+}
+
+/* ARGSUSED */
+
+Lower(which, loc, w, winfo)
+       int which;
+       Locator loc;
+       Window w;
+       WindowInfo *winfo;
+{
+       BEvent newbutton;
+       Window neww;
+
+       if (w == RootWindow) return;
+
+       GetButton(&newbutton);
+       if (!MatchUp(newbutton, which)) return;
+
+       InterpretLocatorW(RootWindow, &neww, newbutton.location);
+       if (neww != w) return;
+
+       if (popup) UnmapPopup();
+
+       XLowerWindow(w);
+}
+
+Move(which, loc, w, winfo)
+       int which;
+       Locator loc;
+       Window w;
+       WindowInfo *winfo;
+{
+       Window subwindow;
+       BEvent newbutton;
+       int x, y, oldx, oldy, left, top;
+       int stop = FALSE;
+
+       if (w == RootWindow) return;
+
+       InterpretLocatorXY(RootWindow, &x, &y, loc);
+
+       left = winfo->x;
+       top = winfo->y;
+
+       oldx = x;
+       oldy = y;
+
+       StoreBox(left, top, winfo->width + (winfo->bdrwidth << 1) - 1,
+               winfo->height + (winfo->bdrwidth << 1) - 1);
+
+       /* If we're willing to freeze the server, we don't flicker the box.
+          If not, we do double inverts that draw and then erase the box,
+          so we have to do them more often */
+
+       if (freeze) XGrabServer();
+       DrawBox();
+
+       while (!stop) {
+           /* If we've moved at all, change the box and reset old x,y */
+
+           if (x != oldx || y != oldy) {
+               if (freeze) DrawBox();          /* Erase */
+               oldx = x;
+               oldy = y;
+               box[0].x = left;
+               box[0].y = top;
+               DrawBox();              /* Redraw */
+           } else if (!freeze) DrawBox();
+
+           /* Find the new x,y.  If there's an event, use that; otherwise
+              query the mouse */
+
+           if (XPending()) {
+               if (!GetEvent(&newbutton)) {
+                   QueryMouse(RootWindow, &x, &y, &subwindow);
+               }
+               else if (!MatchUp(newbutton, which)) break;
+               else {
+                   x = newbutton.x;
+                   y = newbutton.y;
+                   stop = TRUE;
+               }
+           } else QueryMouse(RootWindow, &x, &y, &subwindow);
+
+           left += x - oldx;
+           top += y - oldy;
+       }
+
+       if (freeze) {
+           DrawBox();                  /* Erase */
+           XUngrabServer();
+       }
+
+       if (!stop) return;
+
+       if (popup) UnmapPopup();
+
+       XMoveWindow(w, left, top);
+
+       FrameFocus();   /* Fix up frame */
+}
+
+Resize(which, loc, w, winfo)
+       int which;
+       Locator loc;
+       Window w;
+       WindowInfo *winfo;
+{
+       BEvent newbutton;
+       int t;
+       int baseheight, hinc, basewidth, winc;
+       int x0, y0;             /* Initial x,y of mouse */
+       int fixedx, fixedy;     /* x,y of fixed corner */
+       int movex, movey;       /* x,y of movable corner */
+       int limitx, limity;     /* limit to movement due to min window size */
+       int oldx, oldy;         /* previous location of moving corner */
+       int newx, newy;         /* new location of moving corner */
+       int lastx, lasty;       /* previous cursor location */
+       int x, y;               /* new cursor location */
+       int dx, dy;             /* flags indicating movement direction */
+       int width, height;      /* width & height of window */
+       int usesize, stop = FALSE;
+       Window subwindow;
+
+       if (w == RootWindow) return;
+
+       /* Find out about window and get resizing info */
+
+       status = XGetResizeHint(w, &basewidth, &baseheight, &winc, &hinc);
+       if (status == 0) Error("Couldn't get resize hint in Resize");
+       InterpretLocatorXY(RootWindow, &x0, &y0, loc);
+
+       /* Initially fixedx is left, fixedy top, movex right, and
+          movey bottom */
+
+       fixedx = winfo->x;
+       fixedy = winfo->y;
+       width = winfo->width + (winfo->bdrwidth << 1) - 1;
+       height = winfo->height + (winfo->bdrwidth << 1) - 1;
+       movex = fixedx + width;
+       movey = fixedy + height;
+
+       /* We only will use a size window if the increments are large
+          enough and the current window size corresponds to the hints */
+
+       usesize = (winc > 3 && hinc > 3 &&
+            (winfo->width - basewidth) % winc == 0 &&
+            (winfo->height - baseheight) % hinc == 0);
+
+       if (basewidth == 0 && winc == 1 && baseheight == 0 && hinc == 1) {
+           basewidth = 1;
+           baseheight = 1;
+       }
+
+       /* movex,y are still right and bottom */
+
+       limitx = movex - winfo->width + basewidth + winc;
+       limity = movey - winfo->height + baseheight + hinc;
+
+       basewidth += (winfo->bdrwidth << 1) - 1;
+       baseheight += (winfo->bdrwidth << 1) - 1;
+
+       /* Calculate the moving directions dx,dy */
+
+       CalculateMovingEdges(&dx, &dy, x0, fixedx, movex,
+               y0, fixedy, movey, winfo);
+
+       /* Figure out which edges to move depending upon which ninth
+          the cursor is in.  Adjust fixed and move edges accordingly:
+
+          dx,y indicate which edges are fixed.  Values:
+
+               dx      fixedx  movex           dy      fixedy  movey
+               1,0     left    right           1,0     top     bottom
+               -1      right   left            -1      bottom  top
+
+          A value of 0 means that both edges are fixed in that direction */
+
+       /* If we're moving left edge, switch */
+
+       if (dx == -1) {
+           limitx = movex - (limitx - fixedx);
+           t = fixedx; fixedx = movex; movex = t;
+           width = -width;
+       }
+
+       /* If we're moving top edge, switch */
+
+       if (dy == -1) {
+           limity = movey - (limity - fixedy);
+           t = fixedy; fixedy = movey; movey = t;
+           height = -height;
+       }
+
+       oldx = newx = movex;
+       oldy = newy = movey;
+       lastx = x0;
+       lasty = y0;
+
+       StoreBox(fixedx, fixedy, width, height);
+
+       /* If we're willing to freeze the server, we don't flicker the box.
+          If not, we do double inverts that draw and then erase the box,
+          so we have to do them more often */
+
+       if (freeze) XGrabServer();
+       DrawBox();              /* Draw box */
+
+       if (usesize) {
+           CreateSize (dx, dy, fixedx, fixedy, winfo);
+           FillinSize ((abs(width) - basewidth) / winc,
+                   (abs(height) - baseheight) / hinc);
+       }
+
+       /* Loop until a button event occurs */
+
+       while (!stop) {
+           /* If we've moved at all, change the box, fill in the
+              size window and reset old x,y */
+
+           if (newx != oldx || newy != oldy) {
+               if (freeze) DrawBox();          /* Erase */
+               StoreBox(fixedx, fixedy, width, height);
+
+               if (usesize) {
+                   FillinSize ((abs(width) - basewidth) / winc,
+                           (abs(height) - baseheight) / hinc);
+               }
+               oldx = newx;
+               oldy = newy;
+               DrawBox();              /* Redraw */
+           } else if (!freeze) DrawBox();
+
+           /* Find the cursor x,y -- by an event if there is one, by
+              querying if not */
+
+           if (XPending()) {
+               if (!GetEvent(&newbutton)) {
+                   QueryMouse(RootWindow, &x, &y, &subwindow);
+               }
+               else if (!MatchUp(newbutton, which)) break;
+               else {
+                   x = newbutton.x;
+                   y = newbutton.y;
+                   stop = TRUE;
+               }
+           } else QueryMouse(RootWindow, &x, &y, &subwindow);
+
+           /* If we haven't moved since last time, skip the rest */
+
+           if (x == lastx && y == lasty) continue;
+
+           lastx = x;
+           lasty = y;
+
+           newx = CalculateChange(dx, x, x0, winc, limitx, movex, oldx);
+           newy = CalculateChange(dy, y, y0, hinc, limity, movey, oldy);
+           width += newx - oldx;
+           height += newy - oldy;
+       }
+
+       if (freeze) {
+           DrawBox();                  /* Erase */
+           XUngrabServer();
+       }
+
+       if (!stop) {
+           if (usesize) DestroySize();
+           return;
+       }
+
+
+       if (newx == movex && newy == movey) {           /* i.e. no change */
+           if (usesize) DestroySize();
+           XRaiseWindow(w);
+       } else {
+
+           /* Re-exchange things so that fixedx,y is the left top */
+
+           if (newx < fixedx) {
+               t = fixedx; fixedx = newx; newx = t;
+           }
+           if (newy < fixedy) {
+               t = fixedy; fixedy = newy; newy = t;
+           }
+
+           /* Calculate new width and height. */
+
+           width = newx - fixedx + 1 - (winfo->bdrwidth << 1);
+           height = newy - fixedy + 1 - (winfo->bdrwidth << 1);
+
+           if (usesize) DestroySize();
+
+           if (popup) UnmapPopup();
+
+           XConfigureWindow(w, fixedx, fixedy, width, height);
+           FrameFocus();
+       }
+}
+
+CalculateMovingEdges(dx, dy, x0, fixedx, movex, y0, fixedy, movey, winfo)
+       int *dx, *dy, x0, fixedx, movex, y0, fixedy, movey;
+       WindowInfo *winfo;
+{
+       int xthird, ythird;
+
+       *dx = *dy = 1;
+
+       /* If we're closer to the left than to the right, switch */
+
+       if (x0 - fixedx < movex - x0) *dx = -1;
+
+       /* If we're closer to the top than the bottom, switch */
+
+       if (y0 - fixedy < movey - y0) *dy = -1;
+
+       /* Now, watch closely!  We take the offset from the point to the
+          left edge, multiply by 3 and divide by the width.  This gives
+          a value of 0, 1, or 2 depending if the point is in the left,
+          middle, or right thirds.  Do the same for y.  Add them together.
+          If the result is odd, the point must be in one of the edge ninths,
+          rather than a corner ninth or the middle ninth.  Figure out
+          which one and set dx,y accordingly. (gag) */
+
+       if (winfo->width > 2 && winfo->height > 2) {
+           xthird = ((x0 - winfo->x - winfo->bdrwidth) * 3) / winfo->width;
+           ythird = ((y0 - winfo->y - winfo->bdrwidth) * 3) / winfo->height;
+
+           if ((xthird + ythird) & 1) {
+               if (xthird & 1) *dx = 0;
+               else *dy = 0;
+           }
+       }
+}
+
+FillinSize(hsize, vsize)
+       register int hsize, vsize;
+{
+       static char sizeText[7] = {'0', '0', '0', 'x', '0', '0', '0'};
+
+       sizeText[0] = vsize / 100 + '0';
+       sizeText[1] = (vsize / 10) % 10 + '0';
+       sizeText[2] = vsize % 10 + '0';
+       sizeText[4] = hsize / 100 + '0';
+       sizeText[5] = (hsize / 10) % 10 + '0';
+       sizeText[6] = hsize % 10 + '0';
+       if (variableWidth) XClear(sizeWin);
+       XText(sizeWin, 1, 1, sizeText, sizeof(sizeText), sizefont,
+               bgColor, fgColor);
+}
+
+CreateSize(dx, dy, fixedx, fixedy, winfo)
+       int dx, dy, fixedx, fixedy;
+       WindowInfo *winfo;
+{
+       int px, py;                     /* Size x, y */
+
+       /* If a corner is being moved, put the size window in the opposite
+          corner.  If an edge, put in middle of opposite edge. */
+
+       if (dx > 0) px = fixedx + winfo->bdrwidth;
+       else if (dx < 0) px = fixedx - sizeWidth - winfo->bdrwidth + 1;
+       else px = winfo->x + winfo->bdrwidth +
+               (winfo->width - sizeWidth) / 2;
+
+       if (dy > 0) py = fixedy + winfo->bdrwidth;
+       else if (dy < 0) py = fixedy - sizeHeight - winfo->bdrwidth + 1;
+       else py = winfo->y + winfo->bdrwidth +
+               (winfo->height - sizeHeight) / 2;
+
+       if (freeze) {
+           sizeX = px;
+           sizeY = py;
+           behindSize = XPixmapSave(RootWindow, px, py,
+                   sizeWidth, sizeHeight);
+           /* Ok to return 0; this means it wasn't on the screen */
+       }
+
+       XMoveWindow(sizeWin, px, py);
+       XMapWindow(sizeWin);
+}
+
+DestroySize()
+{
+       if (behindSize != 0) {
+           XUnmapTransparent(sizeWin);
+           XPixmapPut(RootWindow, 0, 0, sizeX, sizeY, sizeWidth, sizeHeight,
+                   behindSize, GXcopy, AllPlanes);
+           XFreePixmap(behindSize);
+           behindSize = 0;
+       } else XUnmapWindow(sizeWin);
+}
+
+int CalculateChange(direction, new, orig, inc, limit, origedge, oldedge)
+       int direction, new, orig, inc, limit, origedge, oldedge;
+{
+       register int d, newedge;
+
+       if (direction) {                /* If we're changing this way */
+
+           /* Calculate the change in cursor position in inc units */
+
+           d = abs(new - orig) + (inc >> 1);;
+           d = (d / inc) * inc;
+
+           /* Adjust the new position and check against the limit */
+
+           if (new < orig) {
+               newedge = origedge - d;
+               if (direction > 0 && newedge < limit) newedge = limit;
+           } else {
+               newedge = origedge + d;
+               if (direction < 0 && newedge > limit) newedge = limit;
+           }
+       } else newedge = oldedge;
+
+       return(newedge);
+}
+
+/* ARGSUSED */
+
+Iconify(which, loc, w, winfo)
+       int which;
+       Locator loc;
+       Window w;
+       WindowInfo *winfo;
+{
+       int x, y;
+       BEvent newbutton;
+       int width, height;
+       char *iconName;
+       WindowInfo iconInfo;
+       Window icon = 0;
+       struct _xy {short x, y;} *xy;   /* To turn locators into xy pairs */
+       int downx, downy;
+
+       if (w == RootWindow) return;
+
+       /* First change the cursor into the icon cursor */
+
+       status = XGrabMouse(RootWindow, iconCursor,
+               ButtonPressed | ButtonReleased);
+       if (status == 0) Error("Couldn't grab mouse in Iconify");
+
+       /* Then wait for the upbutton; if it doesn't occur abort */
+
+       GetButton(&newbutton);
+       if (!MatchUp(newbutton, which)) return;
+       x = newbutton.x;
+       y = newbutton.y;
+
+       /* See if it already has an associated icon window;
+          if not, figure out the size */
+
+       if (winfo->assoc_wind == 0) {
+           height = iconHeight;
+
+           /* Now get the name of the window */
+
+           status = XFetchName(w, &iconName);
+           if (status == 0) Error("Couldn't fetch name in Iconify");
+
+           width = XQueryWidth(iconName, iconfont);
+           if (width == 0) width = height;
+           else width += 8;
+
+       } else {
+           icon = winfo->assoc_wind;
+           QueryWindow(icon, &iconInfo);
+           height = iconInfo.height;
+           width = iconInfo.width;
+
+           xy = (struct _xy *) &loc;
+           downx = xy->x;
+           downy = xy->y;
+       }
+
+       /* Center the icon on the new cursor position */
+
+       x -= width >> 1 + 1;
+       if (x < 0) x = 0;
+       if (x + width + 2 > screen_width) x = screen_width - width - 2;
+
+       y -= height >> 1 + 1;
+       if (y < 0) y = 0;
+       if (y + height + 2 > screen_height) y = screen_height - height - 2;
+
+       /* Open the icon, give it a text cursor, choose key events, and
+          map it */
+
+       if (icon == 0) {
+           icon = XCreateWindow(RootWindow, x, y, width, height,
+                   1, fgPixmap, gray);
+           if (icon == 0) Error("Couldn't create icon in Iconify");
+           XSelectInput(icon, KeyPressed|ExposeWindow|UnmapWindow);
+           XDefineCursor(icon, textCursor);
+           XSetIconWindow(w, icon);
+       } else {
+           xy = (struct _xy *) &(newbutton.location);
+           if (abs(xy->x - downx) > iconifyDelta ||
+                   abs(xy->y - downy) > iconifyDelta) {
+               XMoveWindow(icon, x, y);
+           }
+       }
+
+       if (popup) UnmapPopup();
+
+       XMapWindow(icon);
+       XUnmapWindow(w);
+       
+       /* If the iconified window was the focus, change to the background */
+
+       if (focus == w) FocusOn(RootWindow);
+       FrameFocus();
+}
+
+/* ARGSUSED */
+
+Deiconify(which, loc, w, winfo)
+       int which;
+       Locator loc;
+       Window w;
+       WindowInfo *winfo;
+{
+       BEvent newbutton;
+       Window neww;
+
+       if (w == RootWindow) return;
+
+       GetButton(&newbutton);
+
+       if (!MatchUp(newbutton, which)) return;
+
+       InterpretLocatorW(RootWindow, &neww, newbutton.location);
+       if (neww != w) return;
+
+       if (popup) UnmapPopup();
+
+       XUnmapWindow(w);
+       XMapWindow(winfo->assoc_wind);
+
+       /* If icon was the focus, change to the window itself */
+
+       if (focus == w) FocusOn(winfo->assoc_wind);
+       FrameFocus();
+}
+
+/* ARGSUSED */
+
+Select(which, loc, w, winfo)
+       int which;
+       Locator loc;
+       Window w;
+       WindowInfo *winfo;
+{
+       BEvent newbutton;
+       Window neww;
+
+       GetButton(&newbutton);
+       if (!MatchUp(newbutton, which)) return;
+
+       InterpretLocatorW(RootWindow, &neww, newbutton.location);
+       if (neww == 0) neww = RootWindow;
+       if (neww != w) return;
+
+       /* See if the current focus is an icon.  If not, set oldfocus
+          so we can go back to it if we want to */
+
+       if (focusInfo.type != IsIcon) oldfocus = focus;
+
+       if (popup) UnmapPopup();
+
+       FocusOn(w);
+       FrameFocus();           /* Now frame the focus window */
+       XRaiseWindow(focus);
+}
+
+FocusOn(w)
+       Window w;
+{
+       focus = w;
+       QueryWindow(focus, &focusInfo);
+       XFocusKeyboard(focus);
+}
+
+FrameFocus()
+{
+       if (frameWidth == 0) return;    /* Nothing to do */
+
+       /* Remove the frame from around any old focus window first */
+
+       XClear(RootWindow);
+
+       if (focus == RootWindow) return;
+       QueryWindow(focus, &focusInfo); /* Refresh it */
+
+       /* Undo the default clipmode for the base window */
+       
+       XClipClipped(RootWindow);
+
+       XPixSet(RootWindow, 
+               focusInfo.x - frameWidth, focusInfo.y - frameWidth,
+               focusInfo.width + 2 * (focusInfo.bdrwidth + frameWidth),
+               focusInfo.height + 2 * (focusInfo.bdrwidth + frameWidth),
+               fgColor);
+
+       XClipDrawThrough(RootWindow);   /* Put it back */
+}
+
+/* ARGSUSED */
+
+Circulate(which, loc, w, winfo)
+       int which;
+       Locator loc;
+       Window w;
+       WindowInfo *winfo;
+{
+       if (popup) UnmapPopup();
+
+       XCircWindowUp(RootWindow);
+}
+
+EditIconName(be, name)
+        XKeyPressedEvent *be;
+       register char *name;
+{
+       Window w = be->window;
+       short charcode = be->detail;
+       register int nameLen, c;
+       int x0, y0, size;
+       WindowInfo winfo;
+       register char *string;
+       int nbytes;
+       register int i;
+
+       string = XLookupMapping (be, &nbytes);
+       nameLen = (name == NULL) ? 0 : strlen(name);
+
+       for (i = 0; i < nbytes; i++) {
+               c = string[i];
+
+       
+               if (c == '\177') {      /* a 'delete' */
+                   if (nameLen > 0)
+                      name[--nameLen] = '\0';
+                        /* control-u if you can't read ascii */
+               } else if (c == '\025') {
+                   if (nameLen > 0) {
+                       *name = '\0';
+                       nameLen = 0;
+                   }
+
+               } else if (c == '\r') {         /* return means reset focus */
+                   FocusOn(oldfocus ? oldfocus : RootWindow);
+                   oldfocus = 0;
+                   FrameFocus();
+
+               } else if (c <= 0)
+                   ;   /* unknown character, ignore it */
+
+               /* Else append the letter to the name */
+
+               else {
+                   if (name == NULL)
+                       name = (char *) malloc (nameLen + 2);
+                   else
+                       name = (char *) realloc(name, nameLen + 2);
+                   if (name == NULL) {
+                       errno = ENOMEM;
+                       perror("newwm:");
+                   }
+                   name[nameLen] = c;
+                   name[++nameLen] = '\0';
+               }
+       }
+
+       QueryWindow(w, &winfo);
+       x0 = winfo.x;
+       y0 = winfo.y;
+
+       size = XQueryWidth(name, iconfont);
+
+       /* Make sure icon is entirely on screen */
+
+       if (x0 < 0) x0 = 0;
+       else if (x0 + size + 10 > screen_width) {
+           x0 = screen_width - size - 10;
+       }
+
+       if (y0 < 0) y0 = 0;
+       else if (y0 + iconHeight + 2 > screen_height) {
+           y0 = screen_height - iconHeight - 2;
+       }
+
+       XConfigureWindow(w, x0, y0, size + 8, iconHeight);
+       XWarpMouse(w, (size+8) >> 1, iconHeight >> 1);
+       FrameFocus();           /* Redraw frame */
+       XStoreName(winfo.assoc_wind, name);
+
+       /* Don't redraw the text yet; the expose event will cause that */
+}
+
+StoreBox (x, y, w, h)
+       int x, y, w, h;
+{
+       box[0].x = x;           box[0].y = y;
+       box[1].x = w+2;         box[1].y = 0;
+       box[2].x = 0;           box[2].y = h+2;
+       box[3].x = -(w+2);      box[3].y = 0;
+       box[4].x = 0;           box[4].y = -(h+1);
+       box[5].x = w+1;         box[5].y = 0;
+       box[6].x = 0;           box[6].y = h;
+       box[7].x = -w;          box[7].y = 0;
+       box[8].x = 0;           box[8].y = -(h-1);
+
+       if (!freeze) {
+           box[9].x = 0;       box[9].y = h-1;
+           box[10].x = w;      box[10].y = 0;
+           box[11].x = 0;      box[11].y = -h;
+           box[12].x = -(w+1); box[12].y = 0;
+           box[13].x = 0;      box[13].y = h+1;
+           box[14].x = w+2;    box[14].y = 0;
+           box[15].x = 0;      box[15].y = -(h+2);
+           box[16].x = -(w+2); box[16].y = 0;
+       }
+}
+
+DrawBox()
+{
+       XDraw(RootWindow, box, vcount, 1, 1, 0,
+               GXinvert, AllPlanes);
+}
+
+InterpretLocator (w, x, y, subw, loc)
+       Window w;
+       Window *subw;
+       Locator loc;
+       int *x, *y;
+{
+       status = XInterpretLocator(w, x, y, subw, loc);
+       if (status == 0) Error("Couldn't interpret in InterpretLocator");
+}
+
+InterpretLocatorW (w, subw, loc)
+       Window w;
+       Window *subw;
+       Locator loc;
+{
+       int x, y;
+
+       status = XInterpretLocator(w, &x, &y, subw, loc);
+       if (status == 0) Error("Couldn't interpret in InterpretLocator");
+}
+
+InterpretLocatorXY (w, x, y, loc)
+       Window w;
+       Locator loc;
+       int *x, *y;
+{
+       Window subw;
+
+       status = XInterpretLocator(w, x, y, &subw, loc);
+       if (status == 0) Error("Couldn't interpret in InterpretLocator");
+}
+
+QueryMouse (w, x, y, subw)
+       Window w;
+       Window *subw;
+       int *x, *y;
+{
+       status = XQueryMouse(w, x, y, subw);
+       if (status == 0) Error("Couldn't query mouse in QueryMouse");
+}
+
+QueryWindow (w, info)
+       Window w;
+       WindowInfo *info;
+{
+       status = XQueryWindow(w, info);
+       if (status == 0) Error("Couldn't query windown in QueryWindow");
+}