/*****************************************************************************/
/**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
/**                          Salt Lake City, Utah                           **/
/**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
/**                        Cambridge, Massachusetts                         **/
/**                                                                         **/
/**                           All Rights Reserved                           **/
/**                                                                         **/
/**    Permission to use, copy, modify, and distribute this software and    **/
/**    its documentation  for  any  purpose  and  without  fee is hereby    **/
/**    granted, provided that the above copyright notice appear  in  all    **/
/**    copies and that both  that  copyright  notice  and  this  permis-    **/
/**    sion  notice appear in supporting  documentation,  and  that  the    **/
/**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
/**    in publicity pertaining to distribution of the  software  without    **/
/**    specific, written prior permission.                                  **/
/**                                                                         **/
/**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
/**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
/**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
/**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
/**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
/**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
/**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
/**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
/*****************************************************************************/
/* 
 *  [ ctwm ]
 *
 *  Copyright 1992 Claude Lecommandeur.
 *            
 * Permission to use, copy, modify  and distribute this software  [ctwm] and
 * its documentation for any purpose is hereby granted without fee, provided
 * that the above  copyright notice appear  in all copies and that both that
 * copyright notice and this permission notice appear in supporting documen-
 * tation, and that the name of  Claude Lecommandeur not be used in adverti-
 * sing or  publicity  pertaining to  distribution of  the software  without
 * specific, written prior permission. Claude Lecommandeur make no represen-
 * tations  about the suitability  of this software  for any purpose.  It is
 * provided "as is" without express or implied warranty.
 *
 * Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL  IMPLIED WARRANTIES OF  MERCHANTABILITY AND FITNESS.  IN NO
 * EVENT SHALL  Claude Lecommandeur  BE LIABLE FOR ANY SPECIAL,  INDIRECT OR
 * CONSEQUENTIAL  DAMAGES OR ANY  DAMAGES WHATSOEVER  RESULTING FROM LOSS OF
 * USE, DATA  OR PROFITS,  WHETHER IN AN ACTION  OF CONTRACT,  NEGLIGENCE OR
 * OTHER  TORTIOUS ACTION,  ARISING OUT OF OR IN  CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * Author:  Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ]
 */


/***********************************************************************
 *
 * $XConsortium: resize.c,v 1.80 91/05/11 17:35:42 dave Exp $
 *
 * window resizing borrowed from the "wm" window manager
 *
 * 11-Dec-87 Thomas E. LaStrange                File created
 *
 * Do the necessary modification to be integrated in ctwm.
 * Can no longer be used for the standard twm.
 *
 * 22-April-92 Claude Lecommandeur.
 *
 *
 ***********************************************************************/

#include <stdio.h>
#include <ctype.h>
#include "twm.h"
#include "parse.h"
#include "events.h"
#include "util.h"
#include "resize.h"
#include "add_window.h"
#include "screen.h"

#define MINHEIGHT 0     /* had been 32 */
#define MINWIDTH 0      /* had been 60 */

static int dragx;       /* all these variables are used */
static int dragy;       /* in resize operations */
static unsigned int dragWidth;
static unsigned int dragHeight;

static int origx;
static int origy;
static int origWidth;
static int origHeight;

static int clampTop;
static int clampBottom;
static int clampLeft;
static int clampRight;
static int clampDX;
static int clampDY;

static int last_width;
static int last_height;

static unsigned int resizeGrabMask;

extern Cursor	TopRightCursor, TopLeftCursor, BottomRightCursor, BottomLeftCursor,
		LeftCursor, RightCursor, TopCursor, BottomCursor;

static void do_auto_clamp (TwmWindow *tmp_win, XEvent *evp)
{
    Window junkRoot;
    int x, y, h, v, junkbw;
    unsigned int junkMask;

    switch (evp->type) {
      case ButtonPress:
	x = evp->xbutton.x_root;
	y = evp->xbutton.y_root;
	break;
      case KeyPress:
	x = evp->xkey.x_root;
	y = evp->xkey.y_root;
	break;
      default:
	if (!XQueryPointer (dpy, Scr->Root, &junkRoot, &junkRoot,
			    &x, &y, &junkbw, &junkbw, &junkMask))
	  return;
    }

    /*
     * Determine in which of the 9 "quadrants" of the window we are.
     * Cast the values to signed int: if the numerator is negative
     * we don't want them converted to unsigned due to the default
     * promotion rules: that would produce a very large quotient.
     */
    h = (int)(x - dragx) / (int)(dragWidth < 3 ? 1 : (dragWidth / 3));
    v = (int)(y - dragy - tmp_win->title_height) / 
	 (int)(dragHeight < 3 ? 1 : (dragHeight / 3));
	
    if (h <= 0) {
	clampLeft = 1;
	clampDX = (x - dragx);
    } else if (h >= 2) {
	clampRight = 1;
	clampDX = (x - dragx - dragWidth);
    }

    if (v <= 0) {
	clampTop = 1;
	clampDY = (y - dragy);
    } else if (v >= 2) {
	clampBottom = 1;
	clampDY = (y - dragy - dragHeight);
    }
}


/***********************************************************************
 *
 *  Procedure:
 *      StartResize - begin a window resize operation
 *
 *  Inputs:
 *      ev      - the event structure (button press)
 *      tmp_win - the TwmWindow pointer
 *      fromtitlebar - action invoked from titlebar button
 *
 ***********************************************************************
 */

void StartResize(XEvent *evp, TwmWindow *tmp_win,
		 Bool fromtitlebar, Bool from3dborder)
{
    Window      junkRoot, grabwin;
    unsigned int junkbw, junkDepth;
    Cursor	cursor;

    cursor = (Scr->BorderCursors && tmp_win->curcurs) ? tmp_win->curcurs : Scr->ResizeCursor;
    ResizeWindow = tmp_win->frame;
    if (! Scr->OpaqueResize || resizeWhenAdd) XGrabServer(dpy);
    resizeGrabMask = ButtonPressMask | ButtonReleaseMask |
			ButtonMotionMask | PointerMotionHintMask;

    grabwin = Scr->Root;
    if (tmp_win->winbox) grabwin = tmp_win->winbox->window;
    XGrabPointer(dpy, grabwin, True, resizeGrabMask,
        GrabModeAsync, GrabModeAsync, grabwin, cursor, CurrentTime);

    XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot,
        &dragx, &dragy, &dragWidth, &dragHeight, &junkbw,
                 &junkDepth);
    dragx += tmp_win->frame_bw;
    dragy += tmp_win->frame_bw;
    origx = dragx;
    origy = dragy;
    origWidth = dragWidth;
    origHeight = dragHeight;
    clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0;

    if (Scr->AutoRelativeResize && (from3dborder || !fromtitlebar))
	do_auto_clamp (tmp_win, evp);

    Scr->SizeStringOffset = SIZE_HINDENT;
    XResizeWindow (dpy, Scr->SizeWindow,
		   Scr->SizeStringWidth + SIZE_HINDENT * 2, 
		   Scr->SizeFont.height + SIZE_VINDENT * 2);
    XMapRaised(dpy, Scr->SizeWindow);
    InstallRootColormap();
    last_width = 0;
    last_height = 0;
    DisplaySize(tmp_win, origWidth, origHeight);

    if (! Scr->OpaqueResize || resizeWhenAdd)
        MoveOutline (Scr->Root, dragx - tmp_win->frame_bw,
		 dragy - tmp_win->frame_bw, dragWidth + 2 * tmp_win->frame_bw,
		 dragHeight + 2 * tmp_win->frame_bw,
		 tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
}



void MenuStartResize(TwmWindow *tmp_win, int x, int y, int w, int h)
{
    if (! Scr->OpaqueResize) XGrabServer(dpy);
    resizeGrabMask = ButtonPressMask | ButtonMotionMask | PointerMotionMask;
    XGrabPointer(dpy, Scr->Root, True, resizeGrabMask,
        GrabModeAsync, GrabModeAsync,
        Scr->Root, Scr->ResizeCursor, CurrentTime);
    dragx = x + tmp_win->frame_bw;
    dragy = y + tmp_win->frame_bw;
    origx = dragx;
    origy = dragy;
    dragWidth = origWidth = w; /* - 2 * tmp_win->frame_bw; */
    dragHeight = origHeight = h; /* - 2 * tmp_win->frame_bw; */
    clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0;
    last_width = 0;
    last_height = 0;
    Scr->SizeStringOffset = SIZE_HINDENT;
    XResizeWindow (dpy, Scr->SizeWindow,
		   Scr->SizeStringWidth + SIZE_HINDENT * 2, 
		   Scr->SizeFont.height + SIZE_VINDENT * 2);
    XMapRaised(dpy, Scr->SizeWindow);
    DisplaySize(tmp_win, origWidth, origHeight);
    if (! Scr->OpaqueResize)
        MoveOutline (Scr->Root, dragx - tmp_win->frame_bw,
		 dragy - tmp_win->frame_bw, 
		 dragWidth + 2 * tmp_win->frame_bw,
		 dragHeight + 2 * tmp_win->frame_bw,
		 tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
}

/***********************************************************************
 *
 *  Procedure:
 *      AddStartResize - begin a windorew resize operation from AddWindow
 *
 *  Inputs:
 *      tmp_win - the TwmWindow pointer
 *
 ***********************************************************************
 */

void AddStartResize(TwmWindow *tmp_win, int x, int y, int w, int h)
{
    XGrabServer(dpy);
    resizeGrabMask = ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask;
    XGrabPointer(dpy, Scr->Root, True, resizeGrabMask,
        GrabModeAsync, GrabModeAsync,
        Scr->Root, Scr->ResizeCursor, CurrentTime);

    dragx = x + tmp_win->frame_bw;
    dragy = y + tmp_win->frame_bw;
    origx = dragx;
    origy = dragy;
    dragWidth = origWidth = w - 2 * tmp_win->frame_bw;
    dragHeight = origHeight = h - 2 * tmp_win->frame_bw;
    clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0;
/*****
    if (Scr->AutoRelativeResize) {
	clampRight = clampBottom = 1;
    }
*****/
    last_width = 0;
    last_height = 0;
    DisplaySize(tmp_win, origWidth, origHeight);
}



void MenuDoResize(int x_root, int y_root, TwmWindow *tmp_win)
{
    int action;
    Cursor cursor = 0;

    action = 0;

    x_root -= clampDX;
    y_root -= clampDY;

    if (clampTop) {
        int         delta = y_root - dragy;
        if ((int)(dragHeight - delta) < MINHEIGHT) {
            delta = dragHeight - MINHEIGHT;
            clampTop = 0;
        }
        dragy += delta;
        dragHeight -= delta;
        action = 1;
	cursor = TopCursor;
    }
    else if (y_root <= dragy/* ||
             y_root == findRootInfo(root)->rooty*/) {
        dragy = y_root;
        dragHeight = origy + origHeight -
            y_root;
        clampBottom = 0;
        clampTop = 1;
	clampDY = 0;
        action = 1;
	cursor = TopCursor;
    }
    if (clampLeft) {
        int         delta = x_root - dragx;
        if ((int)(dragWidth - delta) < MINWIDTH) {
            delta = dragWidth - MINWIDTH;
            clampLeft = 0;
        }
        dragx += delta;
        dragWidth -= delta;
        action = 1;
	cursor = clampTop ? TopLeftCursor : LeftCursor;
    }
    else if (x_root <= dragx/* ||
             x_root == findRootInfo(root)->rootx*/) {
        dragx = x_root;
        dragWidth = origx + origWidth -
            x_root;
        clampRight = 0;
        clampLeft = 1;
	clampDX = 0;
        action = 1;
	cursor = clampTop ? TopLeftCursor : LeftCursor;
    }
    if (clampBottom) {
        int         delta = y_root - dragy - dragHeight;
        if ((int)(dragHeight + delta) < MINHEIGHT) {
            delta = MINHEIGHT - dragHeight;
            clampBottom = 0;
        }
        dragHeight += delta;
        action = 1;
	cursor = clampLeft ? BottomLeftCursor : BottomCursor;
    }
    else if (y_root >= dragy + dragHeight) {
        dragy = origy;
        dragHeight = 1 + y_root - dragy;
        clampTop = 0;
        clampBottom = 1;
	clampDY = 0;
        action = 1;
	cursor = clampLeft ? BottomLeftCursor : BottomCursor;
    }
    if (clampRight) {
        int         delta = x_root - dragx - dragWidth;
        if ((int)(dragWidth + delta) < MINWIDTH) {
            delta = MINWIDTH - dragWidth;
            clampRight = 0;
        }
        dragWidth += delta;
        action = 1;
	cursor = clampBottom ? BottomRightCursor : RightCursor;
	cursor = clampTop ? TopRightCursor : cursor;
    }
    else if (x_root >= dragx + dragWidth) {
        dragx = origx;
        dragWidth = 1 + x_root - origx;
        clampLeft = 0;
        clampRight = 1;
	clampDX = 0;
        action = 1;
	cursor = clampBottom ? BottomRightCursor : RightCursor;
	cursor = clampTop ? TopRightCursor : cursor;
    }

    if (action) {
        ConstrainSize (tmp_win, &dragWidth, &dragHeight);
        if (clampLeft)
            dragx = origx + origWidth - dragWidth;
        if (clampTop)
            dragy = origy + origHeight - dragHeight;
	if (Scr->OpaqueResize)
	    SetupWindow (tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
		 dragWidth, dragHeight, -1);
	else
          MoveOutline(Scr->Root,
            dragx - tmp_win->frame_bw,
            dragy - tmp_win->frame_bw,
            dragWidth + 2 * tmp_win->frame_bw,
            dragHeight + 2 * tmp_win->frame_bw,
	    tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
	if (Scr->BorderCursors && (cursor != tmp_win->curcurs)) {
	    tmp_win->curcurs = cursor;
	    XChangeActivePointerGrab (dpy, resizeGrabMask, cursor, CurrentTime);
	}
    }

    DisplaySize(tmp_win, dragWidth, dragHeight);
}

/***********************************************************************
 *
 *  Procedure:
 *      DoResize - move the rubberband around.  This is called for
 *                 each motion event when we are resizing
 *
 *  Inputs:
 *      x_root  - the X corrdinate in the root window
 *      y_root  - the Y corrdinate in the root window
 *      tmp_win - the current twm window
 *
 ***********************************************************************
 */

void DoResize(int x_root, int y_root, TwmWindow *tmp_win)
{
    int action;
    Cursor cursor = 0;

    action = 0;

    x_root -= clampDX;
    y_root -= clampDY;

    if (clampTop) {
        int         delta = y_root - dragy;
        if ((int)(dragHeight - delta) < MINHEIGHT) {
            delta = dragHeight - MINHEIGHT;
            clampTop = 0;
        }
        dragy += delta;
        dragHeight -= delta;
        action = 1;
	cursor = TopCursor;
    }
    else if (y_root <= dragy/* ||
             y_root == findRootInfo(root)->rooty*/) {
        dragy = y_root;
        dragHeight = origy + origHeight -
            y_root;
        clampBottom = 0;
        clampTop = 1;
	clampDY = 0;
        action = 1;
	cursor = TopCursor;
    }
    if (clampLeft) {
        int         delta = x_root - dragx;
        if ((int)(dragWidth - delta) < MINWIDTH) {
            delta = dragWidth - MINWIDTH;
            clampLeft = 0;
        }
        dragx += delta;
        dragWidth -= delta;
        action = 1;
	cursor = clampTop ? TopLeftCursor : LeftCursor;
    }
    else if (x_root <= dragx/* ||
             x_root == findRootInfo(root)->rootx*/) {
        dragx = x_root;
        dragWidth = origx + origWidth -
            x_root;
        clampRight = 0;
        clampLeft = 1;
	clampDX = 0;
        action = 1;
	cursor = clampTop ? TopLeftCursor : LeftCursor;
    }
    if (clampBottom) {
        int         delta = y_root - dragy - dragHeight;
        if ((int)(dragHeight + delta) < MINHEIGHT) {
            delta = MINHEIGHT - dragHeight;
            clampBottom = 0;
        }
        dragHeight += delta;
        action = 1;
	cursor = clampLeft ? BottomLeftCursor : BottomCursor;
    }
    else if (y_root >= dragy + dragHeight - 1/* ||
           y_root == findRootInfo(root)->rooty
           + findRootInfo(root)->rootheight - 1*/) {
        dragy = origy;
        dragHeight = 1 + y_root - dragy;
        clampTop = 0;
        clampBottom = 1;
	clampDY = 0;
        action = 1;
	cursor = clampLeft ? BottomLeftCursor : BottomCursor;
    }
    if (clampRight) {
        int         delta = x_root - dragx - dragWidth;
        if ((int)(dragWidth + delta) < MINWIDTH) {
            delta = MINWIDTH - dragWidth;
            clampRight = 0;
        }
        dragWidth += delta;
        action = 1;
	cursor = clampBottom ? BottomRightCursor : RightCursor;
	cursor = clampTop ? TopRightCursor : cursor;
    }
    else if (x_root >= dragx + dragWidth - 1/* ||
             x_root == findRootInfo(root)->rootx +
             findRootInfo(root)->rootwidth - 1*/) {
        dragx = origx;
        dragWidth = 1 + x_root - origx;
        clampLeft = 0;
        clampRight = 1;
	clampDX = 0;
        action = 1;
	cursor = clampBottom ? BottomRightCursor : RightCursor;
	cursor = clampTop ? TopRightCursor : cursor;
    }

    if (action) {
        ConstrainSize (tmp_win, &dragWidth, &dragHeight);
        if (clampLeft)
            dragx = origx + origWidth - dragWidth;
        if (clampTop)
            dragy = origy + origHeight - dragHeight;
	if (Scr->OpaqueResize && ! resizeWhenAdd)
	    SetupWindow (tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
		 dragWidth, dragHeight, -1);
	else
          MoveOutline(Scr->Root,
            dragx - tmp_win->frame_bw,
            dragy - tmp_win->frame_bw,
            dragWidth + 2 * tmp_win->frame_bw,
            dragHeight + 2 * tmp_win->frame_bw,
	    tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
	if (Scr->BorderCursors && (cursor != tmp_win->curcurs)) {
	    tmp_win->curcurs = cursor;
	    XChangeActivePointerGrab (dpy, resizeGrabMask, cursor, CurrentTime);
	}
    }

    DisplaySize(tmp_win, dragWidth, dragHeight);
}

/***********************************************************************
 *
 *  Procedure:
 *      DisplaySize - display the size in the dimensions window
 *
 *  Inputs:
 *      tmp_win - the current twm window
 *      width   - the width of the rubber band
 *      height  - the height of the rubber band
 *
 ***********************************************************************
 */

void DisplaySize(TwmWindow *tmp_win, int width, int height)
{
    char str[100];
    int dwidth;
    int dheight;
    
    if (last_width == width && last_height == height)
        return;

    last_width = width;
    last_height = height;

    dheight = height - tmp_win->title_height - 2 * tmp_win->frame_bw3D;
    dwidth = width - 2 * tmp_win->frame_bw3D;

    /*
     * ICCCM says that PMinSize is the default is no PBaseSize is given,
     * and vice-versa.
     */
    if (tmp_win->hints.flags&(PMinSize|PBaseSize) && tmp_win->hints.flags & PResizeInc)
    {
	if (tmp_win->hints.flags & PBaseSize) {
	    dwidth -= tmp_win->hints.base_width;
	    dheight -= tmp_win->hints.base_height;
	} else {
	    dwidth -= tmp_win->hints.min_width;
	    dheight -= tmp_win->hints.min_height;
	}
    }

    if (tmp_win->hints.flags & PResizeInc)
    {
        dwidth /= tmp_win->hints.width_inc;
        dheight /= tmp_win->hints.height_inc;
    }

    (void) sprintf (str, " %4d x %-4d ", dwidth, dheight);
    XRaiseWindow(dpy, Scr->SizeWindow);

    Draw3DBorder (Scr->SizeWindow, 0, 0,
		Scr->SizeStringOffset + Scr->SizeStringWidth + SIZE_HINDENT,
		Scr->SizeFont.height + SIZE_VINDENT * 2,
		2, Scr->DefaultC, off, False, False);

    FB(Scr->DefaultC.fore, Scr->DefaultC.back);
    XmbDrawImageString (dpy, Scr->SizeWindow, Scr->SizeFont.font_set,
		      Scr->NormalGC, Scr->SizeStringOffset,
		      Scr->SizeFont.ascent + SIZE_VINDENT, str, 13);
}

/***********************************************************************
 *
 *  Procedure:
 *      EndResize - finish the resize operation
 *
 ***********************************************************************
 */

void EndResize(void)
{
    TwmWindow *tmp_win;

#ifdef DEBUG
    fprintf(stderr, "EndResize\n");
#endif

    MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
    XUnmapWindow(dpy, Scr->SizeWindow);

    tmp_win = GetTwmWindow(ResizeWindow);
    if (!tmp_win) return;

    ConstrainSize (tmp_win, &dragWidth, &dragHeight);

    if (dragWidth != tmp_win->frame_width ||
        dragHeight != tmp_win->frame_height)
            tmp_win->zoomed = ZOOM_NONE;

    SetupWindow (tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
		 dragWidth, dragHeight, -1);

    if (tmp_win->iconmgr)
    {
	int ncols = tmp_win->iconmgrp->cur_columns;
	if (ncols == 0) ncols = 1;

	tmp_win->iconmgrp->width = (int) (((dragWidth - 2 * tmp_win->frame_bw3D) *
			(long) tmp_win->iconmgrp->columns)
					  / ncols);
        PackIconManager(tmp_win->iconmgrp);
    }

    if (!Scr->NoRaiseResize) {
        RaiseWindow(tmp_win);
	WMapRaise (tmp_win);
    }
    UninstallRootColormap();

    ResizeWindow = None;
}

void MenuEndResize(TwmWindow *tmp_win)
{
    MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
    XUnmapWindow(dpy, Scr->SizeWindow);
    ConstrainSize (tmp_win, &dragWidth, &dragHeight);
    AddingX = dragx - tmp_win->frame_bw;
    AddingY = dragy - tmp_win->frame_bw;
    AddingW = dragWidth;
    AddingH = dragHeight;
    SetupWindow (tmp_win, AddingX, AddingY, AddingW, AddingH, -1);
}



/***********************************************************************
 *
 *  Procedure:
 *      AddEndResize - finish the resize operation for AddWindo<w
 *
 ***********************************************************************
 */

void AddEndResize(TwmWindow *tmp_win)
{

#ifdef DEBUG
    fprintf(stderr, "AddEndResize\n");
#endif

    ConstrainSize (tmp_win, &dragWidth, &dragHeight);
    AddingX = dragx;
    AddingY = dragy;
    AddingW = dragWidth + (2 * tmp_win->frame_bw);
    AddingH = dragHeight + (2 * tmp_win->frame_bw);
}

/***********************************************************************
 *
 *  Procedure:
 *      ConstrainSize - adjust the given width and height to account for the
 *              constraints imposed by size hints
 *
 *      The general algorithm, especially the aspect ratio stuff, is
 *      borrowed from uwm's CheckConsistency routine.
 * 
 ***********************************************************************/

void ConstrainSize (TwmWindow *tmp_win,
		    unsigned int *widthp, unsigned int *heightp)
{
#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
#define _min(a,b) (((a) < (b)) ? (a) : (b))

    int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
    int baseWidth, baseHeight;
    int dwidth = *widthp, dheight = *heightp;


    dwidth  -= 2 * tmp_win->frame_bw3D;
    dheight -= (tmp_win->title_height + 2 * tmp_win->frame_bw3D);

    if (tmp_win->hints.flags & PMinSize) {
        minWidth = tmp_win->hints.min_width;
        minHeight = tmp_win->hints.min_height;
    } else if (tmp_win->hints.flags & PBaseSize) {
        minWidth = tmp_win->hints.base_width;
        minHeight = tmp_win->hints.base_height;
    } else {
        minWidth = minHeight = 1;
    }

    if (tmp_win->hints.flags & PBaseSize) {
	baseWidth = tmp_win->hints.base_width;
	baseHeight = tmp_win->hints.base_height;
    } else if (tmp_win->hints.flags & PMinSize) {
	baseWidth = tmp_win->hints.min_width;
	baseHeight = tmp_win->hints.min_height;
    } else {
	baseWidth = baseHeight = 0;
    }


    if (tmp_win->hints.flags & PMaxSize) {
        maxWidth = _min (Scr->MaxWindowWidth, tmp_win->hints.max_width);
        maxHeight = _min (Scr->MaxWindowHeight, tmp_win->hints.max_height);
    } else {
        maxWidth = Scr->MaxWindowWidth;
	maxHeight = Scr->MaxWindowHeight;
    }

    if (tmp_win->hints.flags & PResizeInc) {
        xinc = tmp_win->hints.width_inc;
        yinc = tmp_win->hints.height_inc;
	if (xinc == 0) xinc = 1;
	if (yinc == 0) yinc = 1;
    } else {
        xinc = yinc = 1;
    }

    /*
     * First, clamp to min and max values
     */
    if (dwidth < minWidth) dwidth = minWidth;
    if (dheight < minHeight) dheight = minHeight;

    if (dwidth > maxWidth) dwidth = maxWidth;
    if (dheight > maxHeight) dheight = maxHeight;


    /*
     * Second, fit to base + N * inc
     */
    dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
    dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;


    /*
     * Third, adjust for aspect ratio
     */
    /*
     * The math looks like this:
     *
     * minAspectX    dwidth     maxAspectX
     * ---------- <= ------- <= ----------
     * minAspectY    dheight    maxAspectY
     *
     * If that is multiplied out, then the width and height are
     * invalid in the following situations:
     *
     * minAspectX * dheight > minAspectY * dwidth
     * maxAspectX * dheight < maxAspectY * dwidth
     * 
     */
    
    if (tmp_win->hints.flags & PAspect) {
	int minAspectX = tmp_win->hints.min_aspect.x;
	int minAspectY = tmp_win->hints.min_aspect.y;
	int maxAspectX = tmp_win->hints.max_aspect.x;
	int maxAspectY = tmp_win->hints.max_aspect.y;

	if (minAspectX && minAspectY && maxAspectX && maxAspectY) {
	    if (minAspectX * dheight > minAspectY * dwidth) {
		delta = makemult(minAspectX * dheight / minAspectY - dwidth,
				 xinc);
		if (dwidth + delta <= maxWidth) {
		    dwidth += delta;
		} else {
		    delta = makemult(dheight - dwidth*minAspectY/minAspectX,
				     yinc);
		    if (dheight - delta >= minHeight) {
			dheight -= delta;
		    }
		}
	    }

	    if (maxAspectX * dheight < maxAspectY * dwidth) {
		delta = makemult(dwidth * maxAspectY / maxAspectX - dheight,
				 yinc);
		if (dheight + delta <= maxHeight) {
		    dheight += delta;
		} else {
		    delta = makemult(dwidth - maxAspectX*dheight/maxAspectY,
				     xinc);
		    if (dwidth - delta >= minWidth) {
			dwidth -= delta;
		    }
		}
	    }
	}
    }


    /*
     * Fourth, account for border width and title height
     */
    *widthp = dwidth + 2 * tmp_win->frame_bw3D;
    *heightp = dheight + tmp_win->title_height + 2 * tmp_win->frame_bw3D;
}


/***********************************************************************
 *
 *  Procedure:
 *      SetupWindow - set window sizes, this was called from either
 *              AddWindow, EndResize, or HandleConfigureNotify.
 *
 *  Inputs:
 *      tmp_win - the TwmWindow pointer
 *      x       - the x coordinate of the upper-left outer corner of the frame
 *      y       - the y coordinate of the upper-left outer corner of the frame
 *      w       - the width of the frame window w/o border
 *      h       - the height of the frame window w/o border
 *      bw      - the border width of the frame window or -1 not to change
 *
 *  Special Considerations:
 *      This routine will check to make sure the window is not completely
 *      off the display, if it is, it'll bring some of it back on.
 *
 *      The tmp_win->frame_XXX variables should NOT be updated with the
 *      values of x,y,w,h prior to calling this routine, since the new
 *      values are compared against the old to see whether a synthetic
 *      ConfigureNotify event should be sent.  (It should be sent if the
 *      window was moved but not resized.)
 *
 ***********************************************************************
 */

void SetupWindow (TwmWindow *tmp_win, int x, int y, int w, int h, int bw)
{
    SetupFrame (tmp_win, x, y, w, h, bw, False);
}

void SetupFrame (TwmWindow *tmp_win, int x, int y, int w, int h, int bw,
		 Bool sendEvent)	/* whether or not to force a send */
{
    XEvent client_event;
    XWindowChanges frame_wc, xwc;
    unsigned long frame_mask, xwcm;
    int title_width, title_height;
    int reShape;

#ifdef DEBUG
    fprintf (stderr, "SetupWindow: x=%d, y=%d, w=%d, h=%d, bw=%d\n",
	     x, y, w, h, bw);
#endif

    if (x >= Scr->rootw)
      x = Scr->rootw - 16;	/* one "average" cursor width */
    if (y >= Scr->rooth)
      y = Scr->rooth - 16;	/* one "average" cursor width */
    if (bw < 0)
      bw = tmp_win->frame_bw;		/* -1 means current frame width */

    if (tmp_win->iconmgr) {
	tmp_win->iconmgrp->width = w - (2 * tmp_win->frame_bw3D);
	h = tmp_win->iconmgrp->height + tmp_win->title_height + (2 * tmp_win->frame_bw3D);
    }

    /*
     * According to the July 27, 1988 ICCCM draft, we should send a
     * "synthetic" ConfigureNotify event to the client if the window
     * was moved but not resized.
     */
    if (((x != tmp_win->frame_x || y != tmp_win->frame_y) &&
	 (w == tmp_win->frame_width && h == tmp_win->frame_height)) ||
	(bw != tmp_win->frame_bw))
      sendEvent = TRUE;

    xwcm = CWWidth;
    title_width  = xwc.width = w - (2 * tmp_win->frame_bw3D);
    title_height = Scr->TitleHeight + bw;
    ComputeWindowTitleOffsets (tmp_win, xwc.width, True);

    reShape = (tmp_win->wShaped ? TRUE : FALSE);
    if (tmp_win->squeeze_info/* && !tmp_win->squeezed*/)	/* check for title shaping */
    {
	title_width = tmp_win->rightx + Scr->TBInfo.rightoff;
	if (title_width < xwc.width)
	{
	    xwc.width = title_width;
	    if (tmp_win->frame_height != h ||
	    	tmp_win->frame_width != w ||
		tmp_win->frame_bw != bw ||
	    	title_width != tmp_win->title_width)
	    	reShape = TRUE;
	}
	else
	{
	    if (!tmp_win->wShaped) reShape = TRUE;
	    title_width = xwc.width;
	}
    }

    tmp_win->title_width = title_width;
    if (tmp_win->title_height) tmp_win->title_height = title_height;

    if (tmp_win->title_w) {
	if (bw != tmp_win->frame_bw) {
	    xwc.border_width = bw;
	    tmp_win->title_x = xwc.x = tmp_win->frame_bw3D - bw;
	    tmp_win->title_y = xwc.y = tmp_win->frame_bw3D - bw;
	    xwcm |= (CWX | CWY | CWBorderWidth);
	}
	
	XConfigureWindow(dpy, tmp_win->title_w, xwcm, &xwc);
    }
    if (tmp_win->attr.width != w)
	tmp_win->widthEverChangedByUser = True;

    if (tmp_win->attr.height != (h - tmp_win->title_height))
	tmp_win->heightEverChangedByUser = True;

    if (!tmp_win->squeezed) {
	tmp_win->attr.width  = w - (2 * tmp_win->frame_bw3D);
	tmp_win->attr.height = h - tmp_win->title_height - (2 * tmp_win->frame_bw3D);
    }
    if (tmp_win->squeezed) {
	if (x != tmp_win->frame_x) tmp_win->actual_frame_x += x - tmp_win->frame_x;
	if (y != tmp_win->frame_y) tmp_win->actual_frame_y += y - tmp_win->frame_y;
    }
    /* 
     * fix up frame and assign size/location values in tmp_win
     */
    frame_mask = 0;
    if (bw != tmp_win->frame_bw) {
	frame_wc.border_width = tmp_win->frame_bw = bw;
	frame_mask |= CWBorderWidth;
    }
    tmp_win->frame_x = x;
    tmp_win->frame_y = y;
    if (tmp_win->UnmapByMovingFarAway && !visible(tmp_win)) {
	frame_wc.x = Scr->rootw  + 1;
	frame_wc.y = Scr->rooth + 1;
    } else {
	frame_wc.x = tmp_win->frame_x;
	frame_wc.y = tmp_win->frame_y;
    }
    frame_wc.width = tmp_win->frame_width = w;
    frame_wc.height = tmp_win->frame_height = h;
    frame_mask |= (CWX | CWY | CWWidth | CWHeight);
    XConfigureWindow (dpy, tmp_win->frame, frame_mask, &frame_wc);

    XMoveResizeWindow (dpy, tmp_win->w, tmp_win->frame_bw3D,
			tmp_win->title_height + tmp_win->frame_bw3D,
			tmp_win->attr.width, tmp_win->attr.height);

    /*
     * fix up highlight window
     */
    if (tmp_win->title_height && tmp_win->hilite_wl)
    {
	xwc.width = (tmp_win->name_x - tmp_win->highlightxl - 2);
        if (xwc.width <= 0) {
            xwc.x = Scr->rootw;	/* move offscreen */
            xwc.width = 1;
        } else {
            xwc.x = tmp_win->highlightxl;
        }

        xwcm = CWX | CWWidth;
        XConfigureWindow(dpy, tmp_win->hilite_wl, xwcm, &xwc);
    }
    if (tmp_win->title_height && tmp_win->hilite_wr)
    {
	xwc.width = (tmp_win->rightx - tmp_win->highlightxr);
	if (Scr->TBInfo.nright > 0) xwc.width -= 2 * Scr->TitlePadding;
	if (Scr->use3Dtitles) xwc.width -= Scr->TitleButtonShadowDepth;
        if (xwc.width <= 0) {
            xwc.x = Scr->rootw;	/* move offscreen */
            xwc.width = 1;
        } else {
            xwc.x = tmp_win->highlightxr;
        }

        xwcm = CWX | CWWidth;
        XConfigureWindow(dpy, tmp_win->hilite_wr, xwcm, &xwc);
    }
    if (tmp_win->title_height && tmp_win->lolite_wl)
    {
	xwc.width = (tmp_win->name_x - tmp_win->highlightxl);
	if (Scr->use3Dtitles) xwc.width -= 4;
	if (xwc.width <= 0) {
	     xwc.x = Scr->rootw;        /* move offscreen */
	     xwc.width = 1;
	} else {
	     xwc.x = tmp_win->highlightxl;
	}

	xwcm = CWX | CWWidth;
	XConfigureWindow(dpy, tmp_win->lolite_wl, xwcm, &xwc);
    }
    if (tmp_win->title_height && tmp_win->lolite_wr)
    {
	xwc.width = (tmp_win->rightx - tmp_win->highlightxr);
	if (Scr->TBInfo.nright > 0) xwc.width -= Scr->TitlePadding;
	if (Scr->use3Dtitles) xwc.width -= 4;
	if (xwc.width <= 0) {
	     xwc.x = Scr->rootw;        /* move offscreen */
	     xwc.width = 1;
	} else {
	     xwc.x = tmp_win->highlightxr;
	}

	xwcm = CWX | CWWidth; 
	XConfigureWindow(dpy, tmp_win->lolite_wr, xwcm, &xwc);
    }
    if (HasShape && reShape) {
	SetFrameShape (tmp_win);
    }
    WMapSetupWindow (tmp_win, x, y, w, h);
    if (sendEvent)
    {
        client_event.type = ConfigureNotify;
        client_event.xconfigure.display = dpy;
        client_event.xconfigure.event = tmp_win->w;
        client_event.xconfigure.window = tmp_win->w;
        client_event.xconfigure.x = (x + tmp_win->frame_bw - tmp_win->old_bw
					+ tmp_win->frame_bw3D);
        client_event.xconfigure.y = (y + tmp_win->frame_bw +
				     tmp_win->title_height - tmp_win->old_bw
					+ tmp_win->frame_bw3D);
        client_event.xconfigure.width = tmp_win->attr.width;
        client_event.xconfigure.height = tmp_win->attr.height;
        client_event.xconfigure.border_width = tmp_win->old_bw;
        /* Real ConfigureNotify events say we're above title window, so ... */
	/* what if we don't have a title ????? */
        client_event.xconfigure.above = tmp_win->frame;
        client_event.xconfigure.override_redirect = False;
        XSendEvent(dpy, tmp_win->w, False, StructureNotifyMask, &client_event);
    }
}


/**********************************************************************
 *  Rutgers mod #1   - rocky.
 *  Procedure:
 *         fullzoom - zooms window to full height of screen or
 *                    to full height and width of screen. (Toggles
 *                    so that it can undo the zoom - even when switching
 *                    between fullzoom and vertical zoom.)
 *
 *  Inputs:
 *         tmp_win - the TwmWindow pointer
 *
 *
 **********************************************************************
 */

void fullzoom(TwmWindow *tmp_win, int flag)
{
    Window      junkRoot;
    unsigned int junkbw, junkDepth;
    int basex, basey;
    int border_x, border_y;
    int frame_bw_times_2;
    int  zwidth = Scr->rootw;
    int zheight = Scr->rooth;
    int tmpX, tmpY, tmpW, tmpH;



	XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot,
	        &dragx, &dragy, (unsigned int *)&dragWidth, (unsigned int *)&dragHeight, &junkbw,
	        &junkDepth);

	basex = Scr->BorderLeft;
	basey = Scr->BorderTop;

        border_x = Scr->BorderLeft + Scr->BorderRight;
        border_y = Scr->BorderTop + Scr->BorderBottom;

	if (tmp_win->winbox) {
	    XWindowAttributes winattrs;
	    if (XGetWindowAttributes(dpy, tmp_win->winbox->window, &winattrs)) {
		zwidth   = winattrs.width;
		zheight  = winattrs.height;
	    }
	    basex    = 0;
	    basey    = 0;
            border_x = 0;
            border_y = 0;
	}
	if (tmp_win->zoomed == flag)
	{
		dragHeight = tmp_win->save_frame_height;
		dragWidth = tmp_win->save_frame_width;
		dragx = tmp_win->save_frame_x;
		dragy = tmp_win->save_frame_y;
		tmp_win->zoomed = ZOOM_NONE;
	}
	else
	{
		if (tmp_win->zoomed == ZOOM_NONE)
		{
			tmp_win->save_frame_x = dragx;
			tmp_win->save_frame_y = dragy;
			tmp_win->save_frame_width = dragWidth;
			tmp_win->save_frame_height = dragHeight;
			tmp_win->zoomed = flag;
		}
		else
			tmp_win->zoomed = flag;

		frame_bw_times_2 = 2*tmp_win->frame_bw;

		switch (flag)
        {
        case ZOOM_NONE:
            break;
        case F_ZOOM:
            dragHeight = zheight - border_y - frame_bw_times_2;
            dragy=basey;
            break;
        case F_HORIZOOM:
            dragx = basex;
            dragWidth = zwidth - border_x - frame_bw_times_2;
            break;
        case F_FULLZOOM:
            dragx = basex;
            dragy = basey;
            dragHeight = zheight - border_y - frame_bw_times_2;
            dragWidth = zwidth - border_x - frame_bw_times_2;
            break;
        case F_LEFTZOOM:
            dragx = basex;
            dragy = basey;
            dragHeight = zheight - border_y - frame_bw_times_2;
            dragWidth = (zwidth - border_x)/2 - frame_bw_times_2;
            break;
        case F_RIGHTZOOM:
            dragx = basex + (zwidth - border_x)/2;
            dragy = basey;
            dragHeight = zheight - border_y - frame_bw_times_2;
            dragWidth = (zwidth - border_x)/2 - frame_bw_times_2;
            break;
        case F_TOPZOOM:
            dragx = basex;
            dragy = basey;
            dragHeight = (zheight - border_y)/2 - frame_bw_times_2;
            dragWidth = zwidth - border_x - frame_bw_times_2;
            break;
        case F_BOTTOMZOOM:
            dragx = basex;
            dragy = basey + (zheight - border_y)/2;
            dragHeight = (zheight - border_y)/2 - frame_bw_times_2;
            dragWidth = zwidth - border_x - frame_bw_times_2;
            break;
         }
      }

    if (!Scr->NoRaiseResize)
        RaiseWindow(tmp_win);

    ConstrainSize(tmp_win, &dragWidth, &dragHeight);
#ifdef BETTERZOOM 
	if (flag == F_ZOOM)
	{
		if (dragy + dragHeight < tmp_win->save_frame_y + tmp_win->save_frame_height)
			dragy = tmp_win->save_frame_y + tmp_win->save_frame_height - dragHeight;
	}
#endif
    SetupWindow (tmp_win, dragx , dragy , dragWidth, dragHeight, -1);
/* I don't understand the reason of this. Claude.
    XUngrabPointer (dpy, CurrentTime);
*/
    XUngrabServer (dpy);

   XQueryPointer(dpy, 
		 tmp_win->w, 
		 &junkRoot, &junkRoot, 
		 &tmpX, &tmpY, &tmpW, &tmpH, &junkDepth);
   if (tmp_win->frame_x > tmpX ||
       tmp_win->frame_x + tmp_win->frame_width < tmpX ||
       tmp_win->frame_y > tmpY ||
       tmp_win->frame_y + tmp_win->frame_height < tmpY) {
      XWarpPointer(dpy, Scr->Root, tmp_win->w, 0, 0, 0, 0, 0, 0);
   }
}

void savegeometry (TwmWindow *tmp_win)
{
    if (!tmp_win) return;
    tmp_win->savegeometry.x      = tmp_win->frame_x;
    tmp_win->savegeometry.y      = tmp_win->frame_y;
    tmp_win->savegeometry.width  = tmp_win->frame_width;
    tmp_win->savegeometry.height = tmp_win->frame_height;
}

void restoregeometry (TwmWindow *tmp_win)
{
    int x, y;
    unsigned int w, h;

    if (!tmp_win) return;
    if (tmp_win->savegeometry.width == (unsigned int)-1) return;
    x = tmp_win->savegeometry.x;
    y = tmp_win->savegeometry.y;
    w = tmp_win->savegeometry.width;
    h = tmp_win->savegeometry.height;
    SetupWindow (tmp_win, x, y, w, h, -1);
}

void SetFrameShape (TwmWindow *tmp)
{
    /*
     * see if the titlebar needs to move
     */
    if (tmp->title_w) {
	int oldx = tmp->title_x, oldy = tmp->title_y;
	ComputeTitleLocation (tmp);
	if (oldx != tmp->title_x || oldy != tmp->title_y)
	  XMoveWindow (dpy, tmp->title_w, tmp->title_x, tmp->title_y);
    }

    /*
     * The frame consists of the shape of the contents window offset by
     * title_height or'ed with the shape of title_w (which is always
     * rectangular).
     */
    if (tmp->wShaped) {
	/*
	 * need to do general case
	 */
	XShapeCombineShape (dpy, tmp->frame, ShapeBounding,
			    tmp->frame_bw3D, tmp->title_height + tmp->frame_bw3D, tmp->w,
			    ShapeBounding, ShapeSet);
	if (tmp->title_w) {
	    XShapeCombineShape (dpy, tmp->frame, ShapeBounding,
				tmp->title_x + tmp->frame_bw,
				tmp->title_y + tmp->frame_bw,
				tmp->title_w, ShapeBounding,
				ShapeUnion);
	}
    } else {
	/*
	 * can optimize rectangular contents window
	 */
	if (tmp->squeeze_info && !tmp->squeezed) {
	    XRectangle  newBounding[2];
	    XRectangle  newClip[2];
	    int fbw2 = 2 * tmp->frame_bw;

	    /*
	     * Build the border clipping rectangles; one around title, one
	     * around window.  The title_[xy] field already have had frame_bw
	     * subtracted off them so that they line up properly in the frame.
	     *
	     * The frame_width and frame_height do *not* include borders.
	     */
	    /* border */
	    newBounding[0].x = tmp->title_x - tmp->frame_bw3D;
	    newBounding[0].y = tmp->title_y - tmp->frame_bw3D;
	    newBounding[0].width = tmp->title_width + fbw2 + 2 * tmp->frame_bw3D;
	    newBounding[0].height = tmp->title_height;
	    newBounding[1].x = -tmp->frame_bw;
	    newBounding[1].y = Scr->TitleHeight;
	    newBounding[1].width = tmp->attr.width + fbw2 + 2 * tmp->frame_bw3D;
	    newBounding[1].height = tmp->attr.height + fbw2 + 2 * tmp->frame_bw3D;
	    XShapeCombineRectangles (dpy, tmp->frame, ShapeBounding, 0, 0,
				     newBounding, 2, ShapeSet, YXBanded);
	    /* insides */
	    newClip[0].x = tmp->title_x + tmp->frame_bw - tmp->frame_bw3D;
	    newClip[0].y = 0;
	    newClip[0].width = tmp->title_width + 2 * tmp->frame_bw3D;
	    newClip[0].height = Scr->TitleHeight + tmp->frame_bw3D;
	    newClip[1].x = 0;
	    newClip[1].y = tmp->title_height;
	    newClip[1].width = tmp->attr.width + 2 * tmp->frame_bw3D;
	    newClip[1].height = tmp->attr.height + 2 * tmp->frame_bw3D;
	    XShapeCombineRectangles (dpy, tmp->frame, ShapeClip, 0, 0,
				     newClip, 2, ShapeSet, YXBanded);
	} else {
	    (void) XShapeCombineMask (dpy, tmp->frame, ShapeBounding, 0, 0,
 				      None, ShapeSet);
	    (void) XShapeCombineMask (dpy, tmp->frame, ShapeClip, 0, 0,
				      None, ShapeSet);
	}
    }
}

void ChangeSize (char *in_string, TwmWindow *tmp_win)
{
  int i=0, j=0, change=0, size=0;
  char tmp_string[10], tmp_string2[10];
  char operator ='\0';
  char size_string[10];
  int rx, ry, wx, wy, mr;
  Window  rr, cr;

  if (Isdigit(in_string[0]))
    {
      while(in_string[i] != 'x')
	{
	  tmp_string[i] = in_string[i];
	  i++;
	}
      tmp_string[i]='\0';
      i++;
      while(in_string[i] != '\0')
	{
	  tmp_string2[j] = in_string[i];
	  i++;
	  j++;
	}

      wx = atoi(tmp_string);
      wy = atoi(tmp_string2);

      if (wy < tmp_win->title_height+1)
	wy = tmp_win->title_height+1;

      SetupWindow (tmp_win, tmp_win->frame_x, tmp_win->frame_y,
		       wx, wy+tmp_win->title_height, -1);
    }
  else
    {
      while(in_string[i] != ' ')
	{
	  tmp_string[i] = in_string[i];
	  i++;
	}
      tmp_string[i]='\0';

      i++;
      operator = in_string[i];
      i++;

      while(in_string[i] != '\0')
	{
	  size_string[j] = in_string[i];
	  i++;
	  j++;
	}
      size_string[j] = '\0';

      change = atoi(size_string);

      if (operator == '-')
	{
	  change = 0 - change;
	}
      else if (operator != '+')
	{
	  /* error */
	  fprintf (stderr, "%s: Bad argument to f.changesize\n", ProgramName);
	  return;
	}

      if (strcmp("bottom", tmp_string) == 0)
	{
	  size = tmp_win->frame_height + change;

	  if (size < (tmp_win->title_height+1))
	    size = tmp_win->title_height+1;

	  SetupWindow (tmp_win, tmp_win->frame_x, tmp_win->frame_y,
		       tmp_win->frame_width, size , 
		       -1);

	  XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy, 
			(unsigned int*)&mr);

	  if ((wy+tmp_win->title_height) > size)
	    XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0);
	}
      else if (strcmp("top", tmp_string) == 0)
	{
	  size = tmp_win->frame_height + change;

	  if (size < (tmp_win->title_height+1))
	    size = tmp_win->title_height+1;

	  SetupWindow (tmp_win, tmp_win->frame_x, (tmp_win->frame_y - change),
		       tmp_win->frame_width, size, 
		       -1);
      
	  XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy, 
			(unsigned int*)&mr);

	  if ((wy + tmp_win->title_height) > size)
	    XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0);


	}
      else if (strcmp("left", tmp_string) == 0)
	{
	  size = tmp_win->frame_width + change;

	  if (size < 1)
	    size = 1;

	  SetupWindow (tmp_win, (tmp_win->frame_x - change), tmp_win->frame_y,
		       size, tmp_win->frame_height, 
		       -1);
      
	  XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy, 
			(unsigned int*)&mr);

	  if (wx > size)
	    XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0);

      
	}
      else if (strcmp("right", tmp_string) == 0)
	{
	  size = tmp_win->frame_width + change;

	  if (size < 1)
	    size = 1;

	  SetupWindow (tmp_win, tmp_win->frame_x, tmp_win->frame_y,
		       size, tmp_win->frame_height, 
		       -1);

	  XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy, 
			(unsigned int*)&mr);

	  if (wx > size)
	    XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0);
	  
	}
      else
	{
	  /* error */
	  fprintf (stderr, "%s: Bad argument to f.changesize\n", ProgramName);
	  return;
	}
    }
}

/*
 * Squeezed Title:
 * 
 *                         tmp->title_x
 *                   0     |
 *  tmp->title_y   ........+--------------+.........  -+,- tmp->frame_bw
 *             0   : ......| +----------+ |....... :  -++
 *                 : :     | |          | |      : :   ||-Scr->TitleHeight
 *                 : :     | |          | |      : :   ||
 *                 +-------+ +----------+ +--------+  -+|-tmp->title_height
 *                 | +---------------------------+ |  --+
 *                 | |                           | |
 *                 | |                           | |
 *                 | |                           | |
 *                 | |                           | |
 *                 | |                           | |
 *                 | +---------------------------+ |
 *                 +-------------------------------+
 * 
 * 
 * Unsqueezed Title:
 * 
 *                 tmp->title_x
 *                 | 0
 *  tmp->title_y   +-------------------------------+  -+,tmp->frame_bw
 *             0   | +---------------------------+ |  -+'
 *                 | |                           | |   |-Scr->TitleHeight
 *                 | |                           | |   |
 *                 + +---------------------------+ +  -+
 *                 |-+---------------------------+-|
 *                 | |                           | |
 *                 | |                           | |
 *                 | |                           | |
 *                 | |                           | |
 *                 | |                           | |
 *                 | +---------------------------+ |
 *                 +-------------------------------+
 * 
 * 
 * 
 * Dimensions and Positions:
 * 
 *     frame orgin                 (0, 0)
 *     frame upper left border     (-tmp->frame_bw, -tmp->frame_bw)
 *     frame size w/o border       tmp->frame_width , tmp->frame_height
 *     frame/title border width    tmp->frame_bw
 *     extra title height w/o bdr  tmp->title_height = TitleHeight + frame_bw
 *     title window height         Scr->TitleHeight
 *     title origin w/o border     (tmp->title_x, tmp->title_y)
 *     client origin               (0, Scr->TitleHeight + tmp->frame_bw)
 *     client size                 tmp->attr.width , tmp->attr.height
 * 
 * When shaping, need to remember that the width and height of rectangles
 * are really deltax and deltay to lower right handle corner, so they need
 * to have -1 subtracted from would normally be the actual extents.
 */
