/**
 *
 * $Id: Draw.c,v 1.3 1998/02/04 20:41:07 u27113 Exp $
 *
 * Copyright (C) 1997 Free Software Foundation, Inc.
 *
 * This file is part of the GNU LessTif Library.
 *
 * 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.
 *
 **/

static char rcsid[] = "$Id: Draw.c,v 1.3 1998/02/04 20:41:07 u27113 Exp $";

#include <XmI/DebugUtil.h>
#include <Xm/DrawP.h>

/* Used by List.c and IconG.c. */
void
_XmDrawHighlight(Display *display,
                 Drawable d,
                 GC gc,
                 Position x,
                 Position y,
                 Dimension width,
                 Dimension height,
                 Dimension highlight_thick,
                 int line_style)
{
    int i;
    static char dash_list[] =
    {8, 8};

    /* this is dangerous, but the same as the Manger and Primitive */
    XSetLineAttributes(display, gc, 0, line_style, CapButt, JoinMiter);

    switch (line_style)
    {
    case LineOnOffDash:
    case LineDoubleDash:
        XSetDashes(display, gc, 0, dash_list, 2);
        for (i = 0; i < highlight_thick; i++)
        {
            XDrawLine(display, (Window)d, gc,
                      x, y + i, x + width - 1, y + i);

            XDrawLine(display, (Window)d, gc,
                      x, y + height - 1 - i, x + width - 1, y + height - 1 - i);

            XDrawLine(display, (Window)d, gc,
                      x + i, y, x + i, y + height - 1);

            XDrawLine(display, (Window)d, gc,
                      x + width - 1 - i, y, x + width - 1 - i, y + height - 1);
        }
        break;

    case LineSolid:
    default:
        for (i = 0; i < highlight_thick; i++)
        {
            /*
             * draw the vertical lines
             */
            XFillRectangle(display,
                           d,
                           gc,
                           x + i, y,
                           1, height - i);

            XFillRectangle(display,
                           d,
                           gc,
                           x + width - i - 1, y + i + 1,
                           1, height - i - 1);

            /*
             * draw the horizontal lines
             */
            XFillRectangle(display,
                           d,
                           gc,
                           x, y + i,
                           width - i, 1);

            XFillRectangle(display,
                           d,
                           gc,
                           x + i + 1, y + height - i - 1,
                           width - i - 1, 1);

        }
        break;
    }
}

/* Shadow */
void
XmeClearBorder(Display *display,
	       Window win,
	       Position x,
	       Position y,
	       Dimension width,
	       Dimension height,
	       Dimension shadow_thick)
{
    if (shadow_thick == 0)
    {
        shadow_thick = 1;
    }

    XClearArea(display, win,
               x, y,
               shadow_thick, height,
               False);

    XClearArea(display, win,
               x, y,
               width, shadow_thick,
               False);
    XClearArea(display, win,
               x + width - shadow_thick, y,
               shadow_thick, height,
               False);

    XClearArea(display, win,
               x, y + height - shadow_thick,
               width, shadow_thick,
               False);
}

/* Shadow */
void
XmeDrawShadows(Display *display,
	       Window win,
	       GC topShadowGC,
	       GC bottomShadowGC,
	       Position x, Position y,
	       Dimension width, Dimension height,
	       Dimension shadowThickness,
	       unsigned int shadowType)
{
    GC topGC = 0, bottomGC = 0;
    int i;
    Cardinal n;

    if (shadowThickness > width || shadowThickness > height)
    {
        shadowThickness = 2;
    }

    switch (shadowType)
    {
    case XmSHADOW_ETCHED_IN:
    case XmSHADOW_IN:
        topGC = bottomShadowGC;
        bottomGC = topShadowGC;
        break;
    case XmSHADOW_ETCHED_OUT:
    case XmSHADOW_OUT:
        bottomGC = bottomShadowGC;
        topGC = topShadowGC;
        break;
    case XmNO_LINE:
        break;
    default:
        n = 0;
        XtAppWarningMsg(XtDisplayToApplicationContext(display),
                        "shadowType", "shadowType",
                        "LessTifError",
                        "Illegal shadow type sent to _XmDrawShadows",
                        NULL, &n);

        break;
    }

    DEBUGOUT(XdbDebug(__FILE__, NULL,
             "XmeDrawShadows(x = %d, y = %d, w = %d, h = %d, s = %d, t = %d)\n",
                      x, y, width, height, shadowThickness, shadowType));

    if (shadowType == XmNO_LINE)
    {
        XClearArea(display,
                   win,
                   x, y,
                   shadowThickness ? shadowThickness : 1, height,
                   False);
        XClearArea(display,
                   win,
                   x + width - shadowThickness, y,
                   shadowThickness ? shadowThickness : 1, height,
                   False);
        XClearArea(display,
                   win,
                   x, y,
                   width, shadowThickness ? shadowThickness : 1,
                   False);
        XClearArea(display,
                   win,
                   x, y + height - shadowThickness,
                   width, shadowThickness ? shadowThickness : 1,
                   False);
        return;
    }

    if (shadowType == XmSHADOW_IN || shadowType == XmSHADOW_OUT)
    {

        for (i = 0; i < shadowThickness; i++)
        {
            /*
             * draw the vertical lines
             */
            XFillRectangle(display,
                           win,
                           topGC,
                           x + i, y,
                           1, height - i);

            XFillRectangle(display,
                           win,
                           bottomGC,
                           x + width - i - 1, y + i + 1,
                           1, height - i - 1);

            /*
             * draw the horizontal lines
             */
            XFillRectangle(display,
                           win,
                           topGC,
                           x, y + i,
                           width - i, 1);

            XFillRectangle(display,
                           win,
                           bottomGC,
                           x + i + 1, y + height - i - 1,
                           width - i - 1, 1);
        }
    }
    else
    {                           /* SHADOW_ETCHED_IN and SHADOW_ETCHED_OUT */

        for (i = 0; i < (shadowThickness + 1) / 2; i++)
        {
            /*
             * draw the vertical lines
             */
            XFillRectangle(display,
                           win,
                           topGC,
                           x + i, y,
                           1, height - i);

            XFillRectangle(display,
                           win,
                           bottomGC,
                           x + width - i - 1, y + i + 1,
                           1, height - i - 1);

            /*
             * draw the horizontal lines
             */
            XFillRectangle(display,
                           win,
                           topGC,
                           x, y + i,
                           width - i, 1);

            XFillRectangle(display,
                           win,
                           bottomGC,
                           x + i + 1, y + height - i - 1,
                           width - i - 1, 1);
        }

        for (; i < shadowThickness; i++)
        {
            /*
             * draw the vertical lines
             */
            XFillRectangle(display,
                           win,
                           bottomGC,
                           x + i, y + shadowThickness / 2,
                           1, height - i - shadowThickness / 2);

            XFillRectangle(display,
                           win,
                           topGC,
                           x + width - i - 1, y + i + 1,
                           1, height - i - 1 - shadowThickness / 2);

            /*
             * draw the horizontal lines
             */
            XFillRectangle(display,
                           win,
                           bottomGC,
                           x + shadowThickness / 2, y + i,
                           width - i - shadowThickness / 2, 1);

            XFillRectangle(display,
                           win,
                           topGC,
                           x + i + 1, y + height - i - 1,
                           width - i - 1 - shadowThickness / 2, 1);
        }
    }
}

/* Shadow */

/*
  FUNCTION: XmeDrawArrow
  SYNOPSIS: void XmeDrawArrow(Display *display, Window win, GC bottomGC, GC topGC, GC fillGC, Position x, Position y, Dimension width, Dimension height, Dimension shadowThickness, unsigned char direction)
  DESCRIPTION:
  This routine only draws equilateral trianlges with in the specified width
  and height.  It first draws the fill area and then the shadow over the
  fill area.

  If shadow thickness exceeds a value of two then it is set to two.  Shadow 
  thickness is always greater then or equal to zero due to type.
  M*tif 1.2 can handle shadow thickness of zero or two.
  M*tif 2.0 can handle shadow thickness of 0,1 or 2.  This routine handles 
  the latter.

  If you are asking Why has this changed then read on:

  To determine the combobox drawing alg for the arrow button this routine
  needed to be fixed first.  This routine was drawing things too big and
  incorrectly.  This was effecting my calculations for the line width
  and centering of the arrow in the combobox. (pgw@ma.ultranet.com)

  BTW, this routine is too big and complicated.  This routine does exactly
  what the M*tif version 2.0 does down to the pixel level.  If not then report
  the bug. 

  To Do - condense common code blocks.
  END:
*/
void
XmeDrawArrow(Display *display,
	     Window win,
	     GC bottomGC,
	     GC topGC,
	     GC fillGC,
	     Position x, Position y,
	     Dimension width, Dimension height,
	     Dimension shadowThickness,
	     unsigned char direction)
{
    /* 
       REMARK: 
       Notice the parameters bottomGC and topGC are reversed in M*tif 2.0. 
       Please report to the mailing list if this has been fixed in a LATER
       release and indicate the version it is fixed in.
       END:
    */

    XRectangle *fill;   /* fill area */
    XRectangle *bottom; /* bottom shadow */
    XRectangle *top;    /* top shadow */
    int offsetX, offsetY;
    int arrowSize, isOdd;
    int i=0,j=0,k=0;
    /* 
       The define below is a heuristic.  Adjust as needed to avoid memory 
       fragmentation.  Otherwise change the code to use a static pointer 
       to reallocated memory as needed but would static pointers be thread safe?
     */  
#define XME_DRAW_ARROW_INTERNAL_SIZE 20
    XRectangle _internal_fill[XME_DRAW_ARROW_INTERNAL_SIZE];
    XRectangle _internal_top[XME_DRAW_ARROW_INTERNAL_SIZE];
    XRectangle _internal_bottom[XME_DRAW_ARROW_INTERNAL_SIZE];
    int isBig, allocSize;

    /* shadow thickness must be <= 2, its always >= 0 due to type. */
    if (shadowThickness>2)
    {
        shadowThickness = 2;
    }

    /* determine size */
    arrowSize = width;
    if (width > height)
    {
        arrowSize = height;
    }

    /* Prevent the for loops below from overrunning */
    if (width == 0 || height == 0)
	return;

    /* determine if odd */
    isOdd = arrowSize%2; 
 
    /* if odd round down to get even number */
    if (isOdd)
    {
        arrowSize = (arrowSize / 2) * 2;
    }

    /* determine offsets to center arrow */
    offsetX = offsetY = 0;
    if ((width - arrowSize) > 0)
    {
        offsetX = (width - arrowSize)/2;
    }

    if ((height - arrowSize) > 0)
    {
        offsetY = (height - arrowSize)/2;
    }

    /* if originally odd increment by 1 */
    if (isOdd)
    {
        arrowSize++;
    }

    /* misc calcs */
    x++;
    y++;

    /*
     * Things could go wrong badly here ;-(
     * Again, for loops below would overflow. This fixes an xmgr bug.
     */
    arrowSize-=2;
    if (arrowSize < 0)
	return;

    fill = _internal_fill;
    bottom = _internal_bottom;
    top = _internal_top;

    /* BTW, adding 4 should make things safe should probably put some
       asserts in here just to be sure. */
    allocSize = (arrowSize/2)+4;
    isBig = allocSize > XME_DRAW_ARROW_INTERNAL_SIZE;  

    /* allocate space if arrow is too big for internal array */
    if (isBig) 
    {
        fill = (XRectangle *) XtMalloc(sizeof(XRectangle)*allocSize);
        if(shadowThickness)
        {
            top = (XRectangle *) XtMalloc(sizeof(XRectangle)*allocSize);
            bottom = (XRectangle *) XtMalloc(sizeof(XRectangle)*allocSize);
        }
    }

    /* Draw arrow */
    switch (direction)
    {
    case XmARROW_UP:
        /* bottom up */
        fill[0].x = x + offsetX;
        fill[0].y = y + offsetY + arrowSize - (2 + isOdd);
        fill[0].width = arrowSize;
        fill[0].height = 2;

        for (i=1;(fill[i-1].width-2)>0;i++)
        {
            fill[i].x = fill[i-1].x + 1;
            fill[i].y = fill[i-1].y - fill[i-1].height;
            fill[i].width = fill[i-1].width - 2; 
            fill[i].height = 2;

#if 0
            /* keep this around for debugging purposes */
            printf("i=%d,x=%d,y=%d,width=%d,height=%d\n",
                   i,fill[i].x, fill[i].y, 
                   fill[i].width, fill[i].height);
#endif
        }

        /* special case */
        if (isOdd)
        {
            fill[i-1].y++;
            fill[i-1].height--;
        }
        break;
    case XmARROW_DOWN:
        /* top down */
        fill[0].x = x + offsetX;
        fill[0].y = y + offsetY;
        fill[0].width = arrowSize;
        fill[0].height = 2;

        for (i=1;(fill[i-1].width-2)>0;i++)
        {
            fill[i].x = fill[i-1].x + 1;
            fill[i].y = fill[i-1].y + fill[i-1].height;
            fill[i].width = fill[i-1].width - 2; 
            fill[i].height = 2;
        }

        /* special case */
        if (isOdd)
        {
            fill[i-1].height--;
        }
        else if (fill[i-1].width == 2)
        {
            i--;
        }
        break;
    case XmARROW_LEFT:
        /* right to left */
        fill[0].x = x + offsetX + arrowSize - 2;
        fill[0].y = y + offsetY - isOdd;
        fill[0].width = 2;
        fill[0].height = arrowSize;

        for (i=1;(fill[i-1].height-2)>0;i++)
        {
            fill[i].x = fill[i-1].x - fill[i-1].width;
            fill[i].y = fill[i-1].y + 1;
            fill[i].width = fill[i-1].width; 
            fill[i].height = fill[i-1].height - 2;
        }

        /* special case */
        if (isOdd)
        {
            fill[i-1].x++;
            fill[i-1].width--;
        }
        break;
    case XmARROW_RIGHT:
        /* left to right */
        fill[0].x = x + offsetX;
        fill[0].y = y + offsetY;
        fill[0].width = 2;
        fill[0].height = arrowSize;

        for (i=1;(fill[i-1].height-2)>0;i++)
        {
            fill[i].x = fill[i-1].x + fill[i-1].width;
            fill[i].y = fill[i-1].y + 1;
            fill[i].width = fill[i-1].width; 
            fill[i].height = fill[i-1].height - 2;
        }

        /* special case */
        if (isOdd)
        {
            fill[i-1].width = 1;
        }
        else if (fill[i-1].height == 2)
        {
            i--;
        }
        break;
    }

    if (shadowThickness)
    {
        /* Draw the bottom shadow */
        switch (direction)
        {
        case XmARROW_UP:
            bottom[0].x = fill[0].x;  
            bottom[0].y = fill[0].y;
            bottom[0].width = shadowThickness; 
            bottom[0].height = 2;

            for (k=1;k<i;k++)
            {
                bottom[k].x = fill[k].x;  
                bottom[k].y = fill[k].y;
                bottom[k].width = shadowThickness; 
                bottom[k].height = shadowThickness;
            }

            /* special case */
            if (isOdd)
            {
                bottom[k-1].width = 1;
                bottom[k-1].height = 1;
            }
            else
            {
                bottom[k-1].width = 2;
            }
            break;
        case XmARROW_DOWN:
            bottom[0].x = fill[0].x;
            bottom[0].y = fill[0].y;
            bottom[0].width = fill[0].width; 
            bottom[0].height = shadowThickness; 

            for (k=1;k-1<i;k++)
            {
                bottom[k].x = fill[k-1].x;
                bottom[k].y = fill[k-1].y + 2-shadowThickness;
                bottom[k].width = shadowThickness;
                bottom[k].height = shadowThickness;
            }
            if (isOdd)
            {
                k--;
            }
            else
            {
                bottom[k-1].width = 2;
            }
            break;
        case XmARROW_LEFT:
            bottom[0].x = fill[0].x;
            bottom[0].y = fill[0].y;
            bottom[0].width = 2; 
            bottom[0].height = shadowThickness;

            for (k=1;k<i;k++)
            {
                bottom[k].x = fill[k].x;
                bottom[k].y = fill[k].y;
                bottom[k].width = shadowThickness; 
                bottom[k].height = shadowThickness;
            }

            /* special case */
            if (isOdd)
            {
                bottom[k-1].width = 1;
                bottom[k-1].height = 1;
            }
            else
            {
                bottom[k-1].height = 2;
            }
            break;
        case XmARROW_RIGHT:
            bottom[0].x = fill[0].x;
            bottom[0].y = fill[0].y;
            bottom[0].width = shadowThickness;
            bottom[0].height = fill[0].height;

            for (k=1;k-1<i;k++)
            {
                bottom[k].x = fill[k-1].x + 2-shadowThickness;
                bottom[k].y = fill[k-1].y;
                bottom[k].width = shadowThickness;
                bottom[k].height = shadowThickness;
            }

            /* special case */
            if (isOdd)
            {
                k--;
            }
            else
            {
                bottom[k-1].height = 2;
            }
            break;
        }

        /* Draw the top shadow */
        switch (direction)
        {
        case XmARROW_UP:
            top[0].x = fill[0].x + 1;
            top[0].y = fill[0].y + 1;
            top[0].width = 1;
            top[0].height = 1;

            top[1].x = fill[0].x + shadowThickness;
            top[1].y = fill[0].y + (2-shadowThickness);
            top[1].width = arrowSize-shadowThickness;
            top[1].height = shadowThickness;

            for (j=2;(fill[j-2].width-2)>0;j++)
            {
                top[j].x = fill[j-2].x + fill[j-2].width 
                               - shadowThickness;
                top[j].y = fill[j-2].y;
                top[j].width = shadowThickness; 
                top[j].height = shadowThickness;
            }

            /* special cases */
            if (isOdd)
            {
                top[j-1].x += shadowThickness - 1;
                top[j-1].width = 1;
            }
            else /* even */
            {
                if (shadowThickness == 2)
                {
                    top[j].x = fill[j-2].x+1;
                    top[j].y = fill[j-2].y+1;
                    top[j].width = 1;
                    top[j].height = 1;
                    j++;
                }
            }
            break;
        case XmARROW_DOWN:
            top[0].x = fill[0].x + fill[0].width 
                           - shadowThickness;
            top[0].y = fill[0].y + 1;
            top[0].width = shadowThickness;
            top[0].height = 1; /* special case */

            for (j=1;(fill[j-1].width-2)>0;j++)
            {
                top[j].x = fill[j].x + fill[j].width 
                               - shadowThickness;
                top[j].y = fill[j].y + (2 - shadowThickness);
                top[j].width = shadowThickness; 
                top[j].height = shadowThickness;
            }

            if (isOdd) /* or fill[j-1].width == 1 */
            {
                top[j-1].x = fill[j-1].x;
                top[j-1].y = fill[j-1].y;
                top[j-1].width = 1; 
                top[j-1].height = 1;
            }
            else if (fill[j-1].width == 2)
            {
                j--;

                if (shadowThickness == 1)
                {
                    top[j-1].x--;
                    top[j-1].width = 2; 
                }
            }
            break;
        case XmARROW_LEFT:
            top[0].x = fill[0].x + 1;
            top[0].y = fill[0].y + 1;
            top[0].width = 1;
            top[0].height = 1;

            top[1].x = fill[0].x + (2-shadowThickness);
            top[1].y = fill[0].y + shadowThickness;
            top[1].width = shadowThickness;
            top[1].height = arrowSize-shadowThickness;

            for (j=2;(fill[j-2].height-2)>0;j++)
            {
                top[j].x = fill[j-2].x;
                top[j].y = fill[j-2].y + fill[j-2].height 
                               - shadowThickness;
                top[j].width = shadowThickness; 
                top[j].height = shadowThickness;
            }

            /* special cases */
            if (isOdd)
            {
                top[j-1].y += shadowThickness-1; 
                top[j-1].height = 1;
            }
            else /* even */
            {
                if (shadowThickness == 2)
                {
                    top[j].x = fill[j-2].x+1;
                    top[j].y = fill[j-2].y+1;
                    top[j].width = 1;
                    top[j].height = 1;
                    j++;
                }
            }
            break;
        case XmARROW_RIGHT:
            top[0].x = fill[0].x + 1;
            top[0].y = fill[0].y + fill[0].height
                           - shadowThickness;
            top[0].width = 1; /* special case */
            top[0].height = shadowThickness;

            for (j=1;(fill[j-1].height-2)>0;j++)
            {
                top[j].x = fill[j].x + (2-shadowThickness);
                top[j].y = fill[j].y + fill[j].height 
                               - shadowThickness;
                top[j].width = shadowThickness;
                top[j].height = shadowThickness;
            }
            /* special case */
            if (isOdd)
            {
                top[j-1].x = fill[j-1].x;
                top[j-1].y = fill[j-1].y;
                top[j-1].height = 1;
                top[j-1].width = 1;
            }
            else /* even */
            {
                j--;
 
                top[j-1].y = top[j-1].y - (2-shadowThickness); 
                top[j-1].height = 2; 
            }
            break;
        }
    }

    /* 
       The code above ASSUMES the arrays will be filled in the following
       order:
       1. fill
       2. bottom
       3. top
     */
    /* Fill in the arrow */
    XFillRectangles(display, win, fillGC, fill, i );
    if (shadowThickness)
    {
        XFillRectangles(display, win, bottomGC, bottom, k );
        XFillRectangles(display, win, topGC, top, j );
    }

    /* Free allocated memory */
    if (isBig)
    {
        XtFree((char *) fill);
        if(shadowThickness)
        {
            /* free the shadows */
            XtFree((char *) bottom);
            XtFree((char *) top);
        }
    }
}

/* Shadow */
void
XmeDrawDiamond(Display *display,
	       Window win,
	       GC bottomGC,
	       GC topGC,
	       GC selectGC,
	       Position x, Position y,
	       Dimension width, Dimension height,
	       Dimension shadowThickness,
	       Dimension fill)
{
    int i;
    int x_edge, y_edge;
    int ox, oy;
    XPoint pts[5];

    x_edge = width / 2;
    y_edge = height / 2;

    ox = x + x_edge;
    oy = y + y_edge;

    pts[0].x = (short)ox;
    pts[0].y = (short)oy - y_edge;
    pts[1].x = (short)ox + x_edge;
    pts[1].y = (short)oy;
    pts[2].x = (short)ox;
    pts[2].y = (short)oy + y_edge;
    pts[3].x = (short)ox - x_edge;
    pts[3].y = (short)oy;
    pts[4].x = (short)ox;
    pts[4].y = (short)oy - y_edge;

    if (fill)
    {
        XFillPolygon(display, win, selectGC, pts, 4, CoordModeOrigin, Complex);
    }

    for (i = 0; i < shadowThickness + 1; i++)
    {
        XDrawLine(display, win, topGC,
                  ox, oy - y_edge - i, ox + x_edge + i, oy);
        XDrawLine(display, win, topGC,
                  ox - x_edge - i, oy, ox, oy - y_edge - i);
    }

    for (i = 0; i < shadowThickness + 1; i++)
    {
        XDrawLine(display, win, bottomGC,
                  ox, oy + y_edge + i, ox - x_edge - i, oy);
        XDrawLine(display, win, bottomGC,
                  ox + x_edge + i, oy, ox, oy + y_edge + i);
    }
}

/* Shadow */
void
XmeDrawSeparator(Display *display,
		 Drawable win,
		 GC top_gc,
		 GC bottom_gc,
		 GC separator_GC,
		 Position wx,
		 Position wy,
		 Dimension wwidth,
		 Dimension wheight,
		 Dimension shadowThickness,
		 Dimension margin,
		 unsigned char orientation,
		 unsigned char separator_type)
{
    int x, y;
    int x1 = 0, y1 = 0, x2 = 0, y2 = 0, x3 = 0, y3 = 0, x4 = 0, y4 = 0;
    int width, height, i;

#ifdef  DO_FLUSH
    XFlush(display);
#endif

    if (orientation == XmHORIZONTAL)
    {
        x = wx + margin;
        y = wy + wheight / 2;
        width = wwidth - 2 * margin;
        if (separator_type == XmDOUBLE_LINE ||
            separator_type == XmDOUBLE_DASHED_LINE)
        {
            y2 = y1 = y;
            y3 = y4 = y + 1;
            x3 = x1 = x;
            x4 = x2 = x + width;
        }
        else if (separator_type == XmSHADOW_ETCHED_OUT ||
                 separator_type == XmSHADOW_ETCHED_IN ||
                 separator_type == XmSHADOW_ETCHED_IN_DASH ||
                 separator_type == XmSHADOW_ETCHED_OUT_DASH)
        {
            y2 = y1 = y - shadowThickness / 2;
            y3 = y4 = y;
            x3 = x1 = x;
            x4 = x2 = x + width;
        }
        else
        {
            x1 = x;
            y1 = y;
            x2 = x + width;
            y2 = y;
        }
    }
    else
    {
        x = wx + wwidth / 2;
        y = wy + margin;
        height = wheight - 2 * margin;
        y1 = y + height;
        x1 = x;
        if (separator_type == XmDOUBLE_LINE ||
            separator_type == XmDOUBLE_DASHED_LINE)
        {
            y3 = y1 = y;
            y2 = y4 = y + height;
            x2 = x1 = x;
            x4 = x3 = x + 1;
        }
        else if (separator_type == XmSHADOW_ETCHED_OUT ||
                 separator_type == XmSHADOW_ETCHED_IN ||
                 separator_type == XmSHADOW_ETCHED_IN_DASH ||
                 separator_type == XmSHADOW_ETCHED_OUT_DASH)
        {
            y3 = y1 = y;
            y2 = y4 = y + height;
            x2 = x1 = x - shadowThickness / 2;
            x4 = x3 = x;
        }
        else
        {
            x1 = x;
            y1 = y;
            x2 = x;
            y2 = y + height;
        }
    }

    switch (separator_type)
    {
    case XmSINGLE_LINE:
        XDrawLine(display, win, separator_GC, x1, y1, x2, y2);
        break;

    case XmSINGLE_DASHED_LINE:
        XDrawLine(display, win, separator_GC, x1, y1, x2, y2);
        break;

    case XmDOUBLE_LINE:
        XDrawLine(display, win, separator_GC, x1, y1, x2, y2);
        XDrawLine(display, win, separator_GC, x3, y3, x4, y4);
        break;

    case XmDOUBLE_DASHED_LINE:
        XDrawLine(display, win, separator_GC, x1, y1, x2, y2);
        XDrawLine(display, win, separator_GC, x3, y3, x4, y4);
        break;


    case XmSHADOW_ETCHED_IN:
        if (orientation == XmVERTICAL)
        {
            for (i = 0; i < shadowThickness / 2; i++)
            {
                XDrawLine(display, win, bottom_gc,
                          x1 + i, y1 + (shadowThickness / 2 - i - 1),
                          x2 + i, y2 - (shadowThickness / 2 - i - 1));
            }
            for (i = 0; i < shadowThickness / 2; i++)
            {
                XDrawLine(display, win, top_gc,
                          x3 + i, y3 + i,
                          x4 + i, y4 - i);
            }
        }
        else
        {
            for (i = 0; i < shadowThickness / 2; i++)
            {
                XDrawLine(display, win, bottom_gc,
                          x1 + (shadowThickness / 2 - i - 1), y1 + i,
                          x2 - (shadowThickness / 2 - i - 1), y2 + i);
            }
            for (i = 0; i < shadowThickness / 2; i++)
            {
                XDrawLine(display, win, top_gc,
                          x3 + i, y3 + i,
                          x4 - i, y4 + i);
            }
        }
        break;

    case XmSHADOW_ETCHED_OUT:
        if (orientation == XmVERTICAL)
        {
            for (i = 0; i < shadowThickness / 2; i++)
                XDrawLine(display, win, top_gc,
                          x1 + i, y1 + (shadowThickness / 2 - i - 1),
                          x2 + i, y2 - (shadowThickness / 2 - i - 1));
            for (i = 0; i < shadowThickness / 2; i++)
                XDrawLine(display, win, bottom_gc,
                          x3 + i, y3 + i,
                          x4 + i, y4 - i);
        }
        else
        {
            for (i = 0; i < shadowThickness / 2; i++)
                XDrawLine(display, win, top_gc,
                          x1 + (shadowThickness / 2 - i - 1), y1 + i,
                          x2 - (shadowThickness / 2 - i - 1), y2 + i);
            for (i = 0; i < shadowThickness / 2; i++)
                XDrawLine(display, win, bottom_gc,
                          x3 + i, y3 + i,
                          x4 - i, y4 + i);
        }
        break;

    case XmSHADOW_ETCHED_IN_DASH:
        XSetLineAttributes(display, top_gc, 0, LineDoubleDash,
                           CapButt, JoinMiter);
        XSetLineAttributes(display, bottom_gc, 0, LineDoubleDash,
                           CapButt, JoinMiter);
        if (orientation == XmVERTICAL)
        {
            for (i = 0; i < shadowThickness / 2; i++)
            {
                XDrawLine(display, win, bottom_gc,
                          x1 + i, y1 + (shadowThickness / 2 - i - 1),
                          x2 + i, y2 - (shadowThickness / 2 - i - 1));
            }
            for (i = 0; i < shadowThickness / 2; i++)
            {
                XDrawLine(display, win, top_gc,
                          x3 + i, y3 + i,
                          x4 + i, y4 - i);
            }
        }
        else
        {
            for (i = 0; i < shadowThickness / 2; i++)
            {
                XDrawLine(display, win, bottom_gc,
                          x1 + (shadowThickness / 2 - i - 1), y1 + i,
                          x2 - (shadowThickness / 2 - i - 1), y2 + i);
            }
            for (i = 0; i < shadowThickness / 2; i++)
            {
                XDrawLine(display, win, top_gc,
                          x3 + i, y3 + i,
                          x4 - i, y4 + i);
            }
        }
        break;

    case XmSHADOW_ETCHED_OUT_DASH:
        if (orientation == XmVERTICAL)
        {
            for (i = 0; i < shadowThickness / 2; i++)
                XDrawLine(display, win, top_gc,
                          x1 + i, y1 + (shadowThickness / 2 - i - 1),
                          x2 + i, y2 - (shadowThickness / 2 - i - 1));
            for (i = 0; i < shadowThickness / 2; i++)
                XDrawLine(display, win, bottom_gc,
                          x3 + i, y3 + i,
                          x4 + i, y4 - i);
        }
        else
        {
            for (i = 0; i < shadowThickness / 2; i++)
                XDrawLine(display, win, top_gc,
                          x1 + (shadowThickness / 2 - i - 1), y1 + i,
                          x2 - (shadowThickness / 2 - i - 1), y2 + i);
            for (i = 0; i < shadowThickness / 2; i++)
                XDrawLine(display, win, bottom_gc,
                          x3 + i, y3 + i,
                          x4 - i, y4 + i);
        }
        break;

    case XmNO_LINE:
        break;

    default:
        XDrawLine(display, win, separator_GC, x, y, x1, y1);
        break;
    }
}

/* Shadow */
void
XmeDrawHighlight(Display *display,
		 Drawable d,
		 GC gc,
		 Position x,
		 Position y,
		 Dimension width,
		 Dimension height,
		 Dimension highlight_thick)
{
    _XmDrawHighlight(display, d, gc, x, y, width, height,
		     highlight_thick, LineSolid);
}

