/*********************************************************************
 *
 *         EZWGL, the EZ Widget and Graphics Library
 *
 *             Copyright (C) 1996, 1997  Maorong Zou
 *  
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public
 * License along with this library; if not, write to the Free
 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 **********************************************************************/
/*
 *  June 1996.  Beta Release.
 *  Sept 1996.  Release Version 1.0
 *  Dec 1996.  Release Version 1.1 Beta
 *  April 1997.  Release Version 1.2
 *  November 1997.  Release Version 1.3
 */
/*******************************************************************
 *  
 *  Border Stuff.
 */
#define _EZ_WIDGET_BORDER_C_

#include "EZ_Widget.h"
/*******************************************************************
 *
 * Functions implemented in this file:
 */

void                EZ_FillRectBorderCoor MY_ANSIARGS((
						       int width, int height, int bdwidth,
						       int xoff, int yoff,
						       XPoint *top, XPoint *bottom,
						       XPoint *left, XPoint *right));
void                EZ_FillDiamondBorderCoor MY_ANSIARGS((
							  int width, int height, int bdwidth,
							  int xoff, int yoff,
							  XPoint *tr, XPoint *bl,
							  XPoint *tl, XPoint *br));
void                EZ_DrawRectBorder MY_ANSIARGS((EZ_Widget *widget, Drawable drawable));
void                EZ_DrawRectBorderWithSize MY_ANSIARGS((
							   EZ_Widget *widget, Drawable drawable,
							   int x, int y, int w, int h, int bw,
							   int bdtype));
void                EZ_DrawDiamondBorderWithSize MY_ANSIARGS((
							      EZ_Widget *widget, Drawable drawable,
							      int x, int y, int w, int h, int bw,
							      int bdtype));
void                EZ_RenderBorder  MY_ANSIARGS((
						  Drawable  drawable,
						  int       type,
						  EZ_BorderPiece *top, 
						  EZ_BorderPiece *bottom, 
						  EZ_BorderPiece *left,
						  EZ_BorderPiece *right,
						  EZ_BorderPiece *extra,
						  EZ_BorderPiece *extraB  ));

void                EZ_FillNBBorderCoor  MY_ANSIARGS((int width, int height, int bwidth, int padb,
						      int xoffset, int yoffset,
						      XPoint *left, XPoint *ul, XPoint *top,
						      XPoint *ur, XPoint *right  ));
void                EZ_SetupUpBdGC MY_ANSIARGS((
						EZ_Widget *widget,
						GC        *left,  GC *uleft, GC *top, GC *uright,
						GC *right, GC *bottom));
void                EZ_SetupDownBdGC MY_ANSIARGS((
						  EZ_Widget *widget,
						  GC        *left,  GC *uleft, GC *top, GC *uright,
						  GC *right, GC *bottom  ));

void                EZ_DrawFocusIndicator MY_ANSIARGS((EZ_Widget *widget, Drawable drawable, 
						       int inout));
/******************************************************************/

#define EZ_BORDER_POLYGON               1
#define EZ_BORDER_LINE                  2

/******************************************************************
 * 
 * Draw Border.  Border are like the following:
 *
 *     -----------------------------------------------------
 *    |\                TOP, BrightGray2                   /|
 *    | \-------------------------------------------------/ |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |                                               |  |  <- Right 
 *    |  | <- Left                                       |  |    DrakGray1
 *    |  |      BrightGray1                              |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |            THE WIDGET                         |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  |                                               |  |
 *    |  /-----------------------------------------------\  |
 *    | /           Bottom DarkGray2                      \ |
 *     ------------------------------------------------------
 *
 ******************************************************************
 *
 *  All drawing are done in a pixmap and then copied to the 
 *  widget window.
 *
 ******************************************************************/

/******************************************************************
 *
 *  Draw the Rectangular border of a Rectangular shaped widget.
 *  Note:  A widget always fill completely its supporting window !
 */
void  EZ_DrawRectBorder(widget, drawable)
     EZ_Widget *widget;
     Drawable        drawable;
{
  int                w,h,bw, padb, padb2;

  bw  = EZ_WidgetBorderWidth(widget);
  w   = EZ_WidgetWidth(widget);
  h   = EZ_WidgetHeight(widget);
  padb= EZ_WidgetPadB(widget);
  padb2 = padb+padb;

  if( bw > 0) 
    EZ_DrawRectBorderWithSize(widget, drawable, padb,padb, w-padb2,h-padb2,bw,
			      (int)(EZ_WidgetBorderStyle(widget)));

  if(EZ_WeAreInFocus != 0 && widget == EZ_CurrentFocusingWidget)
    EZ_DrawFocusIndicator(widget, drawable, FocusIn);
  else if(widget == EZ_CurrentFlashWidget)
    {
      w--; h--;
      EZ_FlashWidgetWindowBorder(widget, drawable, 0, 0, w, h);
    }
}

/*********************************************************************************/
void EZ_DrawFocusIndicator(widget, drawable, inout)
     EZ_Widget *widget; Drawable drawable; int inout;
{
  int  padb= EZ_WidgetPadB(widget);
  if(padb > 0)
    {
      int  w   = EZ_WidgetWidth(widget) - 1;
      int  h   = EZ_WidgetHeight(widget) -1;
      int  style, refresh = 0;

      GC gc;
      unsigned long pv;
      if(drawable == (Drawable)0) { drawable = EZ_WidgetWindow(widget); refresh = 1; }
      if(inout == FocusIn)
	{
	  XSetForeground(EZ_Display, EZ_WRITABLEGC2, EZ_KbdFocusHighlightColor);
	  gc = EZ_WRITABLEGC2;
	}
      else EZ_GetParentBgGCN(widget, &gc, &pv);
      XDrawLine(EZ_Display, drawable, gc, 0,1, w, 1);
      XDrawLine(EZ_Display, drawable, gc, w,0, w, h);
      XDrawLine(EZ_Display, drawable, gc, 1,h, 1, 1);
      style = EZ_WidgetBorderStyle(widget);
      if((style != EZ_BORDER_NB_UP && style != EZ_BORDER_NB_DOWN))
	XDrawLine(EZ_Display, drawable, gc, w+1,h, 0, h);
      if(refresh) XSync(EZ_Display, False);
    }
}
/*********************************************************************************
 *
 *  Draw Rectangular border.
 */
void EZ_SetupUpBdGC(widget, left, uleft, top, uright,right, bottom)
     EZ_Widget *widget;
     GC        *top, *bottom, *left, *right, *uleft, *uright;     
{
  unsigned long pixel;

  if(EZ_WidgetBackground(widget))
    {
      pixel = EZ_GetDarkColor(EZ_WidgetBackground(widget));
      XSetForeground(EZ_Display, EZ_BD_DARKGC, pixel);
      pixel = EZ_GetBrightColor(EZ_WidgetBackground(widget));
      XSetForeground(EZ_Display, EZ_BD_BRIGHTGC, pixel);
      *right = *bottom = EZ_BD_DARKGC;
      *uleft = *uright = *top = *left = EZ_BD_BRIGHTGC;
    }
  else if(EZ_WidgetParentBG(widget) && *(EZ_WidgetParentBG(widget)))
    {
      pixel = EZ_GetDarkColor(*(EZ_WidgetParentBG(widget)));
      XSetForeground(EZ_Display, EZ_BD_DARKGC, pixel);
      pixel = EZ_GetBrightColor(*(EZ_WidgetParentBG(widget)));
      XSetForeground(EZ_Display, EZ_BD_BRIGHTGC, pixel);
      *uleft = *uright = *top = *left = EZ_BD_BRIGHTGC;	  
      *right = *bottom = EZ_BD_DARKGC;
    }
  else
    {
      *top = EZ_BRIGHTGC2;  *bottom = EZ_DARKGC2;
      *left = EZ_BRIGHTGC1;  *right = EZ_DARKGC1;
      *uleft = EZ_BRIGHTGC2; *uright = EZ_BRIGHTGC1;
    }  
}

void EZ_SetupDownBdGC(widget, left, uleft, top, uright,right, bottom)
     EZ_Widget *widget;
     GC        *top, *bottom, *left, *right, *uleft, *uright;     
{
  unsigned long pixel;

  if(EZ_WidgetBackground(widget))
    {
      pixel = EZ_GetDarkColor(EZ_WidgetBackground(widget));
      XSetForeground(EZ_Display, EZ_BD_DARKGC, pixel);
      pixel = EZ_GetBrightColor(EZ_WidgetBackground(widget));
      XSetForeground(EZ_Display, EZ_BD_BRIGHTGC, pixel);
      *right = *bottom = EZ_BD_BRIGHTGC;
      *uleft = *uright = *left = *top = EZ_BD_DARKGC;

    }
  else if(EZ_WidgetParentBG(widget) && *(EZ_WidgetParentBG(widget)))
    {
      pixel = EZ_GetDarkColor(*(EZ_WidgetParentBG(widget)));
      XSetForeground(EZ_Display, EZ_BD_DARKGC, pixel);
      pixel = EZ_GetBrightColor(*(EZ_WidgetParentBG(widget)));
      XSetForeground(EZ_Display, EZ_BD_BRIGHTGC, pixel);
      *uleft = *uright = *left = *top = EZ_BD_DARKGC;
      *bottom = *right = EZ_BD_BRIGHTGC;	  
    }
  else
    {
      *uleft = *top = EZ_DARKGC2;  *bottom = EZ_BRIGHTGC2;
      *uright = *left = EZ_DARKGC1;  *right = EZ_BRIGHTGC1;  
    }  
}
/********************************************************************/

void EZ_DrawRectBorderWithSize(widget, drawable, x,y,w,h,bw, bdtype)
     EZ_Widget *widget;
     Drawable  drawable;
     int       x,y,w,h, bdtype,bw;
{
  EZ_BorderPiece     top, bottom, left, right, uleft, uright;
  int                padb, bw2 = bw << 1;
  GC                 gc; 

  switch(bdtype)
    {
    case  EZ_BORDER_NONE:          /* nothing need to be done    */
      break;

    case EZ_BORDER_FLAT:           /* draw a black flat border   */
      EZ_SetupUpBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
      top.gc = left.gc = right.gc = bottom.gc;
      EZ_FillRectBorderCoor(w,h,bw,x,y,top.xp,bottom.xp,left.xp,right.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &top, &bottom, &left, &right, 0, 0);
      break;

    case EZ_BORDER_FRAMED_UP:
    case EZ_BORDER_FRAMED_DOWN:
      {
	GC  gc;
	unsigned long bgpv;
	if(bw > 0)
	  {
	    EZ_GetBackgroundGC(widget, &gc, &bgpv, 0, 0);
	    XFillRectangle(EZ_Display, drawable, gc, x, y, (unsigned int)w, (unsigned int)bw);
	    XFillRectangle(EZ_Display, drawable, gc, x, y, (unsigned int)bw, (unsigned int)h);
	    XFillRectangle(EZ_Display, drawable, gc, x+w-bw,y,(unsigned int)bw, (unsigned int)h);
	    XFillRectangle(EZ_Display, drawable, gc, x,h-bw+y,(unsigned int)w, (unsigned int)bw);
	  }
      }
      if(bdtype == EZ_BORDER_FRAMED_UP)
	EZ_SetupUpBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
      else
	EZ_SetupDownBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
      EZ_FillRectBorderCoor(w-1,h-1,0,x,y,top.xp,bottom.xp,left.xp,right.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_LINE, &top, &bottom, &left, &right,0, 0);
      if(bdtype == EZ_BORDER_FRAMED_UP)
	EZ_SetupDownBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
      else
	EZ_SetupUpBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
      EZ_FillRectBorderCoor(w-bw2-1,h-bw2-1,0,x+bw, y+bw, top.xp,bottom.xp,left.xp,right.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_LINE, &top, &bottom, &left, &right,0, 0);
      break;

    case  EZ_BORDER_UP:
      EZ_SetupUpBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
      EZ_FillRectBorderCoor(w,h,bw,x,y, top.xp,bottom.xp,left.xp,right.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &top, &bottom, &left, &right,0, 0);     
      break; 

    case  EZ_BORDER_DOWN:
      EZ_SetupDownBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
      EZ_FillRectBorderCoor(w,h,bw,x,y,top.xp,bottom.xp,left.xp,right.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &top, &bottom, &left, &right,0, 0);  
      break; 

    case EZ_BORDER_NB_UP:
      padb = EZ_WidgetPadB(widget);
      EZ_FillNBBorderCoor(w,h,bw,padb,x,y,left.xp,uleft.xp, top.xp, uright.xp, right.xp);
      EZ_SetupUpBdGC(widget, &left.gc, &uleft.gc, &top.gc, &uright.gc, &right.gc, &bottom.gc);
      EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &left, &uleft, &top, &uright, &right, 0);  
      /* fix the corner */
      if(EZ_WidgetParentBG(widget) && *(EZ_WidgetParentBG(widget)))
	{
	  XSetForeground(EZ_Display, EZ_WRITABLEGC, *(EZ_WidgetParentBG(widget)));
	  gc = EZ_WRITABLEGC;	  
	}
      else gc = EZ_NORMALGC1;
      (uleft.xp)[0].x = x;  (uleft.xp)[0].y = x;
      XFillPolygon(EZ_DisplayForWidgets, drawable, gc,  uleft.xp, 3, Convex, CoordModeOrigin); 
      (uright.xp)[0].x = x+w;  (uright.xp)[0].y = y;
      XFillPolygon(EZ_DisplayForWidgets, drawable, gc,  uright.xp, 3, Convex, CoordModeOrigin); 
      break;

    case EZ_BORDER_NB_DOWN:
      padb = EZ_WidgetPadB(widget);
      EZ_FillNBBorderCoor(w,h,bw,padb,x,y,left.xp, uleft.xp, top.xp, uright.xp, right.xp);
      EZ_SetupDownBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
      EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &left, &uleft, &top, &uright, &right, 0);  
      /* fix the corner */
      if(EZ_WidgetParentBG(widget) && *(EZ_WidgetParentBG(widget)))
	{
	  XSetForeground(EZ_Display, EZ_WRITABLEGC, *(EZ_WidgetParentBG(widget)));
	  gc = EZ_WRITABLEGC;	  
	}
      else  gc = EZ_NORMALGC1;
      (uleft.xp)[0].x = x;  (uleft.xp)[0].y = x;
      XFillPolygon(EZ_DisplayForWidgets, drawable, gc,  uleft.xp, 3, Convex, CoordModeOrigin); 
      (uright.xp)[0].x = x+w;  (uright.xp)[0].y = y;
      XFillPolygon(EZ_DisplayForWidgets, drawable, gc,  uright.xp, 3, Convex, CoordModeOrigin);     
      break;
    case EZ_BORDER_FRAMED:
    case EZ_BORDER_CARVED:
      {
	GC gc;
	unsigned long bgpv;
	if(bw > 0)
	  {
	    EZ_GetBackgroundGC(widget, &gc, &bgpv, 0, 0);
	    XFillRectangle(EZ_Display, drawable, gc, x, y, (unsigned int)w, (unsigned int)bw);
	    XFillRectangle(EZ_Display, drawable, gc, x, y, (unsigned int)bw, (unsigned int)h);
	    XFillRectangle(EZ_Display, drawable, gc, x+w-bw,y,(unsigned int)bw, (unsigned int)h);
	    XFillRectangle(EZ_Display, drawable, gc, x,h-bw+y,(unsigned int)w, (unsigned int)bw);
	  }
      }
      {
	if(bw >= 3)
	  {
	    int rbw = (bw+2)/3;
	    int mbw = bw - rbw;
	    int sadjust= bw2 - (rbw + rbw) ;
	    if(bdtype == EZ_BORDER_FRAMED)
	      EZ_SetupUpBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
	    else
	      EZ_SetupDownBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
	    EZ_FillRectBorderCoor(w,h,rbw,x,y, top.xp,bottom.xp,left.xp,right.xp);
	    EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &top, &bottom, &left, &right,0, 0);     
	    if(bdtype == EZ_BORDER_FRAMED)
	      EZ_SetupDownBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
	    else
	      EZ_SetupUpBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
	    EZ_FillRectBorderCoor(w-sadjust,h-sadjust,rbw,x+mbw, y+mbw, top.xp,bottom.xp,left.xp,right.xp);
	    EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &top, &bottom, &left, &right,0, 0);
	  }
	else
	  {
	    if(bdtype == EZ_BORDER_FRAMED)	    
	      EZ_SetupUpBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
	    else
	      EZ_SetupDownBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
	    EZ_FillRectBorderCoor(w-1,h-1,0,x,y,top.xp,bottom.xp,left.xp,right.xp);
	    EZ_RenderBorder(drawable,EZ_BORDER_LINE, &top, &bottom, &left, &right,0, 0);
	    if(bdtype == EZ_BORDER_FRAMED)	    	    
	      EZ_SetupDownBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
	    else
	      EZ_SetupUpBdGC(widget, &left.gc, &uleft.gc, &top.gc,&uright.gc, &right.gc, &bottom.gc);
	    EZ_FillRectBorderCoor(w-bw2-1,h-bw2-1,0,x+bw, y+bw, top.xp,bottom.xp,left.xp,right.xp);
	    EZ_RenderBorder(drawable,EZ_BORDER_LINE, &top, &bottom, &left, &right,0, 0);
	  }
      }
      break;
    default:
      (void) fprintf(stderr, "Unknown border type!\n");
      break;
    }
}
/*********************************************************************************
 *
 *  Compute the coordinates of the edge polygons for rectangular shaped widgets.
 *  See figure above.
 *
 */
void EZ_FillRectBorderCoor(width,height,bwidth,xoffset,yoffset,top,bottom,left,right)
     int        width, height, bwidth,xoffset, yoffset;
     XPoint     *left, *right, *top, *bottom;
{
  short x,y,w,h,bw;
    
  x  = (short)xoffset;      /*   x coor of origin  */              
  y  = (short)yoffset;      /*   y coor of origin  */
  w  = (short)width;        /*   width and height, */
  h  = (short)height;       /*   including border  */
  bw = (short)bwidth;       /*   border width      */
  

  /* the top border piece     */
  top[0].x = x;          top[0].y = y;
  top[1].x = w+x;        top[1].y = y;  
  top[2].x = w-bw+x;     top[2].y = bw+y;  
  top[3].x = bw+x;       top[3].y = bw+y;  

  /* the bottom border piece  */  
  bottom[0].x = x;       bottom[0].y = h+y;
  bottom[1].x = w+x;     bottom[1].y = h+y;
  bottom[2].x = w-bw+x;  bottom[2].y = h-bw+y;
  bottom[3].x = bw+x;    bottom[3].y = h-bw+y;

  /* the left border piece   */
  left[0].x = x;         left[0].y = y;
  left[1].x = x;         left[1].y = h+y;  
  left[2].x = bw+x;      left[2].y = h-bw+y;
  left[3].x = bw+x;      left[3].y = bw+y;

  /* the right border piece  */
  right[0].x= w+x;       right[0].y = y;
  right[1].x= w+x;       right[1].y = h+y;
  right[2].x= w-bw+x;    right[2].y = h-bw+y;
  right[3].x= w-bw+x;    right[3].y = bw+y;
}


void EZ_DrawDiamondBorderWithSize(widget, drawable,x,y,w,h,bw, btype)
     EZ_Widget  *widget;
     Drawable         drawable;
     int              x,y,w,h,bw, btype;
{
  int                 bw2,bw22;
  EZ_BorderPiece     tr, bl, tl, br, jk1, jk2;

  switch(btype)
    {
    case  EZ_BORDER_NONE:          /* nothing need to be done    */
      break;

    case EZ_BORDER_FLAT:           /* draw a black flat border   */
      EZ_SetupDownBdGC(widget, &br.gc, &jk1.gc, &bl.gc, &jk2.gc, &tl.gc, &bl.gc);
      tr.gc = bl.gc = tl.gc = br.gc;
      EZ_FillDiamondBorderCoor(w,h,bw,x,y,tr.xp,bl.xp,tl.xp,br.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &tr, &bl, &tl, &br,0, 0);
      break;

    case   EZ_BORDER_FRAMED_UP:
      bw2 = (int) (1.4142135623730951* (float) bw);
      bw22 = bw2 <<1;
      EZ_SetupDownBdGC(widget, &br.gc, &jk1.gc, &bl.gc, &jk2.gc, &tl.gc, &bl.gc);
      EZ_FillDiamondBorderCoor(w,h,0,x,y,tr.xp,bl.xp,tl.xp,br.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_LINE, &tr, &bl, &tl, &br,0, 0);
      EZ_SetupUpBdGC(widget, &br.gc, &jk1.gc, &bl.gc, &jk2.gc, &tl.gc, &tr.gc);
      EZ_FillDiamondBorderCoor(w-bw22,h-bw22,0,x+bw2, y, tr.xp,bl.xp,tl.xp,br.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_LINE, &tr, &bl, &tl, &br,0, 0);
      break;

    case   EZ_BORDER_FRAMED_DOWN:
      bw2 = (int) (1.4142135623730951* (float) bw);
      bw22 = bw2 <<1;
      EZ_SetupUpBdGC(widget, &br.gc, &jk1.gc, &bl.gc, &jk2.gc, &tl.gc, &tr.gc);
      EZ_FillDiamondBorderCoor(w,h,0,x,y,tr.xp,bl.xp,tl.xp,br.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_LINE, &tr, &bl, &tl, &br,0, 0);
      EZ_SetupDownBdGC(widget, &br.gc, &jk1.gc, &bl.gc, &jk2.gc, &tl.gc, &bl.gc);
      EZ_FillDiamondBorderCoor(w-bw22,h-bw22,0,x+bw2, y, tr.xp,bl.xp,tl.xp,br.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_LINE, &tr, &bl, &tl, &br,0, 0);
      break;
      
    case  EZ_BORDER_UP:
      EZ_SetupDownBdGC(widget, &br.gc, &jk1.gc, &bl.gc, &jk2.gc, &tl.gc, &tr.gc);
      EZ_FillDiamondBorderCoor(w,h,bw,x,y, tr.xp,bl.xp,tl.xp,br.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &tr, &bl, &tl, &br,0, 0);     
      break; 

    case  EZ_BORDER_DOWN:
      EZ_SetupUpBdGC(widget, &br.gc, &jk1.gc, &bl.gc, &jk2.gc, &tl.gc, &tr.gc);
      EZ_FillDiamondBorderCoor(w,h,bw,x,y, tr.xp,bl.xp,tl.xp,br.xp);
      EZ_RenderBorder(drawable,EZ_BORDER_POLYGON, &tr, &bl, &tl, &br,0, 0);  
      break; 

    default:
      (void) fprintf(stderr, "Unknown border style!\n");
      break;
    }
}
/*********************************************************************************
 *
 *  Compute the coordinates of the edge polygons for diamond shaped widgets.
 *
 *
 *                  /\             
 *             tl  /  \ tr         
 *                /    \           
 *        (x,y)  <      >       
 *                \    /        
 *              bl \  / br      
 *                  \/          
 */
void EZ_FillDiamondBorderCoor(width,height,bwidth,xoffset,yoffset,tr,bl,tl,br)
     int        width, height, bwidth,xoffset, yoffset;
     XPoint     *tl, *tr, *bl, *br;
{
  short x,y,w,h,bw;
  int   tmp;

  x  = (short)xoffset;      /*   x coor of origin  */              
  y  = (short)yoffset;      /*   y coor of origin  */

  tmp = (width + 1) >> 1;
  if(tmp != 0)   w = (short) tmp;
  else           w = 1;  
  h = w;

  bw = (short) (1.4142135623730951 * (float) bwidth);
  
  /* the tl border piece     */
  tl[0].x = x;          tl[0].y = y;
  tl[1].x = w+x;        tl[1].y = y - h;  
  tl[2].x = w+x;        tl[2].y = bw+y-h;  
  tl[3].x = bw+x;       tl[3].y = y;  

  /* the tr border piece  */  
  tr[0].x = x+w;       tr[0].y = y-h;
  tr[1].x = x+w+w;     tr[1].y = y;
  tr[2].x = x+w+w-bw;  tr[2].y = y;
  tr[3].x = x+w;       tr[3].y = y-h+bw;

  /* the bl border piece   */
  bl[0].x = x;         bl[0].y = y;
  bl[1].x = x+w;       bl[1].y = h+y;  
  bl[2].x = x+w;       bl[2].y = y+h-bw;
  bl[3].x = x+bw;      bl[3].y = y;

  /* the br border piece  */
  br[0].x= w+x;       br[0].y = y+h;
  br[1].x= w+x+w;     br[1].y = y;
  br[2].x= w+x+w-bw;  br[2].y = y;
  br[3].x= w+x;       br[3].y = y+h-bw;
}

/****************************************************************************
 *
 *   Render a 3D border of a widget.
 */
void   EZ_RenderBorder(drawable,type, top, bottom, left, right, extra, extraB)
     Drawable        drawable;
     int             type;
     EZ_BorderPiece  *top, *bottom, *left, *right, *extra, *extraB;
{
  switch(type)
    {
    case EZ_BORDER_POLYGON:
      XFillPolygon(EZ_DisplayForWidgets, drawable,
		   top->gc,
		   top->xp,
		   4,
		   Convex, CoordModeOrigin);  
      XFillPolygon(EZ_DisplayForWidgets, drawable,
		   bottom->gc,
		   bottom->xp,
		   4,
		   Convex, CoordModeOrigin);  
      XFillPolygon(EZ_DisplayForWidgets, drawable,
		   left->gc,
		   left->xp,
		   4,
		   Convex, CoordModeOrigin);  
      XFillPolygon(EZ_DisplayForWidgets, drawable,
		   right->gc,
		   right->xp,
		   4,
		   Convex, CoordModeOrigin);  
      if(extra) XFillPolygon(EZ_DisplayForWidgets, drawable,
			     extra->gc,
			     extra->xp,
			     4,
			     Convex, CoordModeOrigin);  	
      if(extraB) XFillPolygon(EZ_DisplayForWidgets, drawable,
			      extraB->gc,
			      extraB->xp,
			      4,
			      Convex, CoordModeOrigin);  	
      break;
    case EZ_BORDER_LINE:
      XDrawLines(EZ_DisplayForWidgets, drawable,
		 top->gc,
		 top->xp,
		 2,
		 CoordModeOrigin);
      XDrawLines(EZ_DisplayForWidgets, drawable,
		 bottom->gc,
		 bottom->xp,
		 2,
		 CoordModeOrigin);
      XDrawLines(EZ_DisplayForWidgets, drawable,
		 left->gc,
		 left->xp,
		 2,
		 CoordModeOrigin);
      XDrawLines(EZ_DisplayForWidgets, drawable,
		 right->gc,
		 right->xp,
		 2,
		 CoordModeOrigin);
      if(extra)  XDrawLines(EZ_DisplayForWidgets, drawable,
			    extra->gc,
			    extra->xp,
			    2,
			    CoordModeOrigin);
      if(extraB) XDrawLines(EZ_DisplayForWidgets, drawable,
			    extraB->gc,
			    extraB->xp,
			    2,
			    CoordModeOrigin);
      break;
    default:
      break;
    }
}
/******************************************************************************/

void EZ_FillNBBorderCoor(width,height,bwidth,bpad,xoffset,yoffset,left,ul, top, ur, right)
     int        width, height, bwidth,xoffset, yoffset, bpad;
     XPoint     *left, *ul, *top, *ur, *right;
{
  short x,y,w,h,bw,bw2, bww, padb;
    
  x  = (short)xoffset;      /*   x coor of origin  */              
  y  = (short)yoffset;      /*   y coor of origin  */
  w  = (short)width;        /*   width and height, */
  h  = (short)height;       /*   including border  */
  bw = (short)bwidth;       /*   border width      */
  padb = (short) bpad;
  bww = (bw * 19) >> 3;
  bw2 = bw << 1;

  /* the left border piece   */
  left[0].x = x;         left[0].y = h+y + padb;
  left[1].x = bw+x;      left[1].y = h+y + padb;  
  left[2].x = bw+x;      left[2].y = bww+y;
  left[3].x = x;         left[3].y = bw2+y;

  /* the upper left piece    */
  ul[0].x = left[2].x;   ul[0].y = left[2].y;
  ul[1].x = left[3].x;   ul[1].y = left[3].y;
  ul[2].x = bw2 + x;     ul[2].y = y;
  ul[3].x = bww + x;     ul[3].y = bw + y;

  /* the top border piece     */
  top[0].x = ul[2].x;    top[0].y = ul[2].y;
  top[1].x = ul[3].x;    top[1].y = ul[3].y;  
  top[2].x = w-bww+x;    top[2].y = bw+y;  
  top[3].x = w-bw2+x;    top[3].y = y;  

  /* the upper right piece    */
  ur[0].x = top[2].x;    ur[0].y = top[2].y;
  ur[1].x = top[3].x;    ur[1].y = top[3].y;
  ur[2].x = w + x;       ur[2].y = bw2 + y;
  ur[3].x = w - bw + x;  ur[3].y = bww + y;


  /* the right border piece  */
  right[0].x= ur[3].x;   right[0].y = ur[3].y;
  right[1].x= ur[2].x;   right[1].y = ur[2].y;
  right[2].x= w+x;       right[2].y = h + y + padb;
  right[3].x= w-bw+x;    right[3].y = h + y + padb;
}
/******************************************************************************/
#undef _EZ_WIDGET_BORDER_C_
