/* $XConsortium: DrArrow.c /main/6 1995/10/25 19:59:56 cde-sun $ */ /* * @OPENGROUP_COPYRIGHT@ * COPYRIGHT NOTICE * Copyright (c) 1990, 1991, 1992, 1993 Open Software Foundation, Inc. * Copyright (c) 1996, 1997, 1998, 1999, 2000 The Open Group * ALL RIGHTS RESERVED (MOTIF). See the file named COPYRIGHT.MOTIF for * the full copyright text. * * This software is subject to an open license. It may only be * used on, with or for operating systems which are themselves open * source systems. You must contact The Open Group for a license * allowing distribution and sublicensing of this software on, with, * or for operating systems which are not Open Source programs. * * See http://www.opengroup.org/openmotif/license for full * details of the license agreement. Any use, reproduction, or * distribution of the program constitutes recipient's acceptance of * this agreement. * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS * PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY * WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY * OR FITNESS FOR A PARTICULAR PURPOSE * * EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT * NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE * EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGES. * */ /* * HISTORY */ #include "XmI.h" #include /****************************XmeDrawArrow**********************************/ void XmeDrawArrow(Display *display, Drawable d, GC top_gc, GC bot_gc, GC cent_gc, #if NeedWidePrototypes int x, int y, int width, int height, int shadow_thick, unsigned int direction) #else Position x, Position y, Dimension width, Dimension height, Dimension shadow_thick, unsigned char direction) #endif /* NeedWidePrototypes */ { /* cent_gc might be NULL, which means don't draw anything on the center, but if shadow_thick is 1, then center is not NULL, see in ArrowB */ /* in the current implementation, on shadow_thick = 2, 1 or 0 supported */ static unsigned int allocated = 0; static XRectangle * top = NULL; static XRectangle * cent = NULL; static XRectangle * bot = NULL; XRectangle * rect_tmp; int size, xOffset = 0, yOffset = 0, wwidth, start; register int temp, yy, i, h, w; short t = 0 , b = 0 , c = 0 ; XtAppContext app; if (!d) return ; app = XtDisplayToApplicationContext(display); _XmAppLock(app); /* Get the size and the position and allocate the rectangle lists */ if (width > height) { size = height - 2; xOffset = (width - height) / 2; } else { size = width - 2 ; yOffset = (height - width) / 2; } if (size < 1) { _XmAppUnlock(app); return; } if (allocated < size) { _XmProcessLock(); top = (XRectangle *) XtRealloc ((char*)top, sizeof (XRectangle) * (size/2+6)); cent = (XRectangle *) XtRealloc ((char*)cent, sizeof (XRectangle) * (size/2+6)); bot = (XRectangle *) XtRealloc ((char*)bot, sizeof (XRectangle) * (size/2+6)); allocated = size; _XmProcessUnlock(); } #define SWAP(x,y) temp = x ; x = y; y = temp if (direction == XmARROW_RIGHT || direction == XmARROW_LEFT) { SWAP(xOffset,yOffset) ; } /* Set up a loop to generate the segments. */ wwidth = size; yy = size - 1 + yOffset; start = 1 + xOffset; _XmProcessLock(); while (wwidth > 0) { if (wwidth == 1) { top[t].x = start; top[t].y = yy + 1; top[t].width = 1; top[t].height = 1; t++; } else if (wwidth == 2) { if (size == 2 || (direction == XmARROW_UP || direction == XmARROW_LEFT)) { top[t].x = start; top[t].y = yy; top[t].width = 2; top[t].height = 1; t++; top[t].x = start; top[t].y = yy + 1; top[t].width = 1; top[t].height = 1; t++; bot[b].x = start + 1; bot[b].y = yy + 1; bot[b].width = 1; bot[b].height = 1; b++; } } else { if (start == 1 + xOffset) { if (direction == XmARROW_UP || direction == XmARROW_LEFT) { top[t].x = start; top[t].y = yy; top[t].width = 2; top[t].height = 1; t++; top[t].x = start; top[t].y = yy + 1; top[t].width = 1; top[t].height = 1; t++; bot[b].x = start + 1; bot[b].y = yy + 1; bot[b].width = 1; bot[b].height = 1; b++; bot[b].x = start + 2; bot[b].y = yy; bot[b].width = wwidth - 2; bot[b].height = 2; b++; } else { top[t].x = start; top[t].y = yy; top[t].width = 2; top[t].height = 1; t++; bot[b].x = start; bot[b].y = yy + 1; bot[b].width = 2; bot[b].height = 1; b++; bot[b].x = start + 2; bot[b].y = yy; bot[b].width = wwidth - 2; bot[b].height = 2; b++; } } else { top[t].x = start; top[t].y = yy; top[t].width = 2; top[t].height = 2; t++; bot[b].x = start + wwidth - 2; bot[b].y = yy; bot[b].width = 2; bot[b].height = 2; if (wwidth == 3) { bot[b].width = 1; bot[b].x += 1; } b++; if (wwidth > 4) { cent[c].x = start + 2; cent[c].y = yy; cent[c].width = wwidth - 4; cent[c].height = 2; c++; } } } start++; wwidth -= 2; yy -= 2; } if (direction == XmARROW_DOWN || direction == XmARROW_RIGHT) { rect_tmp = top; top = bot; bot = rect_tmp; SWAP(t, b); } /* Transform the "up" pointing arrow to the correct direction */ switch (direction) { case XmARROW_LEFT: i = -1; do { i++; if (i < t) { SWAP(top[i].y, top[i].x); SWAP(top[i].width, top[i].height); } if (i < b) { SWAP(bot[i].y, bot[i].x); SWAP(bot[i].width, bot[i].height); } if (i < c) { SWAP(cent[i].y, cent[i].x); SWAP(cent[i].width, cent[i].height); } } while (i < t || i < b || i < c); break; case XmARROW_RIGHT: h = height - 2; w = width - 2; i = -1; do { i++; if (i < t) { SWAP(top[i].y, top[i].x); SWAP(top[i].width, top[i].height); top[i].x = w - top[i].x - top[i].width + 2; top[i].y = h - top[i].y - top[i].height + 2; } if (i < b) { SWAP(bot[i].y, bot[i].x); SWAP(bot[i].width, bot[i].height); bot[i].x = w - bot[i].x - bot[i].width + 2; bot[i].y = h - bot[i].y - bot[i].height + 2; } if (i < c) { SWAP(cent[i].y, cent[i].x); SWAP(cent[i].width, cent[i].height); cent[i].x = w - cent[i].x - cent[i].width + 2; cent[i].y = h - cent[i].y - cent[i].height + 2; } } while (i < t || i < b || i < c); break; case XmARROW_DOWN: w = width - 2; h = height - 2; i = -1; do { i++; if (i < t) { top[i].x = w - top[i].x - top[i].width + 2; top[i].y = h - top[i].y - top[i].height + 2; } if (i < b) { bot[i].x = w - bot[i].x - bot[i].width + 2; bot[i].y = h - bot[i].y - bot[i].height + 2; } if (i < c) { cent[i].x = w - cent[i].x - cent[i].width + 2; cent[i].y = h - cent[i].y - cent[i].height + 2; } } while (i < t || i < b || i < c); break; } if (x != 0 || y != 0) { for (i = 0; i < t; i++) { top[i].x += x; top[i].y += y; } for (i = 0; i < c; i++) { cent[i].x += x; cent[i].y += y; } for (i = 0; i < b; i++) { bot[i].x += x; bot[i].y += y; } } if (shadow_thick) { /* 1 or 2 shadow thickness: always draw 2 thickness at that point, we'll correct it later */ XFillRectangles (display, d, top_gc, top, t); XFillRectangles (display, d, bot_gc, bot, b); } else { /* handle the case where arrow shadow_thickness = 0, which give a flat arrow: draw the shadow area with the center color */ if (cent_gc) { XFillRectangles (display, d, cent_gc, top, t); XFillRectangles (display, d, cent_gc, bot, b); } } if (shadow_thick == 1) { /* we already drawn the shadow of 2, now let's draw a bigger center area: ask for a smaller arrow with flat look */ XmeDrawArrow(display, d, top_gc, bot_gc, cent_gc, x+1, y+1, width-2, height-2, 0, direction) ; } else if (cent_gc) XFillRectangles (display, d, cent_gc, cent, c); _XmProcessUnlock(); _XmAppUnlock(app); }