Blame lib/Xm/DrArrow.c

Packit b099d7
/* $XConsortium: DrArrow.c /main/6 1995/10/25 19:59:56 cde-sun $ */
Packit b099d7
/*
Packit b099d7
 * Motif
Packit b099d7
 *
Packit b099d7
 * Copyright (c) 1987-2012, The Open Group. All rights reserved.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are free software; you can
Packit b099d7
 * redistribute them and/or modify them under the terms of the GNU
Packit b099d7
 * Lesser General Public License as published by the Free Software
Packit b099d7
 * Foundation; either version 2 of the License, or (at your option)
Packit b099d7
 * any later version.
Packit b099d7
 *
Packit b099d7
 * These libraries and programs are distributed in the hope that
Packit b099d7
 * they will be useful, but WITHOUT ANY WARRANTY; without even the
Packit b099d7
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
Packit b099d7
 * PURPOSE. See the GNU Lesser General Public License for more
Packit b099d7
 * details.
Packit b099d7
 *
Packit b099d7
 * You should have received a copy of the GNU Lesser General Public
Packit b099d7
 * License along with these librararies and programs; if not, write
Packit b099d7
 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
Packit b099d7
 * Floor, Boston, MA 02110-1301 USA
Packit b099d7
 * 
Packit b099d7
 */
Packit b099d7
/*
Packit b099d7
 * HISTORY
Packit b099d7
 */
Packit b099d7
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
#include "XmI.h"
Packit b099d7
#include <Xm/DrawP.h>
Packit b099d7
Packit b099d7
Packit b099d7
/****************************XmeDrawArrow**********************************/
Packit b099d7
void XmeDrawArrow(Display *display, Drawable d, 
Packit b099d7
                  GC top_gc, GC bot_gc, GC cent_gc, 
Packit b099d7
#if NeedWidePrototypes
Packit b099d7
                  int x, int y, 
Packit b099d7
                  int width, int height, int shadow_thick, 
Packit b099d7
                  unsigned int direction)
Packit b099d7
#else
Packit b099d7
                  Position x, Position y, 
Packit b099d7
                  Dimension width, Dimension height, Dimension shadow_thick, 
Packit b099d7
                  unsigned char direction)
Packit b099d7
#endif /* NeedWidePrototypes */
Packit b099d7
{
Packit b099d7
   /* cent_gc might be NULL, which means don't draw anything on the center,
Packit b099d7
      but if shadow_thick is 1, then center is not NULL, see in ArrowB */
Packit b099d7
   /* in the current implementation, on shadow_thick = 2, 1 or 0 supported */
Packit b099d7
Packit b099d7
   static unsigned int allocated = 0;
Packit b099d7
   static XRectangle * top  = NULL;
Packit b099d7
   static XRectangle * cent = NULL;
Packit b099d7
   static XRectangle * bot  = NULL;
Packit b099d7
   XRectangle * rect_tmp;
Packit b099d7
   int size, xOffset = 0, yOffset = 0, wwidth, start;
Packit b099d7
   register int temp, yy, i, h, w;
Packit b099d7
   short t = 0 , b = 0 , c = 0 ;
Packit b099d7
   XtAppContext app;
Packit b099d7
Packit b099d7
   if (!d) return ;
Packit b099d7
Packit b099d7
   app = XtDisplayToApplicationContext(display);
Packit b099d7
   _XmAppLock(app);
Packit b099d7
 
Packit b099d7
   /*  Get the size and the position and allocate the rectangle lists  */
Packit b099d7
Packit b099d7
   if (width > height) {
Packit b099d7
      size = height - 2;
Packit b099d7
      xOffset = (width - height) / 2;
Packit b099d7
   } else {
Packit b099d7
      size = width - 2 ;
Packit b099d7
      yOffset = (height - width) / 2;
Packit b099d7
   }
Packit b099d7
   if (size < 1) { _XmAppUnlock(app); return; }
Packit b099d7
   if (allocated < size) {
Packit b099d7
      _XmProcessLock();
Packit b099d7
      top  = (XRectangle *) XtRealloc ((char*)top, 
Packit b099d7
                                       sizeof (XRectangle) * (size/2+6));
Packit b099d7
      cent = (XRectangle *) XtRealloc ((char*)cent, 
Packit b099d7
                                       sizeof (XRectangle) * (size/2+6));
Packit b099d7
      bot  = (XRectangle *) XtRealloc ((char*)bot, 
Packit b099d7
                                       sizeof (XRectangle) * (size/2+6));
Packit b099d7
      allocated = size;
Packit b099d7
      _XmProcessUnlock();
Packit b099d7
   }
Packit b099d7
Packit b099d7
#define SWAP(x,y) temp = x ; x = y; y = temp
Packit b099d7
Packit b099d7
   if (direction == XmARROW_RIGHT || direction == XmARROW_LEFT) {
Packit b099d7
      SWAP(xOffset,yOffset) ;
Packit b099d7
   }
Packit b099d7
Packit b099d7
   /*  Set up a loop to generate the segments.  */
Packit b099d7
Packit b099d7
   wwidth = size;
Packit b099d7
   yy = size - 1 + yOffset;
Packit b099d7
   start = 1 + xOffset;
Packit b099d7
Packit b099d7
   _XmProcessLock();
Packit b099d7
   while (wwidth > 0) {
Packit b099d7
       if (wwidth == 1) {
Packit b099d7
           top[t].x = start; top[t].y = yy + 1;
Packit b099d7
           top[t].width = 1; top[t].height = 1;
Packit b099d7
           t++;
Packit b099d7
       }
Packit b099d7
       else if (wwidth == 2) {
Packit b099d7
           if (size == 2 || (direction == XmARROW_UP || 
Packit b099d7
                             direction == XmARROW_LEFT)) {
Packit b099d7
               top[t].x = start; top[t].y = yy;
Packit b099d7
               top[t].width = 2; top[t].height = 1;
Packit b099d7
               t++;
Packit b099d7
               top[t].x = start; top[t].y = yy + 1;
Packit b099d7
               top[t].width = 1; top[t].height = 1;
Packit b099d7
               t++;
Packit b099d7
               bot[b].x = start + 1; bot[b].y = yy + 1;
Packit b099d7
               bot[b].width = 1; bot[b].height = 1;
Packit b099d7
               b++;
Packit b099d7
           }
Packit b099d7
       }
Packit b099d7
       else {
Packit b099d7
           if (start == 1 + xOffset)
Packit b099d7
               {
Packit b099d7
                   if (direction == XmARROW_UP || direction == XmARROW_LEFT) {
Packit b099d7
                       top[t].x = start; top[t].y = yy;
Packit b099d7
                       top[t].width = 2; top[t].height = 1;
Packit b099d7
                       t++;
Packit b099d7
                       top[t].x = start; top[t].y = yy + 1;
Packit b099d7
                       top[t].width = 1; top[t].height = 1;
Packit b099d7
                       t++;
Packit b099d7
                       bot[b].x = start + 1; bot[b].y = yy + 1;
Packit b099d7
                       bot[b].width = 1; bot[b].height = 1;
Packit b099d7
                       b++;
Packit b099d7
                       bot[b].x = start + 2; bot[b].y = yy;
Packit b099d7
                       bot[b].width = wwidth - 2; bot[b].height = 2;
Packit b099d7
                       b++;
Packit b099d7
                   }
Packit b099d7
                   else {
Packit b099d7
                       top[t].x = start; top[t].y = yy;
Packit b099d7
                       top[t].width = 2; top[t].height = 1;
Packit b099d7
                       t++;
Packit b099d7
                       bot[b].x = start; bot[b].y = yy + 1;
Packit b099d7
                       bot[b].width = 2; bot[b].height = 1;
Packit b099d7
                       b++;
Packit b099d7
                       bot[b].x = start + 2; bot[b].y = yy;
Packit b099d7
                       bot[b].width = wwidth - 2; bot[b].height = 2;
Packit b099d7
                       b++;
Packit b099d7
                   }
Packit b099d7
               }
Packit b099d7
           else {
Packit b099d7
               top[t].x = start; top[t].y = yy;
Packit b099d7
               top[t].width = 2; top[t].height = 2;
Packit b099d7
               t++;
Packit b099d7
               bot[b].x = start + wwidth - 2; bot[b].y = yy;
Packit b099d7
               bot[b].width = 2; bot[b].height = 2;
Packit b099d7
               if (wwidth == 3) {
Packit b099d7
                   bot[b].width = 1;
Packit b099d7
                   bot[b].x += 1;
Packit b099d7
               }
Packit b099d7
               b++;
Packit b099d7
               if (wwidth > 4) {
Packit b099d7
                   cent[c].x = start + 2; cent[c].y = yy;
Packit b099d7
                   cent[c].width = wwidth - 4; cent[c].height = 2;
Packit b099d7
                   c++;
Packit b099d7
               }
Packit b099d7
           }
Packit b099d7
       }
Packit b099d7
       start++;
Packit b099d7
       wwidth -= 2;
Packit b099d7
       yy -= 2;
Packit b099d7
   }
Packit b099d7
Packit b099d7
   if (direction == XmARROW_DOWN || direction == XmARROW_RIGHT) {
Packit b099d7
       rect_tmp = top; top = bot; bot = rect_tmp;
Packit b099d7
       SWAP(t, b);
Packit b099d7
   }
Packit b099d7
Packit b099d7
  
Packit b099d7
   /*  Transform the "up" pointing arrow to the correct direction  */
Packit b099d7
Packit b099d7
   switch (direction) {
Packit b099d7
   case XmARROW_LEFT:
Packit b099d7
       i = -1;
Packit b099d7
       do {
Packit b099d7
           i++;
Packit b099d7
           if (i < t) {
Packit b099d7
               SWAP(top[i].y, top[i].x);
Packit b099d7
               SWAP(top[i].width, top[i].height);
Packit b099d7
           }             
Packit b099d7
           if (i < b) {
Packit b099d7
               SWAP(bot[i].y, bot[i].x);
Packit b099d7
               SWAP(bot[i].width, bot[i].height);
Packit b099d7
           }             
Packit b099d7
           if (i < c) {
Packit b099d7
               SWAP(cent[i].y, cent[i].x);
Packit b099d7
               SWAP(cent[i].width, cent[i].height);
Packit b099d7
           }             
Packit b099d7
       } while (i < t || i < b || i < c);
Packit b099d7
       break;
Packit b099d7
Packit b099d7
   case XmARROW_RIGHT: 
Packit b099d7
       h = height - 2;
Packit b099d7
       w = width - 2;
Packit b099d7
       i = -1;
Packit b099d7
       do {
Packit b099d7
           i++;
Packit b099d7
           if (i < t) {
Packit b099d7
               SWAP(top[i].y, top[i].x); 
Packit b099d7
               SWAP(top[i].width, top[i].height);
Packit b099d7
               top[i].x = w - top[i].x - top[i].width + 2;
Packit b099d7
               top[i].y = h - top[i].y - top[i].height + 2;
Packit b099d7
           }             
Packit b099d7
           if (i < b) {
Packit b099d7
               SWAP(bot[i].y, bot[i].x); 
Packit b099d7
               SWAP(bot[i].width, bot[i].height);
Packit b099d7
               bot[i].x = w - bot[i].x - bot[i].width + 2;
Packit b099d7
               bot[i].y = h - bot[i].y - bot[i].height + 2;
Packit b099d7
           }             
Packit b099d7
           if (i < c) {
Packit b099d7
               SWAP(cent[i].y, cent[i].x); 
Packit b099d7
               SWAP(cent[i].width, cent[i].height);
Packit b099d7
               cent[i].x = w - cent[i].x - cent[i].width + 2;
Packit b099d7
               cent[i].y = h - cent[i].y - cent[i].height + 2;
Packit b099d7
           }
Packit b099d7
       } while (i < t || i < b || i < c);
Packit b099d7
       break;
Packit b099d7
Packit b099d7
   case XmARROW_DOWN:
Packit b099d7
       w = width - 2;
Packit b099d7
       h = height - 2;
Packit b099d7
       i = -1;
Packit b099d7
       do {
Packit b099d7
           i++;
Packit b099d7
           if (i < t) {
Packit b099d7
               top[i].x = w - top[i].x - top[i].width + 2;
Packit b099d7
               top[i].y = h - top[i].y - top[i].height + 2;
Packit b099d7
           }
Packit b099d7
           if (i < b) {
Packit b099d7
               bot[i].x = w - bot[i].x - bot[i].width + 2;
Packit b099d7
               bot[i].y = h - bot[i].y - bot[i].height + 2;
Packit b099d7
           }
Packit b099d7
           if (i < c) {
Packit b099d7
               cent[i].x = w - cent[i].x - cent[i].width + 2;
Packit b099d7
               cent[i].y = h - cent[i].y - cent[i].height + 2;
Packit b099d7
           }
Packit b099d7
       } while (i < t || i < b || i < c);
Packit b099d7
       break;
Packit b099d7
   }
Packit b099d7
Packit b099d7
   if (x != 0 || y != 0) {
Packit b099d7
       for (i = 0; i < t; i++) {
Packit b099d7
           top[i].x += x;
Packit b099d7
           top[i].y += y;
Packit b099d7
       }
Packit b099d7
       for (i = 0; i < c; i++) {
Packit b099d7
           cent[i].x += x;
Packit b099d7
           cent[i].y += y;
Packit b099d7
       }
Packit b099d7
       for (i = 0; i < b; i++) {
Packit b099d7
           bot[i].x += x;
Packit b099d7
           bot[i].y += y;
Packit b099d7
       }
Packit b099d7
   } 
Packit b099d7
Packit b099d7
   if (shadow_thick) {  /* 1 or 2 shadow thickness: always draw 
Packit b099d7
			   2 thickness at that point, we'll correct it
Packit b099d7
			   later */
Packit b099d7
       XFillRectangles (display, d, top_gc, top, t);
Packit b099d7
       XFillRectangles (display, d, bot_gc, bot, b);
Packit b099d7
   } else {
Packit b099d7
       /* handle the case where arrow shadow_thickness = 0, which give
Packit b099d7
          a flat arrow: draw the shadow area with the center color */
Packit b099d7
       if (cent_gc) {
Packit b099d7
           XFillRectangles (display, d, cent_gc, top, t);
Packit b099d7
           XFillRectangles (display, d, cent_gc, bot, b);
Packit b099d7
       }
Packit b099d7
   } 
Packit b099d7
Packit b099d7
   if (shadow_thick == 1) {
Packit b099d7
       /* we already drawn the shadow of 2, now let's draw a
Packit b099d7
	  bigger center area: ask for a smaller arrow with
Packit b099d7
	  flat look */
Packit b099d7
       XmeDrawArrow(display, d, top_gc, bot_gc, cent_gc, 
Packit b099d7
		    x+1, y+1, width-2, height-2, 0, direction) ;
Packit b099d7
   } else
Packit b099d7
   if (cent_gc) XFillRectangles (display, d, cent_gc, cent, c);
Packit b099d7
   _XmProcessUnlock();
Packit b099d7
   _XmAppUnlock(app);
Packit b099d7
}
Packit b099d7