/****************************************************************************
 * This module is all original code
 * by Rob Nation
 * Copyright 1993, Robert Nation
 *     You may use this code for any purpose, as long as the original
 *     copyright remains in the source code and all documentation
 ****************************************************************************/


/***********************************************************************
 *
 * fvwm window border drawing code
 *
 ***********************************************************************/

#include "config.h"

#include <stdio.h>
#include <signal.h>
#include <string.h>

#include "fvwm.h"
#include "misc.h"
#include "parse.h"
#include "screen.h"
#include "module.h"

#ifdef SHAPE
#include <X11/extensions/shape.h>
#endif

void DrawButton(FvwmWindow *t,
                Window win,
                int W,
                int H,
                ButtonFace *bf,
                GC ReliefGC, GC ShadowGC,
		Boolean inverted,
		int stateflags);

#ifdef VECTOR_BUTTONS
void DrawLinePattern(Window win,
                     GC ReliefGC,
                     GC ShadowGC,
		     struct vector_coords *coords,
                     int w, int h);
#endif

/* macro rules to get button state */
#if defined(ACTIVEDOWN_BTNS) && defined(INACTIVE_BTNS)
#define GetButtonState(window)						\
        (onoroff ? ((PressedW == (window)) ? ActiveDown : ActiveUp)	\
        : Inactive)
#else
#ifdef ACTIVEDOWN_BTNS
#define GetButtonState(window)						\
        ((PressedW == (window)) ? ActiveDown : ActiveUp)
#endif
#ifdef INACTIVE_BTNS
#define GetButtonState(window) (onoroff ? ActiveUp : Inactive)
#endif
#endif

#if !defined(ACTIVEDOWN_BTNS) && !defined(INACTIVE_BTNS)
#define GetButtonState(window) ActiveUp
#endif

/* macro to change window background color/pixmap */
#define ChangeWindowColor(window,valuemask) {				\
        if(NewColor)							\
        {								\
          XChangeWindowAttributes(dpy,window,valuemask, &attributes);	\
          XClearWindow(dpy,window);					\
        }								\
      }

extern Window PressedW;
XGCValues Globalgcv;
unsigned long Globalgcm;
/****************************************************************************
 *
 * Redraws the windows borders
 *
 ****************************************************************************/
void SetBorder (FvwmWindow *t, Bool onoroff,Bool force,Bool Mapped,
		Window expose_win)
{
  int y, i, x;
  GC ReliefGC,ShadowGC;
  Pixel BorderColor,BackColor;
  Pixmap BackPixmap,TextColor;
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
  Pixmap TexturePixmap = None;
  XSetWindowAttributes notex_attributes;
  unsigned long notex_valuemask;
#endif
  Bool NewColor = False;
  XSetWindowAttributes attributes;
  unsigned long valuemask;
  static unsigned int corners[4];
  Window w;

  corners[0] = TOP_HILITE | LEFT_HILITE;
  corners[1] = TOP_HILITE | RIGHT_HILITE;
  corners[2] = BOTTOM_HILITE | LEFT_HILITE;
  corners[3] = BOTTOM_HILITE | RIGHT_HILITE;

  if(!t)
    return;

  if (onoroff)
  {
    /* don't re-draw just for kicks */
    if((!force)&&(Scr.Hilite == t))
      return;

    if(Scr.Hilite != t)
      NewColor = True;

    /* make sure that the previously highlighted window got unhighlighted */
    if((Scr.Hilite != t)&&(Scr.Hilite != NULL))
      SetBorder(Scr.Hilite,False,False,True,None);

#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
    /* are we using textured borders? */
    if ((GetDecor(t,BorderStyle.active.style)
	 & ButtonFaceTypeMask) == TiledPixmapButton)
	TexturePixmap = GetDecor(t,BorderStyle.active.u.p->picture);
#endif

    /* set the keyboard focus */
    if((Mapped)&&(t->flags&MAPPED)&&(Scr.Hilite != t))
      w = t->w;
    else if((t->flags&ICONIFIED)&&
            (Scr.Hilite !=t)&&(!(t->flags &SUPPRESSICON)))
      w = t->icon_w;
    Scr.Hilite = t;

    TextColor = GetDecor(t,HiColors.fore);
    BackPixmap= Scr.gray_pixmap;
    BackColor = GetDecor(t,HiColors.back);
    ReliefGC = GetDecor(t,HiReliefGC);
    ShadowGC = GetDecor(t,HiShadowGC);
    BorderColor = GetDecor(t,HiRelief.back);
  }
  else
  {
    /* don't re-draw just for kicks */
    if((!force)&&(Scr.Hilite != t))
      return;

    if(Scr.Hilite == t)
    {
      Scr.Hilite = NULL;
      NewColor = True;
    }

#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
    if ((GetDecor(t,BorderStyle.inactive.style)
	 & ButtonFaceTypeMask) == TiledPixmapButton)
	TexturePixmap = GetDecor(t,BorderStyle.inactive.u.p->picture);
#endif

    TextColor =t->TextPixel;
    BackPixmap = Scr.light_gray_pixmap;
    if(t->flags & STICKY)
      BackPixmap = Scr.sticky_gray_pixmap;
    BackColor = t->BackPixel;
    Globalgcv.foreground = t->ReliefPixel;
    Globalgcm = GCForeground;
    XChangeGC(dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv);
    ReliefGC = Scr.ScratchGC1;

    Globalgcv.foreground = t->ShadowPixel;
    XChangeGC(dpy,Scr.ScratchGC2,Globalgcm,&Globalgcv);
    ShadowGC = Scr.ScratchGC2;
    BorderColor = t->ShadowPixel;
  }

  if(t->flags & ICONIFIED)
  {
    DrawIconWindow(t);
    return;
  }

#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
  valuemask =
      notex_valuemask =
      CWBorderPixel;
  attributes.border_pixel =
      notex_attributes.border_pixel =
      BorderColor;
#else
  valuemask = CWBorderPixel;
  attributes.border_pixel = BorderColor;
#endif

#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
  if (TexturePixmap)
  {
      attributes.background_pixmap = TexturePixmap;
      valuemask |= CWBackPixmap;
      if (Scr.d_depth < 2) {
	  notex_attributes.background_pixmap = BackPixmap;
	  notex_valuemask |= CWBackPixmap;
      } else {
	  notex_attributes.background_pixel = BackColor;
	  notex_valuemask |= CWBackPixel;
      }
  }
  else
#endif
  if (Scr.d_depth < 2)
  {
      attributes.background_pixmap = BackPixmap;
      valuemask |= CWBackPixmap;
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
      notex_attributes.background_pixmap = BackPixmap;
      notex_valuemask |= CWBackPixmap;
#endif
  }
  else
  {
      attributes.background_pixel = BackColor;
      valuemask |= CWBackPixel;
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
      notex_attributes.background_pixel = BackColor;
      notex_valuemask |= CWBackPixel;
#endif
  }

  if(t->flags & (TITLE|BORDER))
  {
    XSetWindowBorder(dpy,t->Parent,BorderColor);
    XSetWindowBorder(dpy,t->frame,BorderColor);
  }
  if(t->flags & TITLE)
  {
    ChangeWindowColor(t->title_w,valuemask);
    for(i=0;i<Scr.nr_left_buttons;++i)
    {
	if(t->left_w[i] != None)
	{
	    enum ButtonState bs = GetButtonState(t->left_w[i]);
	    ButtonFace *bf = &GetDecor(t,left_buttons[i].state[bs]);
#if !(defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE))
	    ChangeWindowColor(t->left_w[i],valuemask);
#endif
	    if(flush_expose(t->left_w[i])||(expose_win == t->left_w[i])||
	       (expose_win == None)
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
	       || NewColor
#endif
		)
	    {
		int inverted = PressedW == t->left_w[i];
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
		if (bf->style & UseBorderStyle)
		    XChangeWindowAttributes(dpy, t->left_w[i],
					    valuemask, &attributes);
		else
		    XChangeWindowAttributes(dpy, t->left_w[i],
					    notex_valuemask, &notex_attributes);
		XClearWindow(dpy, t->left_w[i]);
#endif
#ifdef EXTENDED_TITLESTYLE
		if (bf->style & UseTitleStyle) {
		    ButtonFace *tsbf = &GetDecor(t,titlebar.state[bs]);
#ifdef MULTISTYLE
		    for (; tsbf; tsbf = tsbf->next)
#endif
			DrawButton(t, t->left_w[i],
				   t->title_height, t->title_height,
				   tsbf, ReliefGC, ShadowGC,
				   inverted, GetDecor(t,left_buttons[i].flags));
		}
#endif /* EXTENDED_TITLESTYLE */
#ifdef MULTISTYLE
		for (; bf; bf = bf->next)
#endif
		    DrawButton(t, t->left_w[i],
			       t->title_height, t->title_height,
			       bf, ReliefGC, ShadowGC,
			       inverted, GetDecor(t,left_buttons[i].flags));

		if (!(GetDecor(t,left_buttons[i].state[bs].style) & FlatButton)) {
		    if (GetDecor(t,left_buttons[i].state[bs].style) & SunkButton)
			RelieveWindow(t,t->left_w[i],0,0,
				      t->title_height, t->title_height,
				      (inverted ? ReliefGC : ShadowGC),
				      (inverted ? ShadowGC : ReliefGC),
				      BOTTOM_HILITE);
		    else
			RelieveWindow(t,t->left_w[i],0,0,
				      t->title_height, t->title_height,
				      (inverted ? ShadowGC : ReliefGC),
				      (inverted ? ReliefGC : ShadowGC),
				      BOTTOM_HILITE);
		}
	    }
	}
    }
    for(i=0;i<Scr.nr_right_buttons;++i)
    {
	if(t->right_w[i] != None)
	{
	    enum ButtonState bs = GetButtonState(t->right_w[i]);
	    ButtonFace *bf = &GetDecor(t,right_buttons[i].state[bs]);
#if !(defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE))
	    ChangeWindowColor(t->right_w[i],valuemask);
#endif
	    if(flush_expose(t->right_w[i])||(expose_win==t->right_w[i])||
	       (expose_win == None)
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
	       || NewColor
#endif
		)
	    {
		int inverted = PressedW == t->right_w[i];
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
		if (bf->style & UseBorderStyle)
		    XChangeWindowAttributes(dpy, t->right_w[i],
					    valuemask, &attributes);
		else
		    XChangeWindowAttributes(dpy, t->right_w[i],
					    notex_valuemask, &notex_attributes);
		XClearWindow(dpy, t->right_w[i]);
#endif
#ifdef EXTENDED_TITLESTYLE
		if (bf->style & UseTitleStyle) {
		    ButtonFace *tsbf = &GetDecor(t,titlebar.state[bs]);
#ifdef MULTISTYLE
		    for (; tsbf; tsbf = tsbf->next)
#endif
			DrawButton(t, t->right_w[i],
				   t->title_height, t->title_height,
				   tsbf, ReliefGC, ShadowGC,
				   inverted, GetDecor(t,right_buttons[i].flags));
		}
#endif /* EXTENDED_TITLESTYLE */
#ifdef MULTISTYLE
		for (; bf; bf = bf->next)
#endif
		    DrawButton(t, t->right_w[i],
			       t->title_height, t->title_height,
			       bf, ReliefGC, ShadowGC,
			       inverted, GetDecor(t,right_buttons[i].flags));

		if (!(GetDecor(t,right_buttons[i].state[bs].style) & FlatButton)) {
		    if (GetDecor(t,right_buttons[i].state[bs].style) & SunkButton)
			RelieveWindow(t,t->right_w[i],0,0,
				      t->title_height, t->title_height,
				      (inverted ? ReliefGC : ShadowGC),
				      (inverted ? ShadowGC : ReliefGC),
				      BOTTOM_HILITE);
		    else
			RelieveWindow(t,t->right_w[i],0,0,
				      t->title_height, t->title_height,
				      (inverted ? ShadowGC : ReliefGC),
				      (inverted ? ReliefGC : ShadowGC),
				      BOTTOM_HILITE);
		}
	    }
	}
    }
    SetTitleBar(t,onoroff, False);

  }

  if(t->flags & BORDER)
  {
    /* draw relief lines */
    y= t->frame_height - 2*t->corner_width;
    x = t->frame_width-  2*t->corner_width +t->bw;

    for(i=0;i<4;i++)
    {
      int vertical = i % 2;
#ifdef BORDERSTYLE
      int flags = onoroff
	  ? GetDecor(t,BorderStyle.active.style)
	  : GetDecor(t,BorderStyle.inactive.style);
#endif /* BORDERSTYLE */

      ChangeWindowColor(t->sides[i],valuemask);
      if((flush_expose (t->sides[i]))||(expose_win == t->sides[i])||
         (expose_win == None))
      {
        GC sgc,rgc;

        sgc=ShadowGC;
        rgc=ReliefGC;
        if(!(t->flags & MWMButtons)&&(PressedW == t->sides[i]))
        {
          sgc = ReliefGC;
          rgc = ShadowGC;
        }
        /* index    side
         * 0        TOP
         * 1        RIGHT
         * 2        BOTTOM
         * 3        LEFT
         */

#ifdef BORDERSTYLE
        if (flags&HiddenHandles) {
	    if (flags&NoInset)
		RelieveWindowHH(t,t->sides[i],0,0,
				((vertical)?t->boundary_width:x),
				((vertical)?y:t->boundary_width),
				rgc, sgc, vertical
				? (i == 3 ? LEFT_HILITE : RIGHT_HILITE)
				: (i ? BOTTOM_HILITE : TOP_HILITE),
				(0x0001<<i)
		    );
	    else
		RelieveWindowHH(t,t->sides[i],0,0,
				((vertical)?t->boundary_width:x),
				((vertical)?y:t->boundary_width),
				rgc, sgc, vertical
				? (LEFT_HILITE|RIGHT_HILITE)
				: (TOP_HILITE|BOTTOM_HILITE),
				(0x0001<<i)
		    );
        } else
#endif /* BORDERSTYLE */
	    RelieveWindow(t,t->sides[i],0,0,
			  ((i%2)?t->boundary_width:x),
			  ((i%2)?y:t->boundary_width),
			  rgc, sgc, (0x0001<<i));
      }
      ChangeWindowColor(t->corners[i],valuemask);
      if((flush_expose(t->corners[i]))||(expose_win==t->corners[i])||
         (expose_win == None))
      {
        GC rgc,sgc;

        rgc = ReliefGC;
        sgc = ShadowGC;
        if(!(t->flags & MWMButtons)&&(PressedW == t->corners[i]))
        {
          sgc = ReliefGC;
          rgc = ShadowGC;
        }
#ifdef BORDERSTYLE
        if (flags&HiddenHandles) {
	    RelieveWindowHH(t,t->corners[i],0,0,t->corner_width,
			    ((i/2)?t->corner_width+t->bw:t->corner_width),
			    rgc,sgc, corners[i], corners[i]);

	    if (!(flags&NoInset)) {
		if (t->boundary_width > 1)
		    RelieveParts(t,i|HH_HILITE,
				 ((i/2)?rgc:sgc),(vertical?rgc:sgc));
		else
		    RelieveParts(t,i|HH_HILITE,
				 ((i/2)?sgc:sgc),(vertical?sgc:sgc));
	    }
         } else {
#endif /* ! BORDERSTYLE */
	     RelieveWindow(t,t->corners[i],0,0,t->corner_width,
			   ((i/2)?t->corner_width+t->bw:t->corner_width),
			   rgc,sgc, corners[i]);

	     if(t->boundary_width > 1)
		 RelieveParts(t,i,((i/2)?rgc:sgc),(vertical?rgc:sgc));
	     else
		 RelieveParts(t,i,((i/2)?sgc:sgc),(vertical?sgc:sgc));
#ifdef BORDERSTYLE
         }
#endif
      }
    }
  }
  else      /* no decorative border */
  {
    /* for mono - put a black border on
     * for color, make it the color of the decoration background */
    if(t->boundary_width < 2)
    {
      flush_expose (t->frame);
      if(Scr.d_depth <2)
      {
        XSetWindowBorder(dpy,t->frame,TextColor);
        XSetWindowBorder(dpy,t->Parent,TextColor);
        XSetWindowBackgroundPixmap(dpy,t->frame,BackPixmap);
        XClearWindow(dpy,t->frame);
        XSetWindowBackgroundPixmap(dpy,t->Parent,BackPixmap);
        XClearWindow(dpy,t->Parent);
      }
      else
      {
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
	XSetWindowBackgroundPixmap(dpy,t->frame,TexturePixmap);
#endif
        XSetWindowBorder(dpy,t->frame,BorderColor);
        XClearWindow(dpy,t->frame);
        XSetWindowBackground(dpy,t->Parent,BorderColor);
        XSetWindowBorder(dpy,t->Parent,BorderColor);
        XClearWindow(dpy,t->Parent);
        XSetWindowBorder(dpy,t->w,BorderColor);
      }
    }
    else
    {
      GC rgc,sgc;

      XSetWindowBorder(dpy,t->Parent,BorderColor);
      XSetWindowBorder(dpy,t->frame,BorderColor);

      rgc=ReliefGC;
      sgc=ShadowGC;
      if(!(t->flags & MWMButtons)&&(PressedW == t->frame))
      {
        sgc=ReliefGC;
        rgc=ShadowGC;
      }
      ChangeWindowColor(t->frame, valuemask);
      if((flush_expose(t->frame))||(expose_win == t->frame)||
         (expose_win == None))
      {
        if(t->boundary_width > 2)
        {
          RelieveWindow(t,t->frame,t->boundary_width-1 - t->bw,
                        t->boundary_width-1-t->bw,
                        t->frame_width-
                        (t->boundary_width<<1)+2+3*t->bw,
                        t->frame_height-
                        (t->boundary_width<<1)+2+3*t->bw,
                        sgc,rgc,
                        TOP_HILITE|LEFT_HILITE|RIGHT_HILITE|
                        BOTTOM_HILITE);
          RelieveWindow(t,t->frame,0,0,t->frame_width+t->bw,
                        t->frame_height+t->bw,rgc,sgc,
                        TOP_HILITE|LEFT_HILITE|RIGHT_HILITE|
                        BOTTOM_HILITE);
        }
        else
        {
          RelieveWindow(t,t->frame,0,0,t->frame_width+t->bw,
                        t->frame_height+t->bw,rgc,rgc,
                        TOP_HILITE|LEFT_HILITE|RIGHT_HILITE|
                        BOTTOM_HILITE);
        }
      }
      else
      {
        XSetWindowBackground(dpy,t->Parent,BorderColor);
      }
    }
  }
  /* Sync to make the border-color change look fast! */
  XSync(dpy,0);

}

/****************************************************************************
 *
 *  Redraws buttons (veliaa@rpi.edu)
 *
 ****************************************************************************/
void DrawButton(FvwmWindow *t, Window win, int w, int h,
		ButtonFace *bf, GC ReliefGC, GC ShadowGC,
		Boolean inverted, int stateflags)
{
    register int type = bf->style & ButtonFaceTypeMask;
#ifdef PIXMAP_BUTTONS
    FvwmPicture *p;
    int border = 0;
    int width, height, x, y;
#endif

    switch (type)
    {
    case SimpleButton:
	break;

    case SolidButton:
	XSetWindowBackground(dpy, win, bf->u.back);
	flush_expose(win);
	XClearWindow(dpy,win);
	break;

#ifdef VECTOR_BUTTONS
    case VectorButton:
	if((t->flags & MWMButtons)
           && (stateflags & MWMDecorMaximize)
	   && (t->flags & MAXIMIZED))
	    DrawLinePattern(win,
			    ShadowGC, ReliefGC,
			    &bf->vector,
			    w, h);
	else
	    DrawLinePattern(win,
			    ReliefGC, ShadowGC,
			    &bf->vector,
			    w, h);
	break;
#endif /* VECTOR_BUTTONS */

#ifdef PIXMAP_BUTTONS
#ifdef MINI_ICONS
    case MiniIconButton:
    case PixmapButton:
	if (type == PixmapButton)
	    p = bf->u.p;
	else {
	    if (!t->mini_icon)
		break;
	    p = t->mini_icon;
	}
#else
    case PixmapButton:
	p = bf->u.p;
#endif /* MINI_ICONS */
	if (bf->style & FlatButton)
	    border = 0;
	else
	    border = t->flags & MWMBorders ? 1 : 2;
	width = w - border * 2; height = h - border * 2;

	x = border;
	if (bf->style&HOffCenter) {
	    if (bf->style&HRight)
		x += (int)(width - p->width);
	} else
	    x += (int)(width - p->width) / 2;

	y = border;
	if (bf->style&VOffCenter) {
	    if (bf->style&VBottom)
		y += (int)(height - p->height);
	} else
	    y += (int)(height - p->height) / 2;

	if (x < border) x = border;
	if (y < border) y = border;
	if (width > p->width) width = p->width;
	if (height > p->height) height = p->height;
	if (width > w - x - border) width = w - x - border;
	if (height > h - y - border) height = h - y - border;

	XSetClipMask(dpy, Scr.TransMaskGC, p->mask);
	XSetClipOrigin(dpy, Scr.TransMaskGC, x, y);
	XCopyArea(dpy, p->picture, win, Scr.TransMaskGC,
		  0, 0, width, height, x, y);
	break;

   case TiledPixmapButton:
	XSetWindowBackgroundPixmap(dpy, win, bf->u.p->picture);
	flush_expose(win);
	XClearWindow(dpy,win);
	break;
#endif /* PIXMAP_BUTTONS */

#ifdef GRADIENT_BUTTONS
    case HGradButton:
    case VGradButton:
    {
	XRectangle bounds;
	bounds.x = bounds.y = 0;
	bounds.width = w;
	bounds.height = h;
	flush_expose(win);

#ifdef PIXMAP_BUTTONS
	XSetClipMask(dpy, Scr.TransMaskGC, None);
#endif
	if (type == HGradButton) {
	    register int i = 0, dw = bounds.width
		/ bf->u.grad.npixels + 1;
	    while (i < bf->u.grad.npixels)
	    {
		unsigned short x = i * bounds.width / bf->u.grad.npixels;
		XSetForeground(dpy, Scr.TransMaskGC, bf->u.grad.pixels[ i++ ]);
		XFillRectangle(dpy, win, Scr.TransMaskGC,
			       bounds.x + x, bounds.y,
			       dw, bounds.height);
	    }
	} else {
	    register int i = 0, dh = bounds.height
		/ bf->u.grad.npixels + 1;
	    while (i < bf->u.grad.npixels)
	    {
		unsigned short y = i * bounds.height / bf->u.grad.npixels;
		XSetForeground(dpy, Scr.TransMaskGC, bf->u.grad.pixels[ i++ ]);
		XFillRectangle(dpy, win, Scr.TransMaskGC,
			       bounds.x, bounds.y + y,
			       bounds.width, dh);
	    }
	}
    }
    break;
#endif /* GRADIENT_BUTTONS */

    default:
	fvwm_msg(ERR,"DrawButton","unknown button type");
	break;
    }
}

/****************************************************************************
 *
 *  Redraws just the title bar
 *
 ****************************************************************************/
void SetTitleBar (FvwmWindow *t,Bool onoroff, Bool NewTitle)
{
  int hor_off, w, i;
  enum ButtonState title_state;
  ButtonFaceStyle tb_style;
  int tb_flags;
  GC ReliefGC, ShadowGC, tGC;
  Pixel Forecolor, BackColor;

  if(!t)
    return;
  if(!(t->flags & TITLE))
    return;

  if (onoroff)
  {
    Forecolor = GetDecor(t,HiColors.fore);
    BackColor = GetDecor(t,HiColors.back);
    ReliefGC = GetDecor(t,HiReliefGC);
    ShadowGC = GetDecor(t,HiShadowGC);
  }
  else
  {
    Forecolor =t->TextPixel;
    BackColor = t->BackPixel;
    Globalgcv.foreground = t->ReliefPixel;
    Globalgcm = GCForeground;
    XChangeGC(dpy,Scr.ScratchGC1,Globalgcm,&Globalgcv);
    ReliefGC = Scr.ScratchGC1;

    Globalgcv.foreground = t->ShadowPixel;
    XChangeGC(dpy,Scr.ScratchGC2,Globalgcm,&Globalgcv);
    ShadowGC = Scr.ScratchGC2;
  }
  if(PressedW==t->title_w)
  {
    tGC = ShadowGC;
    ShadowGC = ReliefGC;
    ReliefGC = tGC;
  }
  flush_expose(t->title_w);

  if(t->name != (char *)NULL)
  {
    w=XTextWidth(GetDecor(t,WindowFont.font),t->name,strlen(t->name));
    if(w > t->title_width-12)
      w = t->title_width-4;
    if(w < 0)
      w = 0;
  }
  else
    w = 0;

  title_state = GetButtonState(t->title_w);
  tb_style = GetDecor(t,titlebar.state[title_state].style);
  tb_flags = GetDecor(t,titlebar.flags);
  if (tb_flags & HOffCenter) {
      if (tb_flags & HRight)
	  hor_off = t->title_width - w - 10;
      else
	  hor_off = 10;
  } else
      hor_off = (t->title_width - w) / 2;

  NewFontAndColor(GetDecor(t,WindowFont.font->fid),Forecolor, BackColor);

  /* the next bit tries to minimize redraw based upon compilation options (veliaa@rpi.edu) */
#ifdef EXTENDED_TITLESTYLE
#if defined(PIXMAP_BUTTONS) && defined(BORDERSTYLE)
  /* we need to check for UseBorderStyle for the titlebar */
  {
      ButtonFace *bf = onoroff
	  ? &GetDecor(t,BorderStyle.active)
	  : &GetDecor(t,BorderStyle.inactive);

      if ((tb_style & UseBorderStyle)
	  && ((bf->style & ButtonFaceTypeMask) == TiledPixmapButton))
	  XSetWindowBackgroundPixmap(dpy,t->title_w,bf->u.p->picture);
  }
#endif /* PIXMAP_BUTTONS && BORDERSTYLE */
  XClearWindow(dpy,t->title_w);
#else /* ! EXTENDED_TITLESTYLE */
  /* if no extended titlestyle, only clear when necessary */
  if (NewTitle)
      XClearWindow(dpy,t->title_w);
#endif /* EXTENDED_TITLESTYLE */

  /* for mono, we clear an area in the title bar where the window
   * title goes, so that its more legible. For color, no need */
  if(Scr.d_depth<2)
  {
    RelieveWindow(t,t->title_w,0,0,hor_off-2,t->title_height,
                  ReliefGC, ShadowGC, BOTTOM_HILITE);
    RelieveWindow(t,t->title_w,hor_off+w+2,0,
                  t->title_width - w - hor_off-2,t->title_height,
                  ReliefGC, ShadowGC, BOTTOM_HILITE);
    XFillRectangle(dpy,t->title_w,
                   (PressedW==t->title_w?ShadowGC:ReliefGC),
                   hor_off - 2, 0, w+4,t->title_height);

    XDrawLine(dpy,t->title_w,ShadowGC,hor_off+w+1,0,hor_off+w+1,
              t->title_height);
    if(t->name != (char *)NULL)
      XDrawString (dpy, t->title_w,Scr.ScratchGC3,hor_off,
                   GetDecor(t,WindowFont.y)+1,
                   t->name, strlen(t->name));
  }
  else
  {
#ifdef EXTENDED_TITLESTYLE
      ButtonFace *bf = &GetDecor(t,titlebar.state[title_state]);
      /* draw compound titlebar (veliaa@rpi.edu) */
      if (PressedW == t->title_w) {
#ifdef MULTISTYLE
	  for (; bf; bf = bf->next)
#endif
	      DrawButton(t, t->title_w, t->title_width, t->title_height,
			 bf, ShadowGC, ReliefGC, True, 0);
      } else {
#ifdef MULTISTYLE
	  for (; bf; bf = bf->next)
#endif
	      DrawButton(t, t->title_w, t->title_width, t->title_height,
			 bf, ReliefGC, ShadowGC, False, 0);
      }
#endif /* EXTENDED_TITLESTYLE */

      if (!(tb_style & FlatButton)) {
	  if (tb_style & SunkButton)
	      RelieveWindow(t,t->title_w,0,0,t->title_width,t->title_height,
			    ShadowGC, ReliefGC, BOTTOM_HILITE);
	  else
	      RelieveWindow(t,t->title_w,0,0,t->title_width,t->title_height,
			    ReliefGC, ShadowGC, BOTTOM_HILITE);
      }

      if(t->name != (char *)NULL)
        XDrawString (dpy, t->title_w,Scr.ScratchGC3,hor_off,
                     GetDecor(t,WindowFont.y)+1,
                     t->name, strlen(t->name));
  }
  /* now, draw lines in title bar if it's a sticky window */
  if(t->flags & STICKY || Scr.StipledTitles)
  {
    for(i=0 ;i< t->title_height/2-3;i+=4)
    {
      XDrawLine(dpy,t->title_w,ShadowGC,4,t->title_height/2 - i-1,
                hor_off-6,t->title_height/2-i-1);
      XDrawLine(dpy,t->title_w,ShadowGC,6+hor_off+w,t->title_height/2 -i-1,
                t->title_width-5,t->title_height/2- i-1);
      XDrawLine(dpy,t->title_w,ReliefGC,4,t->title_height/2 - i,
                hor_off-6,t->title_height/2 - i);
      XDrawLine(dpy,t->title_w,ReliefGC,6+hor_off+w,t->title_height/2-i,
                t->title_width-5,t->title_height/2 - i);

      XDrawLine(dpy,t->title_w,ShadowGC,4,t->title_height/2 + i-1,
                hor_off-6,t->title_height/2+i-1);
      XDrawLine(dpy,t->title_w,ShadowGC,6+hor_off+w,t->title_height/2+i-1,
                t->title_width-5,t->title_height/2 + i-1);
      XDrawLine(dpy,t->title_w,ReliefGC,4,t->title_height/2 + i,
                hor_off-6,t->title_height/2 + i);
      XDrawLine(dpy,t->title_w,ReliefGC,6+hor_off+w,t->title_height/2+i,
                t->title_width-5,t->title_height/2 + i);
    }
  }


  XFlush(dpy);
}




/****************************************************************************
 *
 *  Draws the relief pattern around a window
 *
 ****************************************************************************/
void RelieveWindow(FvwmWindow *t,Window win, int x,int y,int w,int h,
		   GC ReliefGC, GC ShadowGC, int hilite)
{
  XSegment seg[4];
  int i;
  int edge;

  edge = 0;
  if((win == t->sides[0])||(win == t->sides[1])||
     (win == t->sides[2])||(win == t->sides[3]))
    edge = -1;
  if(win == t->corners[0])
    edge = 1;
  if(win == t->corners[1])
    edge = 2;
  if(win == t->corners[2])
    edge = 3;
  if(win == t->corners[3])
    edge = 4;

  i=0;
  seg[i].x1 = x;        seg[i].y1   = y;
  seg[i].x2 = w+x-1;    seg[i++].y2 = y;

  seg[i].x1 = x;        seg[i].y1   = y;
  seg[i].x2 = x;        seg[i++].y2 = h+y-1;

  if(((t->boundary_width > 2)||(edge == 0))&&
     ((t->boundary_width > 3)||(edge < 1))&&
     (!(t->flags & MWMBorders)||
      (((edge==0)||(t->boundary_width > 3))&&(hilite & TOP_HILITE))))
  {
    seg[i].x1 = x+1;      seg[i].y1   = y+1;
    seg[i].x2 = x+w-2;    seg[i++].y2 = y+1;
  }
  if(((t->boundary_width > 2)||(edge == 0))&&
     ((t->boundary_width > 3)||(edge < 1))&&
     (!(t->flags & MWMBorders)||
      (((edge==0)||(t->boundary_width > 3))&&(hilite & LEFT_HILITE))))
  {
    seg[i].x1 = x+1;      seg[i].y1   = y+1;
    seg[i].x2 = x+1;      seg[i++].y2 = y+h-2;
  }
  XDrawSegments(dpy, win, ReliefGC, seg, i);

  i=0;
  seg[i].x1 = x;        seg[i].y1   = y+h-1;
  seg[i].x2 = w+x-1;    seg[i++].y2 = y+h-1;

  if(((t->boundary_width > 2)||(edge == 0))&&
     (!(t->flags & MWMBorders)||
      (((edge==0)||(t->boundary_width > 3))&&(hilite & BOTTOM_HILITE))))
  {
    seg[i].x1 = x+1;      seg[i].y1   = y+h-2;
    seg[i].x2 = x+w-2;    seg[i++].y2 = y+h-2;
  }

  seg[i].x1 = x+w-1;    seg[i].y1   = y;
  seg[i].x2 = x+w-1;    seg[i++].y2 = y+h-1;

  if(((t->boundary_width > 2)||(edge == 0))&&
     (!(t->flags & MWMBorders)||
      (((edge==0)||(t->boundary_width > 3))&&(hilite & RIGHT_HILITE))))
  {
    seg[i].x1 = x+w-2;    seg[i].y1   = y+1;
    seg[i].x2 = x+w-2;    seg[i++].y2 = y+h-2;
  }
  XDrawSegments(dpy, win, ShadowGC, seg, i);
}

#ifdef BORDERSTYLE
/****************************************************************************
 *
 *  Draws the relief pattern around a window for HiddenHandle borders
 *
 *  (veliaa@rpi.edu)
 *
 ****************************************************************************/
void RelieveWindowHH(FvwmWindow *t,Window win, int x,int y,int w,int h,
		     GC ReliefGC, GC ShadowGC, int draw, int hilite)
{
    XSegment seg[4];
    int i = 0;
    int edge = 0, a = 0, b = 0;

    if(win == t->sides[0]) {
	edge = 5;
	b = 1;
    }
    else if (win == t->sides[1]) {
	a = 1;
	edge = 6;
    }
    else if (win == t->sides[2]) {
	edge = 7;
	b = 1;
    }
    else if (win == t->sides[3]) {
	edge = 8;
	a = 1;
    } else if (win == t->corners[0])
	edge = 1;
    else if (win == t->corners[1])
	edge = 2;
    else if (win == t->corners[2])
	edge = 3;
    else if (win == t->corners[3])
	edge = 4;

    if (draw & TOP_HILITE) {
	seg[i].x1 = x;        seg[i].y1   = y;
	seg[i].x2 = w+x-1;    seg[i++].y2 = y;

	if(((t->boundary_width > 2)||(edge == 0))&&
	   ((t->boundary_width > 3)||(edge < 1))&&
	   (!(t->flags & MWMBorders)||
	    (((edge==0)||(t->boundary_width > 3))&&(hilite & TOP_HILITE))))
	{
	    seg[i].x1 = x+((edge == 2)|| b ? 0 : 1);  seg[i].y1 = y+1;
	    seg[i].x2 = x+w-1-((edge == 1)|| b ? 0 : 1);    seg[i++].y2 = y+1;
	}
    }

    if (draw & LEFT_HILITE) {
	seg[i].x1 = x;        seg[i].y1   = y;
	seg[i].x2 = x;        seg[i++].y2 = h+y-1;

	if(((t->boundary_width > 2)||(edge == 0))&&
	   ((t->boundary_width > 3)||(edge < 1))&&
	   (!(t->flags & MWMBorders)||
	    (((edge==0)||(t->boundary_width > 3))&&(hilite & LEFT_HILITE))))
	{
	    seg[i].x1 = x+1;      seg[i].y1   = y+((edge == 3)|| a ? 0 : 1);
	    seg[i].x2 = x+1;      seg[i++].y2 = y+h-1-((edge == 1)|| a ? 0 : 1);
	}
    }
    XDrawSegments(dpy, win, ReliefGC, seg, i);

    i=0;

    if (draw & BOTTOM_HILITE) {
	seg[i].x1 = x;        seg[i].y1   = y+h-1;
	seg[i].x2 = w+x-1;    seg[i++].y2 = y+h-1;

	if(((t->boundary_width > 2)||(edge == 0))&&
	   (!(t->flags & MWMBorders)||
	    (((edge==0)||(t->boundary_width > 3))&&(hilite & BOTTOM_HILITE))))
	{
	    seg[i].x1 = x+(b ||(edge == 4) ? 0 : 1);      seg[i].y1   = y+h-2;
	    seg[i].x2 = x+w-((edge == 3) ? 0 : 1);    seg[i++].y2 = y+h-2;
	}
    }

    if (draw & RIGHT_HILITE) {
	seg[i].x1 = x+w-1;    seg[i].y1   = y;
	seg[i].x2 = x+w-1;    seg[i++].y2 = y+h-1;

	if(((t->boundary_width > 2)||(edge == 0))&&
	   (!(t->flags & MWMBorders)||
	    (((edge==0)||(t->boundary_width > 3))&&(hilite & RIGHT_HILITE))))
	{
	    seg[i].x1 = x+w-2;    seg[i].y1   = y+(a ||(edge == 4) ? 0 : 1);
	    seg[i].x2 = x+w-2;    seg[i++].y2 = y+h-1-((edge == 2)|| a ? 0 : 1);
	}
    }
    XDrawSegments(dpy, win, ShadowGC, seg, i);
}
#endif /* BORDERSTYLE */

void RelieveParts(FvwmWindow *t,int i,GC hor, GC vert)
{
  XSegment seg[2];
  int n = 0, hh = i & HH_HILITE;
  i &= FULL_HILITE;

  if((t->flags & MWMBorders)||(t->boundary_width < 3))
  {
    switch(i)
    {
      case 0:
        seg[0].x1 = t->boundary_width-1;
        seg[0].x2 = t->corner_width;
        seg[0].y1 = t->boundary_width-1;
        seg[0].y2 = t->boundary_width-1;
        n=1;
        break;
      case 1:
        seg[0].x1 = 0;
        seg[0].x2 = t->corner_width - t->boundary_width /* -1*/ ;
        seg[0].y1 = t->boundary_width-1;
        seg[0].y2 = t->boundary_width-1;
        n=1;
        break;
      case 2:
        seg[0].x1 = t->boundary_width-1;
        seg[0].x2 = t->corner_width - (hh ? 1 : 2);
        seg[0].y1 = t->corner_width - t->boundary_width+t->bw;
        seg[0].y2 = t->corner_width - t->boundary_width+t->bw;
        n=1;
        break;
      case 3:
        seg[0].x1 = 0;
        seg[0].x2 = t->corner_width - t->boundary_width;
        seg[0].y1 = t->corner_width - t->boundary_width+t->bw;
        seg[0].y2 = t->corner_width - t->boundary_width+t->bw;
        n=1;
        break;
    }
    XDrawSegments(dpy, t->corners[i], hor, seg, n);
    switch(i)
    {
      case 0:
        seg[0].y1 = t->boundary_width-1;
        seg[0].y2 = t->corner_width;
        seg[0].x1 = t->boundary_width-1;
        seg[0].x2 = t->boundary_width-1;
        n=1;
        break;
      case 1:
        seg[0].y1 = t->boundary_width -1;
        seg[0].y2 = t->corner_width - (hh ? 0 : 2);
        seg[0].x1 = t->corner_width - t->boundary_width;
        seg[0].x2 = t->corner_width - t->boundary_width;
        n=1;
        break;
      case 2:
        seg[0].y1 = 0;
        seg[0].y2 = t->corner_width - t->boundary_width;
        seg[0].x1 = t->boundary_width-1;
        seg[0].x2 = t->boundary_width-1;
        n=1;
        break;
      case 3:
        seg[0].y1 = 0;
        seg[0].y2 = t->corner_width - t->boundary_width + t->bw;
        seg[0].x1 = t->corner_width - t->boundary_width;
        seg[0].x2 = t->corner_width - t->boundary_width;
        n=1;
        break;
    }
    XDrawSegments(dpy, t->corners[i], vert, seg, 1);
  }
  else
  {
    switch(i)
    {
      case 0:
        seg[0].x1 = t->boundary_width-2;
        seg[0].x2 = t->corner_width;
        seg[0].y1 = t->boundary_width-2;
        seg[0].y2 = t->boundary_width-2;

        seg[1].x1 = t->boundary_width-2;
        seg[1].x2 = t->corner_width;
        seg[1].y1 = t->boundary_width-1;
        seg[1].y2 = t->boundary_width-1;
        n=2;
        break;
      case 1:
        seg[0].x1 = (hh ? 0 : 1);
        seg[0].x2 = t->corner_width - t->boundary_width;
        seg[0].y1 = t->boundary_width-2;
        seg[0].y2 = t->boundary_width-2;

        seg[1].x1 = 0;
        seg[1].x2 = t->corner_width - t->boundary_width-1;
        seg[1].y1 = t->boundary_width-1;
        seg[1].y2 = t->boundary_width-1;
        n=2;
        break;
      case 2:
        seg[0].x1 = t->boundary_width-1;
        seg[0].x2 = t->corner_width - (hh ? 1 : 2);
        seg[0].y1 = t->corner_width - t->boundary_width+1;
        seg[0].y2 = t->corner_width - t->boundary_width+1;
        n=1;
        if(t->boundary_width > 3)
        {
          seg[1].x1 = t->boundary_width-2;
          seg[1].x2 = t->corner_width - (hh ? 1 : 3);
          seg[1].y1 = t->corner_width - t->boundary_width + 2;
          seg[1].y2 = t->corner_width - t->boundary_width + 2;
          n=2;
        }
        break;
      case 3:
        seg[0].x1 = 0;
        seg[0].x2 = t->corner_width - t->boundary_width;
        seg[0].y1 = t->corner_width - t->boundary_width+1;
        seg[0].y2 = t->corner_width - t->boundary_width+1;
        n=1;
        if(t->boundary_width > 3)
        {
          seg[0].x2 = t->corner_width - t->boundary_width + 1;

          seg[1].x1 = 0;
          seg[1].x2 = t->corner_width - t->boundary_width + 1;
          seg[1].y1 = t->corner_width - t->boundary_width + 2;
          seg[1].y2 = t->corner_width - t->boundary_width + 2;
          n=2;
        }
        break;
    }
    XDrawSegments(dpy, t->corners[i], hor, seg, n);
    switch(i)
    {
      case 0:
        seg[0].y1 = t->boundary_width-2;
        seg[0].y2 = t->corner_width;
        seg[0].x1 = t->boundary_width-2;
        seg[0].x2 = t->boundary_width-2;

        seg[1].y1 = t->boundary_width-2;
        seg[1].y2 = t->corner_width;
        seg[1].x1 = t->boundary_width-1;
        seg[1].x2 = t->boundary_width-1;
        n=2;
        break;
      case 1:
        seg[0].y1 = t->boundary_width-1;
        seg[0].y2 = t->corner_width - (hh ? 1 : 2);
        seg[0].x1 = t->corner_width - t->boundary_width;
        seg[0].x2 = t->corner_width - t->boundary_width;
        n=1;
        if(t->boundary_width > 3)
        {
          seg[1].y1 = t->boundary_width-2;
          seg[1].y2 = t->corner_width - (hh ? 1 : 3);
          seg[1].x1 = t->corner_width - t->boundary_width+1;
          seg[1].x2 = t->corner_width - t->boundary_width+1;
          n=2;
        }
        break;
      case 2:
        seg[0].y1 = (hh ? 0 : 1);
        seg[0].y2 = t->corner_width - t->boundary_width+1;
        seg[0].x1 = t->boundary_width-2;
        seg[0].x2 = t->boundary_width-2;
        n=1;

        if(t->boundary_width > 3)
        {
          seg[1].y1 = 0;
          seg[1].y2 = t->corner_width - t->boundary_width;
          seg[1].x1 = t->boundary_width-1;
          seg[1].x2 = t->boundary_width-1;
        }
        break;
      case 3:
        seg[0].y1 = 0;
        seg[0].y2 = t->corner_width - t->boundary_width + 1;
        seg[0].x1 = t->corner_width - t->boundary_width;
        seg[0].x2 = t->corner_width - t->boundary_width;
        n=1;

        if(t->boundary_width > 3)
        {
          seg[0].y2 = t->corner_width - t->boundary_width + 2;
          seg[1].y1 = 0;
          seg[1].y2 = t->corner_width - t->boundary_width + 2;
          seg[1].x1 = t->corner_width - t->boundary_width + 1;
          seg[1].x2 = t->corner_width - t->boundary_width + 1;
          n=2;
        }
        break;
    }
    XDrawSegments(dpy, t->corners[i], vert, seg, n);
  }
}

#ifdef VECTOR_BUTTONS
/****************************************************************************
 *
 *  Draws a little pattern within a window (more complex)
 *
 ****************************************************************************/
void DrawLinePattern(Window win,
                     GC ReliefGC,
                     GC ShadowGC,
		     struct vector_coords *coords,
                     int w, int h)
{
  int i = 1;
  for (; i < coords->num; ++i)
  {
      XDrawLine(dpy,win,
		coords->line_style[i] ? ReliefGC : ShadowGC,
		w * coords->x[i-1]/100,
		h * coords->y[i-1]/100,
		w * coords->x[i]/100,
		h * coords->y[i]/100);
  }
}
#endif /* VECTOR_BUTTONS */


/***********************************************************************
 *
 *  Procedure:
 *      Setupframe - set window sizes, this was called from either
 *              AddWindow, EndResize, or HandleConfigureNotify.
 *
 *  Inputs:
 *      tmp_win - the FvwmWindow 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
 *
 *  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 SetupFrame(FvwmWindow *tmp_win,int x,int y,int w,int h,Bool sendEvent)
{
  XEvent client_event;
  XWindowChanges frame_wc, xwc;
  unsigned long frame_mask, xwcm;
  int cx,cy,i;
  Bool Resized = False, Moved = False;
  int xwidth,ywidth,left,right;
#ifdef WINDOWSHADE
  int shaded = tmp_win->buttons & WSHADE;
#endif

#ifdef FVWM_DEBUG_MSGS
  fvwm_msg(DBG,"SetupFrame",
           "Routine Entered (x == %d, y == %d, w == %d, h == %d)",
           x, y, w, h);
#endif

  /* if windows is not being maximized, save size in case of maximization */
  if (!(tmp_win->flags & MAXIMIZED)
#ifdef WINDOWSHADE
      && !shaded
#endif
      )
  {
    tmp_win->orig_x = x;
    tmp_win->orig_y = y;
    tmp_win->orig_wd = w;
    tmp_win->orig_ht = h;
  }

  if((w != tmp_win->frame_width) || (h != tmp_win->frame_height))
    Resized = True;
  if ((x != tmp_win->frame_x || y != tmp_win->frame_y))
    Moved = True;

  /*
   * 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 (Moved && !Resized)
    sendEvent = True;

  if (Resized)
  {
    left = tmp_win->nr_left_buttons;
    right = tmp_win->nr_right_buttons;

    if (tmp_win->flags & TITLE)
      tmp_win->title_height = GetDecor(tmp_win,TitleHeight) + tmp_win->bw;

    tmp_win->title_width= w-
      (left+right)*tmp_win->title_height
      -2*tmp_win->boundary_width+tmp_win->bw;


    if(tmp_win->title_width < 1)
      tmp_win->title_width = 1;

    if (tmp_win->flags & TITLE)
    {
      xwcm = CWWidth | CWX | CWY | CWHeight;
      tmp_win->title_x = tmp_win->boundary_width+
        (left)*tmp_win->title_height;
      if(tmp_win->title_x >=  w - tmp_win->boundary_width)
        tmp_win->title_x = -10;
      tmp_win->title_y = tmp_win->boundary_width;

      xwc.width = tmp_win->title_width;

      xwc.height = tmp_win->title_height;
      xwc.x = tmp_win->title_x;
      xwc.y = tmp_win->title_y;
      XConfigureWindow(dpy, tmp_win->title_w, xwcm, &xwc);


      xwcm = CWX | CWY | CWHeight | CWWidth;
      xwc.height = tmp_win->title_height;
      xwc.width = tmp_win->title_height;

      xwc.y = tmp_win->boundary_width;
      xwc.x = tmp_win->boundary_width;
      for(i=0;i<Scr.nr_left_buttons;i++)
      {
        if(tmp_win->left_w[i] != None)
        {
          if(xwc.x + tmp_win->title_height < w-tmp_win->boundary_width)
            XConfigureWindow(dpy, tmp_win->left_w[i], xwcm, &xwc);
          else
          {
            xwc.x = -tmp_win->title_height;
            XConfigureWindow(dpy, tmp_win->left_w[i], xwcm, &xwc);
          }
          xwc.x += tmp_win->title_height;
        }
      }

      xwc.x=w-tmp_win->boundary_width+tmp_win->bw;
      for(i=0;i<Scr.nr_right_buttons;i++)
      {
        if(tmp_win->right_w[i] != None)
        {
          xwc.x -=tmp_win->title_height;
          if(xwc.x > tmp_win->boundary_width)
            XConfigureWindow(dpy, tmp_win->right_w[i], xwcm, &xwc);
          else
          {
            xwc.x = -tmp_win->title_height;
            XConfigureWindow(dpy, tmp_win->right_w[i], xwcm, &xwc);
          }
        }
      }
    }

    if(tmp_win->flags & BORDER)
    {
      tmp_win->corner_width = GetDecor(tmp_win,TitleHeight) + tmp_win->bw +
        tmp_win->boundary_width ;

      if(w < 2*tmp_win->corner_width)
        tmp_win->corner_width = w/3;
      if((h < 2*tmp_win->corner_width)
#ifdef WINDOWSHADE
        &&!shaded
#endif
         )
        tmp_win->corner_width = h/3;
      xwidth = w - 2*tmp_win->corner_width+tmp_win->bw;
      ywidth = h - 2*tmp_win->corner_width;
      xwcm = CWWidth | CWHeight | CWX | CWY;
      if(xwidth<2)
        xwidth = 2;
      if(ywidth<2)
        ywidth = 2;

      for(i=0;i<4;i++)
      {
        if(i==0)
        {
          xwc.x = tmp_win->corner_width;
          xwc.y = 0;
          xwc.height = tmp_win->boundary_width;
          xwc.width = xwidth;
        }
        else if (i==1)
        {
          xwc.x = w - tmp_win->boundary_width+tmp_win->bw;
          xwc.y = tmp_win->corner_width;
          xwc.width = tmp_win->boundary_width;
          xwc.height = ywidth;

        }
        else if(i==2)
        {
          xwc.x = tmp_win->corner_width;
          xwc.y = h - tmp_win->boundary_width+tmp_win->bw;
          xwc.height = tmp_win->boundary_width+tmp_win->bw;
          xwc.width = xwidth;
        }
        else
        {
          xwc.x = 0;
          xwc.y = tmp_win->corner_width;
          xwc.width = tmp_win->boundary_width;
          xwc.height = ywidth;
        }
#ifdef WINDOWSHADE
        if (!shaded||(i!=2))
#endif
          XConfigureWindow(dpy, tmp_win->sides[i], xwcm, &xwc);
      }

      xwcm = CWX|CWY|CWWidth|CWHeight;
      xwc.width = tmp_win->corner_width;
      xwc.height = tmp_win->corner_width;
      for(i=0;i<4;i++)
      {
        if(i%2)
          xwc.x = w - tmp_win->corner_width+tmp_win->bw;
        else
          xwc.x = 0;

        if(i/2)
          xwc.y = h - tmp_win->corner_width;
        else
          xwc.y = 0;

#ifdef WINDOWSHADE
	if (!shaded||(i==0)||(i==1))
#endif
	    XConfigureWindow(dpy, tmp_win->corners[i], xwcm, &xwc);
      }

    }
  }
  tmp_win->attr.width = w - 2*tmp_win->boundary_width;
  tmp_win->attr.height = h - tmp_win->title_height
    - 2*tmp_win->boundary_width;
  /* may need to omit the -1 for shaped windows, next two lines*/
  cx = tmp_win->boundary_width-tmp_win->bw;
  cy = tmp_win->title_height + tmp_win->boundary_width-tmp_win->bw;

#ifdef WINDOWSHADE
  if (!shaded) {
#endif
      XResizeWindow(dpy, tmp_win->w, tmp_win->attr.width,
		    tmp_win->attr.height);
      XMoveResizeWindow(dpy, tmp_win->Parent, cx,cy,
                        tmp_win->attr.width, tmp_win->attr.height);
#ifdef WINDOWSHADE
  }
#endif

  /*
   * fix up frame and assign size/location values in tmp_win
   */
  frame_wc.x = tmp_win->frame_x = x;
  frame_wc.y = tmp_win->frame_y = 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);
#ifdef FVWM_DEBUG_MSGS
  fvwm_msg(DBG,"SetupFrame",
           "New frame dimensions (x == %d, y == %d, w == %d, h == %d)",
           frame_wc.x, frame_wc.y, frame_wc.width, frame_wc.height);
#endif

#ifdef SHAPE
  if (ShapesSupported)
  {
    if ((Resized)&&(tmp_win->wShaped))
    {
      SetShape(tmp_win,w);
    }
  }
#endif /* SHAPE */
  XSync(dpy,0);
  if (sendEvent
#ifdef WINDOWSHADE
      && !shaded
#endif
      )
  {
    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->boundary_width;
    client_event.xconfigure.y = y + tmp_win->title_height+
      tmp_win->boundary_width;
    client_event.xconfigure.width = w-2*tmp_win->boundary_width;
    client_event.xconfigure.height =h-2*tmp_win->boundary_width -
      tmp_win->title_height;

    client_event.xconfigure.border_width =tmp_win->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);
#ifdef FVWM_DEBUG_MSGS
    fvwm_msg(DBG,"SetupFrame","Sent ConfigureNotify (w == %d, h == %d)",
             client_event.xconfigure.width,client_event.xconfigure.height);
#endif
  }
  XSync(dpy,0);

  BroadcastConfig(M_CONFIGURE_WINDOW,tmp_win);
}


/****************************************************************************
 *
 * Sets up the shaped window borders
 *
 ****************************************************************************/
void SetShape(FvwmWindow *tmp_win, int w)
{
#ifdef SHAPE
  if (ShapesSupported)
  {
    XRectangle rect;

    XShapeCombineShape (dpy, tmp_win->frame, ShapeBounding,
                        tmp_win->boundary_width,
                        tmp_win->title_height+tmp_win->boundary_width,
                        tmp_win->w,
                        ShapeBounding, ShapeSet);
    if (tmp_win->title_w)
    {
      /* windows w/ titles */
      rect.x = tmp_win->boundary_width;
      rect.y = tmp_win->title_y;
      rect.width = w - 2*tmp_win->boundary_width+tmp_win->bw;
      rect.height = tmp_win->title_height;


      XShapeCombineRectangles(dpy,tmp_win->frame,ShapeBounding,
                              0,0,&rect,1,ShapeUnion,Unsorted);
    }
  }
#endif
}
