















        Appendix B.  DDrraagg aanndd DDrroopp EExxaammppllee PPrrooggrraamm










































        May 9, 1992                                              B-1








        OSF/Motif Programmer's Guide


                    FFiigguurree BB--11..  Drag and Drop Demonstration































             The DDNNDDDDeemmoo program is a complex drag and drop
             application.  It uses many of the features covered in
             chapter 15.  The application uses both drag source and
             drop sites.

             The window consists of an array of 6 colors in the
             lower section, with an empty drawing area in the upper
             section.  The user can create a black box within the
             drawing area by pressing and holding the mouse button 1
             while moving the mouse until the desired size rectangle
             is outlined, then releasing the button.  There can be
             as many rectangles as desired and they can overlap each
             other.  A rectangle can be raised to the top by
             clicking mouse button 1 on it.

             The user can change the color of a particular rectangle
             by moving the pointer to one of the six color choices,
             pressing button 2, and moving the pointer to the
             rectangle. A palette in that color becomes the drag



        B-2                                              May 9, 1992








                                       Drag and Drop Example Program


             icon.  The state icon does not appear while the drag
             icon is in the lower section, shows as a slashed circle
             in the background of the upper section, and as a
             paintbrush in the rectangles.  When the mouse button is
             released to make a drop, the rectangle changes to the
             color chosen.  If the rectangle is overlapped by
             another, the whole rectangle is changed, but only the
             unobscured part is shown in the new color.

             The rectangles can be moved around the drawing area by
             pressing button 2 when the pointer is over the
             rectangle, holding it, and moving the mouse until the
             new location is reached.  If the rectangle is small
             enough, it is used to create a pixmap for the source
             drag icon, otherwise a similarly-shaped smaller pixmap
             is used for the source icon.

             The program demonstrates the following drag and drop
             features:

                +o Drag Source

                     - Establishes translations.

                     - Establishes custom drag source targets.

                     - Starts a drag and creates a drag context.

                     - Creates custom drag icons.

                     - Transfers information to the receiver (about
                       color or location)

                +o Drop Site

                     - Establishes simulated drop sites.

                     - Establishes custom drop site targets.

                     - Follows the progress of the drag with a
                       XXmmDDrraaggPPrroocc routine.

                     - Requests transfer of information from the
                       source (about color or location).

             The demonstration program actually consists of three
             files:

                +o DDNNDDDDeemmoo..hh contains header information, global
                  constants, and forward declarations of procedures.




        May 9, 1992                                              B-3








        OSF/Motif Programmer's Guide


                +o DDNNDDDDeemmoo..cc creates the windows and manages the drag
                  and drop functions.

                +o DDNNDDDDrraaww..cc does not have any drag and drop specific
                  code in it.  It manages creating, coloring, and
                  destroying the rectangles and bitmaps within the
                  window.



        B.1  DDNNDDDDeemmoo..hh



             /*
              *    file: DNDDemo.h
              *
              *      Header file for the program DNDDemo.
              */

             #include <stdio.h>
             #include <X11/Xatom.h>
             #include <X11/Intrinsic.h>
             #include <Xm/Xm.h>
             #include <Xm/AtomMgr.h>
             #include <Xm/MainW.h>
             #include <Xm/DrawingA.h>
             #include <Xm/SeparatoG.h>
             #include <Xm/Form.h>
             #include <Xm/RowColumn.h>
             #include <Xm/PushB.h>
             #include <Xm/MessageB.h>
             #include <Xm/DragDrop.h>
             #include <Xm/Screen.h>


             /* The following is used to layout the color labels */
             #define BOX_WIDTH       85
             #define BOX_HEIGHT      25
             #define BOX_X_OFFSET    95
             #define BOX_Y_OFFSET    35
             #define BOX_X_MARGIN    10
             #define BOX_Y_MARGIN    10

             /* The following are used in setting up the drag icons */
             #define ICON_WIDTH          32
             #define ICON_HEIGHT         32
             #define SMALL_ICON_WIDTH    16
             #define SMALL_ICON_HEIGHT   16
             #define ICON_X_HOT          0
             #define ICON_Y_HOT          0



        B-4                                              May 9, 1992








                                       Drag and Drop Example Program


             /* Some scales or text entry field could be added to change
              * this value */
             #define RECT_WIDTH  20
             #define RECT_HEIGHT 50

             /* The following defines could be setup as application resources */
             #define RECT_START_COLOR    "black"
             #define HIGHLIGHT_THICKNESS 3
             #define HIGHLIGHT_COLOR     "Black"   /* this is equivalent to
                                                      gray60 in the R5 rgb.txt */
             #define DRAW_AREA_BG_COLOR "white"
             #define DRAW_AREA_FG_COLOR "white"
             #define LABEL1_COLOR       "#ff5026"     /* a soft shade of red */
             #define LABEL2_COLOR    "orange"
             #define LABEL3_COLOR    "yellow"
             #define LABEL4_COLOR    "violet"
             #define LABEL5_COLOR    "#00C3ff"           /* a blue green color */
             #define LABEL6_COLOR    "green"

             #define VALID_CURSOR_FG_COLOR   "black"
             #define INVALID_CURSOR_FG_COLOR "maroon"
             #define NONE_CURSOR_FG_COLOR    "maroon"


             /*
              * This struct is used to contain information about each rectangle
              * to use in the dislay routines
              */
             typedef struct _RectStruct {
                 Position x;
                 Position y;
                 Dimension width;
                 Dimension height;
                 Pixel color;
                 Pixmap pixmap;   /* currently not in use */
             } RectStruct, *RectPtr;

             /* This struct is used to hold global application information */
             typedef struct _AppInfoRec {
                 GC rectGC;              /* graphic context used to draw the
                                            rectangles */
                 Pixel currentColor;     /* color that is currently in the GC */
                 RectPtr *rectDpyTable;  /* the rectangle display table */
                 int rectsAllocd;        /* keeps track of how much the above
                                            table has been alloc'd */
                 int numRects;           /* number of rects that are visible */
                 RectPtr highlightRect;  /* the current highlighted rectangle */
                 RectPtr clearRect;      /* the rectangle that is being moved */
                 Boolean doMove;         /* indicates that a move is being
                                            performed */
                 Boolean creatingRect;   /* indicates that a rect create is being



        May 9, 1992                                              B-5








        OSF/Motif Programmer's Guide


                                            performed */
                 unsigned char operation;/* indicates the drop help operation */
                 unsigned int maxCursorWidth;  /* the maximum allowable cursor
                                                  width */
                 unsigned int maxCursorHeight; /* the maximum allowable cursor
                                                  height */
                 Position rectX;
                 Position rectY;
                 Position rectX2;
                 Position rectY2;
             } AppInfoRec, *AppInfo;

             /*
              * This struct is used to pass information
              * from the dropProc to the transferProc
              */
             typedef struct _DropTransferRec {
                 Widget widget;
                 Position x;
                 Position y;
             } DropTransferRec, *DropTransfer;

             /*
              * This struct is used to pass information
              * from the rectangle dragStart proc to it's associated
              * callback procs.
              */
             typedef struct _DragConvertRec {
                 Widget widget;
                 RectPtr rect;
             } DragConvertRec, *DragConvertPtr;


             #ifdef _NO_PROTO

             extern void     InitializeAppInfo();
             extern void     StartRect();
             extern void     ExtendRect();
             extern void     EndRect();
             extern RectPtr  RectCreate();
             extern RectPtr  RectFind();
             extern void     RectSetColor();
             extern Pixel    RectGetColor();
             extern Pixmap   GetBitmapFromRect();
             extern void     RectHide();
             extern void     RectFree();
             extern void     RedrawRectangles();
             extern void     RectDrawStippled();
             extern void     RectHighlight();
             extern void     RectUnhighlight();
             extern void     RectSetPixmap();



        B-6                                              May 9, 1992








                                       Drag and Drop Example Program


             extern void     RectRegister();
             extern void     InitializeRectDpyTable();
             extern void     CreateLayout();
             extern void     CreateRectGC();
             extern Pixel    GetColor();
             extern void     ColorRect();

             #else

             extern void     InitializeAppInfo(void);
             extern void     StartRect(Widget, XEvent *, String *, Cardinal *);
             extern void     ExtendRect(Widget, XEvent *, String *, Cardinal *);
             extern void     EndRect(Widget, XEvent *, String *, Cardinal *);
             extern RectPtr  RectCreate(Position, Position, Dimension,
                                       Dimension, Pixel, Pixmap);
             extern RectPtr  RectFind(Position, Position);
             extern void     RectSetColor(RectPtr, Display *, Window, Pixel);
             extern Pixel    RectGetColor(RectPtr);
             extern Pixmap   GetBitmapFromRect(Widget, RectPtr, Pixel, Pixel,
                                               Dimension *, Dimension *);
             extern void     RectHide(Display *, Window, RectPtr);
             extern void     RectFree(RectPtr);
             extern void     RedrawRectangles(Widget);
             extern void     RectDrawStippled(Display *, Window, RectPtr);
             extern void     RectHighlight(Widget, RectPtr);
             extern void     RectUnhighlight(Widget);
             extern void     RectSetPixmap(RectPtr, Display *, Window, Pixmap);
             extern void     RectRegister(RectPtr, Position, Position);
             extern void     InitializeRectDpyTable(void);
             extern void     CreateLayout(void);
             extern void     CreateRectGC(void);
             extern Pixel    GetColor(char *);
             extern void     ColorRect(Widget, XEvent *, String *, Cardinal *);

             #endif    /* _NO_PROTO */


             /* The following character arrays hold the bits for the source and
              * state icons for both 32x32 and 16x16 drag icons.  The source is
              * a color palette icon and the state is a paint brush icon.
              */
             extern char SOURCE_ICON_BITS[];
             extern char SOURCE_ICON_MASK[];
             extern char STATE_ICON_BITS[];
             extern char STATE_ICON_MASK[];
             extern char INVALID_ICON_BITS[];
             extern char SMALL_SOURCE_ICON_BITS[];
             extern char SMALL_SOURCE_ICON_MASK[];
             extern char SMALL_STATE_ICON_BITS[];
             extern char SMALL_STATE_ICON_MASK[];
             extern char SMALL_INVALID_ICON_BITS[];



        May 9, 1992                                              B-7








        OSF/Motif Programmer's Guide


             /* The folowing character arrays are for use with the drop help
              * dialogs.  For internationalization, message catalogs should
              * replace these static declarations.
              */
             extern char HELP_MSG1[];
             extern char HELP_MSG2[];
             extern char HELP_MSG3[];
             extern char HELP_MSG4[];
             extern char HELP_MSG5[];


             /* Globals variables */
             extern AppInfo      appInfo;
             extern Widget       topLevel;
             extern Widget       drawingArea;
             extern Widget       helpDialog;
             extern Widget       helpLabel, helpMenu;
             extern XtAppContext appContext;



        B.2  DDNNDDDDeemmoo..cc



             /*
              *    file: DNDDemo.c
              *
              *      A demo program showing the basic Drag And Drop operations.
              */

             #include "DNDDemo.h"


             /*
              * The folowing character arrays are for use with the drop help
              * dialogs.  For internationalization, message catalogs should
              * replace these static declarations.
              */
             char HELP_MSG1[] =
             "This drop action will change the color\n\
             of the rectangle that the paint palette\n\
             icon is dropped on. To accept this drop\n\
             press the o.k. button, otherwise press\n\
             cancel";

             char HELP_MSG2[] =
             "This drop action will move the rectangle\n\
             to the new position.  To accept this drop\n\
             press the o.k. button, otherwise press\n\
             cancel";



        B-8                                              May 9, 1992








                                       Drag and Drop Example Program


             char HELP_MSG3[] =
             "This drop action will copy the rectangle\n\
             to the new position.  To accept this drop\n\
             press the o.k. button, otherwise press\n\
             cancel";

             char HELP_MSG4[] =
             "This drop action can either copy or\n\
             move the rectangle to the new position.\n\
             Select the operation that you desire.\n\
             In the future, use Ctrl with Btn2 to\n\
             perform copy operations.  The default\n\
             operation is move.  To accept this drop\n\
             press the o.k. button, otherwise press\n\
             cancel";

             char HELP_MSG5[] =
             "This drop action is at an Invalid drop\n\
             position.  Please cancel this drop \n\
             by pressing the cancel button.";


             /* Globals variables */
             Widget          topLevel;
             Widget          drawingArea;
             Widget          helpDialog = NULL;
             Widget          helpLabel, helpMenu;
             Widget          myDC;
             XtAppContext    appContext;


             /* This function creates the Drag Icon. */
             static Widget
             #ifdef _NO_PROTO
             GetDragIcon(w, icon, iconMask, width, height, background,
                         foreground)
             Widget w;
             Pixmap icon;
             Pixmap iconMask;
             Dimension width;
             Dimension height;
             Pixel background;
             Pixel foreground;
             #else
             GetDragIcon(Widget w, Pixmap icon, Pixmap iconMask, Dimension width,
             Dimension height, Pixel background, Pixel foreground)
             #endif /* _NO_PROTO */
             {

                 Widget  dragIcon;
                 Arg     args[10];



        May 9, 1992                                              B-9








        OSF/Motif Programmer's Guide


                 int     n = 0;

                 XtSetArg(args[n], XmNhotX, ICON_X_HOT); n++;
                 XtSetArg(args[n], XmNhotY, ICON_Y_HOT); n++;
                 XtSetArg(args[n], XmNwidth, width); n++;
                 XtSetArg(args[n], XmNheight, height); n++;
                 XtSetArg(args[n], XmNmaxWidth, appInfo->maxCursorWidth); n++;
                 XtSetArg(args[n], XmNmaxHeight, appInfo->maxCursorHeight); n++;
                 XtSetArg(args[n], XmNbackground, background); n++;
                 XtSetArg(args[n], XmNforeground, foreground); n++;
                 XtSetArg(args[n], XmNpixmap, icon); n++;
                 XtSetArg(args[n], XmNmask, iconMask); n++;
                 dragIcon = XmCreateDragIcon(w, "dragIcon", args, n);

                 return(dragIcon);

             }


             /* This function creates the bitmaps for the icon and the mask
              * and then calls GetDragIcon() to  create the drag icon.
              */
             static Widget
             #ifdef _NO_PROTO
             GetDragIconFromBits(w, bits, mask, width, height, background,
                                 foreground)
             Widget w;
             char *bits;
             char *mask;
             Dimension width;
             Dimension height;
             Pixel background;
             Pixel foreground;
             #else
             GetDragIconFromBits(Widget w, char *bits, char *mask,
                                 Dimension width, Dimension height,
                                 Pixel background, Pixel foreground)
             #endif /* _NO_PROTO */
             {

                 Pixmap     icon, iconMask;
                 Display    *display = XtDisplay(w);

                 icon = XCreateBitmapFromData(display,
                             DefaultRootWindow(display), bits, width, height);

                 iconMask = XCreateBitmapFromData(display,
                             DefaultRootWindow(display), mask, width, height);

                 return(GetDragIcon(w, icon, iconMask, width, height,
                                    background, foreground));



        B-10                                             May 9, 1992








                                       Drag and Drop Example Program


             }


             /* This function creates the rectangle bitmaps for the icon and
              * the mask based on the maximum server allowable cursor size
              * and then calls GetDragIcon() to create the drag icon.
              */
             static Widget
             #ifdef _NO_PROTO
             GetDragIconFromRect(w, rect, background)
             Widget w;
             RectPtr rect;
             Pixel background;
             #else
             GetDragIconFromRect(Widget w, RectPtr rect, Pixel background)
             #endif /* _NO_PROTO */
             {

                 Pixmap      icon, icon_mask;
                 Pixel       foreground = RectGetColor(rect);
                 Dimension   width, height;

                 /* Create a depth 1 pixmap (bitmap) for use with the drag
                    icon */
                 icon = icon_mask = GetBitmapFromRect(w, rect, background,
                                         foreground, &width, &height);

                 /* use bitmap for both the bitmap and mask */
                 return(GetDragIcon(w, icon, icon_mask, width, height,
                                    background, foreground));

             }


             /* This is a selection conversion function that is used in
              * converting drag/drop export background color targets.
              * The return types follow ICCC standards.
              */
             /* ARGSUSED */
             Boolean
             #ifdef _NO_PROTO
             ColorConvert(w, selection, target, type, value, length, format)
             Widget w ;
             Atom *selection ;
             Atom *target ;
             Atom *type ;
             XtPointer *value ;
             unsigned long *length ;
             int *format ;
             #else
             ColorConvert(Widget w, Atom *selection, Atom *target, Atom *type,



        May 9, 1992                                             B-11








        OSF/Motif Programmer's Guide


             XtPointer *value, unsigned long *length, int *format)
             #endif /* _NO_PROTO */
             {

                 Display     *display = XtDisplay(w);
                 Atom        BACKGROUND = XmInternAtom(display, "BACKGROUND",
                                                       False);
                 Atom        PIXEL = XmInternAtom(display, "PIXEL", False);
                 Atom        TARGETS = XmInternAtom(display, "TARGETS", False);
                 Atom        MULTIPLE = XmInternAtom(display, "MULTIPLE", False);
                 Atom        TIMESTAMP = XmInternAtom(display, "TIMESTAMP",
                                                      False);
                 int         MAX_TARGS = 5;
                 Widget      widget;
                 XtPointer   client;
                 Arg         args[1];

                 /* get the widget that initiated the drag */
                 XtSetArg(args[0], XmNclientData, &client);
                 XtGetValues(w, args, 1);
                 widget = (Widget) client;

                 /* Make sure we are doing a motif drag by checking if the
                  * widget that is passed in is a drag context. Make sure the
                  * widget in the client data is not NULL.
                  */
                 if (!XmIsDragContext(w) || widget == NULL)
                     return False;

                 if (*target == BACKGROUND) {

                     /* Get widget's background */
                     Pixel *background;

                     background = (Pixel *) XtMalloc(sizeof(Pixel));
                     XtSetArg(args[0], XmNbackground, background);
                     XtGetValues(widget, args, 1);

                     /* value, type, length, and format must be set */
                     *value = (XtPointer) background;
                     *type = PIXEL;
                     *length = sizeof(Pixel);
                     *format = 32;

                 }
                 else if (*target == TARGETS) {

                     /* This target is required by ICCC */
                     Atom *targs = (Atom *)XtMalloc((unsigned)
                                              (MAX_TARGS * sizeof(Atom)));
                     int target_count = 0;



        B-12                                             May 9, 1992








                                       Drag and Drop Example Program


                     *value = (XtPointer) targs;
                     *targs++ = BACKGROUND;
                     target_count++;
                     *targs++ = TARGETS;
                     target_count++;
                     *targs++ = MULTIPLE;
                     target_count++;  /* supported in the Intrinsics */
                     *targs++ = TIMESTAMP;
                     target_count++; /* supported in the Intrinsics */
                     *type = XA_ATOM;
                     *length = (target_count * sizeof(Atom)) >> 2;
                     *format = 32;

                 }
                 else
                     return False;

                 return True;

             }


             /* This callback procedure resets the drag icon cursor to show
              * when the drag is in a valid region .  It cause the
              * state icon to become visible when a drop is at a valid
              * position for drag over effects.
              */
             static void
             #ifdef _NO_PROTO
             DragMotionCallback(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             DragMotionCallback(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 XmDragMotionCallback    cb = (XmDragMotionCallback) call;
                 Arg                     args[2];
                 Widget                  stateIcon, invalidIcon;

                 if (cb->dropSiteStatus == XmVALID_DROP_SITE) {

                     stateIcon = (Widget) client;

                     XtSetArg(args[0], XmNblendModel, XmBLEND_STATE_SOURCE);
                     XtSetArg(args[1], XmNstateCursorIcon, stateIcon);
                     XtSetValues(w, args, 2);

                 }



        May 9, 1992                                             B-13








        OSF/Motif Programmer's Guide


                 else if (cb->dropSiteStatus == XmINVALID_DROP_SITE) {

                     XtSetArg(args[0], XmNdefaultInvalidCursorIcon,
                              &invalidIcon);
                     XtGetValues(XmGetXmScreen(XtScreen(w)), args, 1);
                     XtSetArg(args[0], XmNblendModel, XmBLEND_STATE_SOURCE);
                     XtSetArg(args[1], XmNstateCursorIcon, invalidIcon);
                     XtSetValues(w, args, 2);

                 }
                 else {
                     XtSetArg(args[0], XmNblendModel, XmBLEND_JUST_SOURCE);
                     XtSetValues(w, args, 1);
                 }

             }


             /* This callback procedure resets the drag icon cursor to show
              * when the drag is in a valid region .  It cause the
              * state icon to become visible when a drop is at a valid
              * position for drag over effects.
              */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             DropSiteLeaveCallback(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             DropSiteLeaveCallback(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 Arg    args[1];

                 XtSetArg(args[0], XmNblendModel, XmBLEND_JUST_SOURCE);
                 XtSetValues(w, args, 1);

             }


             /* This callback procedure removes the icons when the drop is
              * complete */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             ColorDragDropFinishCB(w, client, call)
             Widget w;
             XtPointer client;



        B-14                                             May 9, 1992








                                       Drag and Drop Example Program


             XtPointer call;
             #else
             ColorDragDropFinishCB(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 Widget  sourceIcon;
                 Widget  stateIcon = (Widget) client;
                 Arg     args[1];

                 XtSetArg(args[0], XmNsourceCursorIcon, &sourceIcon);
                 XtGetValues(w, args, 1);

                 XtDestroyWidget(sourceIcon);
                 XtDestroyWidget(stateIcon);

             }


             /* This action procedure sets up the drag data and begins the drag
              * operation */
             /* ARGSUSED */
             void
             #ifdef _NO_PROTO
             ColorRect(w, event, params, num_params)
             Widget w;
             XEvent *event;
             String *params;
             Cardinal *num_params;
             #else
             ColorRect(Widget w, XEvent *event, String *params,
                       Cardinal *num_params)
             #endif /* _NO_PROTO */
             {

                 static XtCallbackRec dragDropFinishCB[] = {
                     {ColorDragDropFinishCB, NULL},
                     {NULL, NULL}
                 };

                 static XtCallbackRec dragMotionCB[] = {
                     {DragMotionCallback, NULL},
                     {NULL, NULL}
                 };

                 static XtCallbackRec dropSiteLeaveCB[] = {
                     {DropSiteLeaveCallback, NULL},
                     {NULL, NULL}
                 };

                 Atom        targets[1];



        May 9, 1992                                             B-15








        OSF/Motif Programmer's Guide


                 Widget      sourceIcon, stateIcon;
                 Pixel       background, foreground;
                 char        *source_bits, *source_mask;
                 char        *state_bits, *state_mask;
                 Dimension   width, height;
                 Arg         args[16];
                 int         n = 0;

                 n = 0;
                 XtSetArg(args[n], XmNbackground, &background); n++;
                 XtSetArg(args[n], XmNforeground, &foreground); n++;
                 XtGetValues(w, args, n);

                 /* If the server will handle a large icon, create one */
                 if (appInfo->maxCursorWidth >= ICON_WIDTH &&
                     appInfo->maxCursorHeight >= ICON_HEIGHT) {

                     source_bits = SOURCE_ICON_BITS;
                     source_mask = SOURCE_ICON_MASK;
                     state_bits = STATE_ICON_BITS;
                     state_mask = STATE_ICON_MASK;
                     width = ICON_WIDTH;
                     height = ICON_HEIGHT;

                 }
                 else {

                     /* If the server will handle a small icon, create one */
                     source_bits = SMALL_SOURCE_ICON_BITS;
                     source_mask = SMALL_SOURCE_ICON_MASK;
                     state_bits = SMALL_STATE_ICON_BITS;
                     state_mask = SMALL_STATE_ICON_MASK;
                     width = SMALL_ICON_WIDTH;
                     height = SMALL_ICON_HEIGHT;

                 }

                 /* Create the drag cursor icons */
                 sourceIcon = GetDragIconFromBits(w, source_bits, source_mask,
                                   width, height, background, foreground);

                 stateIcon = GetDragIconFromBits(w, state_bits, state_mask,
                                   width, height, background, foreground);

                 /* Setup the arglist for the drag context that is created at
                  * drag start */
                 n = 0;
                 /* initially only show the source icon */
                 XtSetArg(args[n], XmNblendModel, XmBLEND_JUST_SOURCE); n++;

                 /* set cursor colors for the drag states */



        B-16                                             May 9, 1992








                                       Drag and Drop Example Program


                 XtSetArg(args[n], XmNvalidCursorForeground,
                          GetColor(VALID_CURSOR_FG_COLOR)); n++;
                 XtSetArg(args[n], XmNinvalidCursorForeground,
                          GetColor(INVALID_CURSOR_FG_COLOR)); n++;
                 XtSetArg(args[n], XmNnoneCursorForeground,
                          GetColor(NONE_CURSOR_FG_COLOR)); n++;

                 /* set args for the drag cursor icons */
                 XtSetArg(args[n], XmNcursorBackground, background); n++;
                 XtSetArg(args[n], XmNcursorForeground, foreground); n++;
                 XtSetArg(args[n], XmNsourceCursorIcon, sourceIcon); n++;
                 XtSetArg(args[n], XmNstateCursorIcon, stateIcon); n++;

                 /*
                  * set up the available export targets.  These are targets that
                  * we wish to provide data on
                  */
                 targets[0] = XmInternAtom(XtDisplay(w), "BACKGROUND", False);
                 XtSetArg(args[n], XmNexportTargets, targets); n++;
                 XtSetArg(args[n], XmNnumExportTargets, 1); n++;

                 /*
                  * identify the conversion procedure and
                  * the client data passed to the procedure
                  */
                 XtSetArg(args[n], XmNclientData, w); n++;
                 XtSetArg(args[n], XmNconvertProc, ColorConvert); n++;

                 /* identify the necessary callbacks */
                 dragDropFinishCB[0].closure = (XtPointer) stateIcon;
                 XtSetArg(args[n], XmNdragDropFinishCallback, dragDropFinishCB);
                 n++;
                 dragMotionCB[0].closure = (XtPointer) stateIcon;
                 XtSetArg(args[n], XmNdragMotionCallback, dragMotionCB); n++;
                 XtSetArg(args[n], XmNdropSiteLeaveCallback, dragMotionCB); n++;

                 /* set the drag operations that are supported */
                 XtSetArg(args[n], XmNdragOperations, XmDROP_COPY); n++;

                 /* start the drag.  This creates a drag context. */
                 myDC = XmDragStart(w, event, args, n);

             }


             /*
              * This is a selection conversion function that is used in
              * converting requests for rectangle targets.  The return types
              * follow ICCC standards.
              */
             /* ARGSUSED */



        May 9, 1992                                             B-17








        OSF/Motif Programmer's Guide


             Boolean
             #ifdef _NO_PROTO
             RectConvert( w, selection, target, type, value, length, format)
             Widget w ;
             Atom *selection ;
             Atom *target ;
             Atom *type ;
             XtPointer *value ;
             unsigned long *length ;
             int *format ;
             #else
             RectConvert(Widget w, Atom *selection, Atom *target, Atom *type,
             XtPointer *value, unsigned long *length, int *format)
             #endif /* _NO_PROTO */
             {

                 Display  *display = XtDisplay(w);
                 Atom     MY_RECT = XmInternAtom(display, "_MY_RECTANGLE", False);
                 Atom     RECT_INFO = XmInternAtom(display, "RECT_INFO", False);
                 Atom     DELETE = XmInternAtom(display, "DELETE", False);
                 Atom     TARGETS = XmInternAtom(display, "TARGETS", False);
                 Atom     MULTIPLE = XmInternAtom(display, "MULTIPLE", False);
                 Atom     TIMESTAMP = XmInternAtom(display, "TIMESTAMP", False);
                 Atom     *targs;
                 int      MAX_TARGS = 6;
                 int      target_count;
                 DragConvertPtr  conv;
                 Widget   widget;
                 Arg      args[1];
                 RectPtr  rect, oldRect;

                 /* get the widget that initiated the drag */
                 XtSetArg(args[0], XmNclientData, &conv);
                 XtGetValues(w, args, 1);
                 widget = (Widget) conv->widget;

                 /* Make sure we are doing a motif drag by checking if the
                  * widget that is passed in is a drag context. Make sure the
                  * widget in the client data is not NULL.
                  */
                 if (!XmIsDragContext(w) || widget == NULL)
                     return False;

                 if (*target == MY_RECT) {

                     /* Create a new rectangle using information from the old
                        retangle */
                     oldRect = conv->rect;

                     /* We create create a new rectangle and wait for a delete
                      * target on the old rectangle instead of just moving the



        B-18                                             May 9, 1992








                                       Drag and Drop Example Program


                      * old rectangle because the rectangle movement might be an
                      * interclient move.
                      */
                     rect = RectCreate(oldRect->x, oldRect->y, oldRect->width,
                         oldRect->height, oldRect->color, oldRect->pixmap);
                     /* value, type, length, and format must be assigned values */
                     *value = (XtPointer) rect;
                     *type = RECT_INFO;
                     *length = sizeof(Pixel);
                     *format = 32;

                 }
                 else if (*target == DELETE) {

                     /* delete the old rectangle */
                     RectHide(XtDisplay(widget), XtWindow(widget), conv->rect);
                     RectFree(conv->rect);

                     conv->rect = NULL;
                     /*
                      * DELETE target return parameters MUST be assigned as
                      * follows to ICCC compliant.
                      */
                     *value = NULL;
                     *type = XmInternAtom(XtDisplay(w), "NULL", False);
                     *length = 0;
                     *format = 8;

                 }
                 else if (*target == TARGETS) {

                     /* This target is required by ICCC */
                     targs = (Atom *)XtMalloc((unsigned)
                                              (MAX_TARGS * sizeof(Atom)));
                     target_count = 0;

                     *value = (XtPointer) targs;
                     *targs++ = MY_RECT;
                     target_count++;
                     *targs++ = DELETE;
                     target_count++;
                     *targs++ = TARGETS;
                     target_count++;
                     *targs++ = MULTIPLE;
                     target_count++;  /* supported in the Intrinsics */
                     *targs++ = TIMESTAMP;
                     target_count++; /* supported in the Intrinsics */
                     *type = XA_ATOM;
                     *length = (target_count * sizeof(Atom)) >> 2;
                     *format = 32;




        May 9, 1992                                             B-19








        OSF/Motif Programmer's Guide


                 }
                 else
                     return False;

                 return True;

             }


             /* This callback procedure removes the old cursor icon */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             RectDragDropFinishCB(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             RectDragDropFinishCB(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 DragConvertPtr  conv = (DragConvertPtr) client;
                 Widget          sourceCursorIcon;
                 Arg             args[1];

                 XtSetArg(args[0], XmNsourceCursorIcon, &sourceCursorIcon);
                 XtGetValues(w, args, 1);

                 XtFree((char *) conv);

                 XtDestroyWidget(sourceCursorIcon);

             }


             /* This callback procedure redraws the rectangles once the drop
              * is completed */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             RectDropFinishCB(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             RectDropFinishCB(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 DragConvertPtr    conv = (DragConvertPtr) client;



        B-20                                             May 9, 1992








                                       Drag and Drop Example Program


                 appInfo->clearRect = NULL;
                 appInfo->doMove = True;
                 RedrawRectangles(conv->widget);

             }


             /* This callback procedure handle the drawing of the target
              * rectangle depending of the dropSiteStatus for drag over
              * effects.
              */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             RectDragMotionCB(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             RectDragMotionCB(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 XmDragMotionCallback    cb = (XmDragMotionCallback) call;
                 DragConvertPtr          conv = (DragConvertPtr) client;
                 Display                 *display;
                 Window                  window;
                 RectPtr                 rect;

                 if (cb->dropSiteStatus == XmVALID_DROP_SITE) {

                     /* re-stipple the rectangle when the pointer is inside the
                      * drop site */
                     if ( appInfo->clearRect == NULL && appInfo->doMove) {

                         display = XtDisplay(conv->widget);
                         window = XtWindow(conv->widget);
                         rect = conv->rect;

                         RectHide(display, window, rect);
                         RectDrawStippled(display, window, rect);

                     }

                 }
                 else {

                     /* re-fill the rectangle when the pointer is outside the
                      * drop site */
                     if (appInfo->clearRect != NULL && appInfo->doMove) {
                         appInfo->clearRect = NULL;



        May 9, 1992                                             B-21








        OSF/Motif Programmer's Guide


                         RedrawRectangles(conv->widget);
                     }

                 }

             }


             /* This callback procedure handle the drawing of the target
              * rectangle When the operation changes.
              */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             RectOperationChangedCB(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             RectOperationChangedCB(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 XmDragMotionCallback    cb = (XmDragMotionCallback) call;
                 DragConvertPtr          conv = (DragConvertPtr) client;
                 Display                 *display;
                 Window                  window;
                 RectPtr                 rect;

                 /* re-stipple the rectangle when the pointer is inside the drop
                  * site */
                 if ( appInfo->clearRect == NULL && appInfo->doMove) {

                     display = XtDisplay(conv->widget);
                     window = XtWindow(conv->widget);
                     rect = conv->rect;

                     RectHide(display, window, rect);
                     RectDrawStippled(display, window, rect);

                 }

                 /* re-fill the rectangle when the operation changes to copy */
                 if (appInfo->clearRect != NULL && !appInfo->doMove) {
                     appInfo->clearRect = NULL;
                     RedrawRectangles(conv->widget);
                 }

             }





        B-22                                             May 9, 1992








                                       Drag and Drop Example Program


             /* This action procedure sets up the drag data and begins the drag
              * operation */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             StartMove(w, event, params, num_params)
             Widget w;
             XEvent *event;
             String *params;
             Cardinal *num_params;
             #else
             StartMove(Widget w, XEvent *event, String *params,
                       Cardinal *num_params)
             #endif /* _NO_PROTO */
             {

                 RectPtr     rect;
                 Position    x = event->xbutton.x;
                 Position    y = event->xbutton.y;
                 static XtCallbackRec dragDropFinishCB[] = {
                     {RectDragDropFinishCB, NULL},
                     {NULL, NULL}
                 };

                 static XtCallbackRec dropFinishCB[] = {
                     {RectDropFinishCB, NULL},
                     {NULL, NULL}
                 };

                 static XtCallbackRec dragMotionCB[] = {
                     {RectDragMotionCB, NULL},
                     {NULL, NULL}
                 };

                 static XtCallbackRec operationChangedCB[] = {
                     {RectOperationChangedCB, NULL},
                     {NULL, NULL}
                 };

                 Atom            targets[1];
                 Display         *display = XtDisplay(w);
                 Widget          sourceCursorIcon;
                 DragConvertPtr  conv;
                 Pixel           background, foreground;
                 Arg             args[16];
                 int             n = 0;

                 /* find a rectangle at the given x,y position */
                 rect = RectFind(x, y);

                 /* start move only if it begins on a rectangle */



        May 9, 1992                                             B-23








        OSF/Motif Programmer's Guide


                 if (rect) {

                     XtSetArg(args[0], XmNbackground, &background);
                     XtGetValues(w, args, 1);

                     foreground = RectGetColor(rect);
                     sourceCursorIcon = GetDragIconFromRect(w, rect, background);

                     /*
                      * Set up information to pass to the convert
                      * function and callback procs.
                      */
                     conv = (DragConvertPtr) XtMalloc(sizeof(DragConvertRec));
                     conv->widget = w;
                     conv->rect = rect;

                     /* On a move operation, draw the current
                    * rectangle as a stippled outline.
                    */
                     if (!(event->xbutton.state & ControlMask)) {
                         RectHide(display, XtWindow(w), rect);
                         RectDrawStippled(display, XtWindow(w), rect);
                     }
                     else
                         appInfo->doMove = False;

                     /* Setup arglist for the drag context that is created at
                      * drag start */
                     n = 0;
                     /* initially only show the source icon */
                     XtSetArg(args[n], XmNblendModel, XmBLEND_JUST_SOURCE); n++;

                     /* set args for the drag cursor icons */
                     XtSetArg(args[n], XmNcursorBackground, background); n++;
                     XtSetArg(args[n], XmNcursorForeground, foreground); n++;
                     XtSetArg(args[n], XmNsourceCursorIcon, sourceCursorIcon);
                     n++;

                     /*
                      * set up the available export targets.  These are targets
                      * that we wish to provide data on
                      */
                     targets[0] = XmInternAtom(display, "_MY_RECTANGLE", False);
                     XtSetArg(args[n], XmNexportTargets, targets); n++;
                     XtSetArg(args[n], XmNnumExportTargets, 1); n++;

                     /*
                      * identify the conversion procedure and
                      * the client data passed to the procedure
                      */
                     XtSetArg(args[n], XmNclientData, conv); n++;



        B-24                                             May 9, 1992








                                       Drag and Drop Example Program


                     XtSetArg(args[n], XmNconvertProc, RectConvert); n++;

                     /* identify the necessary callbacks and the client data to
                      * be passed */
                     dragDropFinishCB[0].closure = (XtPointer) conv;
                     XtSetArg(args[n], XmNdragDropFinishCallback,
                                                         dragDropFinishCB); n++;
                     dropFinishCB[0].closure = (XtPointer) conv;
                     XtSetArg(args[n], XmNdropFinishCallback, dropFinishCB); n++;
                     dragMotionCB[0].closure = (XtPointer) conv;
                     XtSetArg(args[n], XmNdragMotionCallback, dragMotionCB); n++;
                     operationChangedCB[0].closure = (XtPointer) conv;
                     XtSetArg(args[n], XmNoperationChangedCallback,
                                                        operationChangedCB); n++;

                     /* set the drag operations that are supported */
                     XtSetArg(args[n], XmNdragOperations,
                                                 XmDROP_COPY | XmDROP_MOVE); n++;

                     /* start the drag. This creates a drag context. */
                     myDC = XmDragStart(w, event, args, n);

                 }

             }


             /* This procedure searches through the export targets and
              * returns flags to indicate which targets were found
              */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             CheckTargets(w, display, rectFound, bgFound, pixFound)
             Widget w;
             Display *display;
             Boolean *rectFound;
             Boolean *bgFound;
             Boolean *pixFound;
             #else
             CheckTargets(Widget w, Display *display, Boolean *rectFound,
             Boolean *bgFound, Boolean *pixFound)
             #endif /* _NO_PROTO */
             {

                 Atom        MY_RECT = XmInternAtom(display, "_MY_RECTANGLE",
                                                    False);
                 Atom        BACKGROUND = XmInternAtom(display, "BACKGROUND",
                                                       False);
                 Atom        PIXMAP = XmInternAtom(display, "PIXMAP", False);
                 Atom        *exportTargets;



        May 9, 1992                                             B-25








        OSF/Motif Programmer's Guide


                 Cardinal    numExportTargets;
                 Arg         args[2];
                 int         n;

                 /* Get list of transfer targets */
                 n = 0;
                 XtSetArg(args[0], XmNexportTargets, &exportTargets);
                 XtSetArg(args[1], XmNnumExportTargets, &numExportTargets);
                 XtGetValues(w, args, 2);

                 /* initialize targets found flags */
                 *rectFound = *bgFound = *pixFound = False;

                 /* search through the export targets */
                 for (n = 0; n < numExportTargets; n++) {

                     if (exportTargets[n] == MY_RECT)
                         *rectFound = True;
                     else if (exportTargets[n] == BACKGROUND)
                         *bgFound = True;
                     else if (exportTargets[n] == PIXMAP)
                         *pixFound = True;

                 }

             }


             /* This procedure handles drop site messages and performs the
              * appropriate drag under effects.
              */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             DragProcCallback(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             DragProcCallback(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 XmDragProcCallbackStruct    *cb = (XmDragProcCallbackStruct *)
                                                    call;
                 Display                     *display = XtDisplay(w);
                 Boolean                     rectFound, bgFound, pixFound;
                 static unsigned char        initial_operations;
                 static unsigned char        initial_operation;
                 RectPtr                     rect;




        B-26                                             May 9, 1992








                                       Drag and Drop Example Program


                 CheckTargets(cb->dragContext, display, &rectFound, &bgFound,
                              &pixFound);

                 switch(cb->reason) {

                     case XmCR_DROP_SITE_ENTER_MESSAGE:

                         /* save the value of the operations and operation
                          * fields */
                         initial_operations = cb->operations;
                         initial_operation = cb->operation;

                         rect = RectFind(cb->x, cb->y);

                         /* Remove any operations for the operations field
                          * which do not apply to the simulated drop site.
                          */
                         if (rect) {

                             if (bgFound || pixFound) {
                                 cb->operations = XmDROP_COPY;
                                 RectHighlight(w, rect);
                             }
                             else if (rectFound) {
                                 cb->operations = cb->operations &
                                                  (XmDROP_COPY | XmDROP_MOVE);
                                 RectUnhighlight(w);
                             }

                         }
                         else {
                             cb->operations = initial_operations &
                                              (XmDROP_COPY | XmDROP_MOVE);
                             RectUnhighlight(w);
                         }

                         /* Set operation to the valid operation preferred by
                          * the simulated drop site or to XmDROP_NOOP if the
                          * operations list does not * contain the preferred
                          * operation.
                          */
                         if (rect) {

                             if (bgFound || pixFound) {

                                 if (cb->operations & XmDROP_COPY)
                                     cb->operation = XmDROP_COPY;
                                 else
                                     cb->operation = XmDROP_NOOP;

                             }



        May 9, 1992                                             B-27








        OSF/Motif Programmer's Guide


                             else if (rectFound) {

                                 if (cb->operations & XmDROP_MOVE)
                                     cb->operation = XmDROP_MOVE;
                                 else if (cb->operations & XmDROP_COPY)
                                     cb->operation = XmDROP_COPY;
                                 else
                                     cb->operation = XmDROP_NOOP;

                             }

                         }
                         else {

                             if (rectFound) {

                                 if (cb->operations & XmDROP_MOVE)
                                     cb->operation = XmDROP_MOVE;
                                 else if (cb->operations & XmDROP_COPY)
                                     cb->operation = XmDROP_COPY;
                                 else
                                     cb->operation = XmDROP_NOOP;

                             }
                             else
                                 cb->operation = initial_operation;

                         }

                         /*
                          * Set dropSiteStatus to XmDROP_SITE_INVALID if the
                          * operation field is XmDROP_NOOP, or if there are no
                          * common targets between the source and the nested
                          * drop site.  Otherwise, set * dropSiteStatus to
                          * XmDROP_SITE_VALID.
                          */
                         if (cb->operation == XmDROP_NOOP ||
                             (rect && (!rectFound && !bgFound && !pixFound)) ||
                             (!rect && !rectFound))
                             cb->dropSiteStatus = XmINVALID_DROP_SITE;
                         else
                             cb->dropSiteStatus = XmVALID_DROP_SITE;

                         /*
                          * Display appropriate drag under visuals.  Only
                          * highlight the rectangle if we are changing rectangle
                          * attributes.
                          */
                         if (rect && bgFound || pixFound &&
                             cb->dropSiteStatus == XmVALID_DROP_SITE)
                             RectHighlight(w, rect);



        B-28                                             May 9, 1992








                                       Drag and Drop Example Program


                         break;

                     case XmCR_DROP_SITE_LEAVE_MESSAGE:

                         /* Only unhighlight the rectangle if previously
                          * highlighted */
                         if (appInfo->highlightRect != NULL)
                             RectUnhighlight(w);
                         break;

                     case XmCR_DROP_SITE_MOTION_MESSAGE:

                         rect = RectFind(cb->x, cb->y);

                         /*
                          * Remove any operations for the operations field
                          * which do not
                          * apply to the simulated drop site.
                          */
                         if (rect) {

                             if (bgFound || pixFound) {
                                 cb->operations = XmDROP_COPY;
                                 RectHighlight(w, rect);
                             }
                             else if (rectFound) {
                                 cb->operations = cb->operations &
                                                  (XmDROP_COPY | XmDROP_MOVE);
                                 RectUnhighlight(w);
                             }

                         }
                         else {
                             cb->operations = initial_operations &
                                              (XmDROP_COPY | XmDROP_MOVE);
                             RectUnhighlight(w);
                         }

                         /*
                          * Set operation to the valid operation preferred by
                          * the simulated drop site or to XmDROP_NOOP if the
                          * operations list does not * contain the preferred
                          * operation.
                          */
                         if (rect) {

                             if (bgFound || pixFound) {

                                 if (cb->operations & XmDROP_COPY)
                                     cb->operation = XmDROP_COPY;
                                 else



        May 9, 1992                                             B-29








        OSF/Motif Programmer's Guide


                                     cb->operation = XmDROP_NOOP;

                             }
                             else if (rectFound) {

                                 if (cb->operations & XmDROP_MOVE)
                                     cb->operation = XmDROP_MOVE;
                                 else if (cb->operations & XmDROP_COPY)
                                     cb->operation = XmDROP_COPY;
                                 else
                                     cb->operation = XmDROP_NOOP;

                             }
                         }
                         else {

                             if (rectFound) {
                                 if (cb->operations & XmDROP_MOVE)
                                     cb->operation = XmDROP_MOVE;
                                 else if (cb->operations & XmDROP_COPY)
                                     cb->operation = XmDROP_COPY;
                                 else
                                     cb->operation = XmDROP_NOOP;

                             }
                             else
                                 cb->operation = initial_operation;

                         }

                         /*
                          * Set dropSiteStatus to XmDROP_SITE_INVALID if the
                          * operation field is XmDROP_NOOP, or if there are no
                          * common targets between the source and the nested
                          * drop site.  Otherwise, set dropSiteStatus to
                          * XmDROP_SITE_VALID.
                          */
                         if (cb->operation == XmDROP_NOOP ||
                             (rect && (!rectFound && !bgFound && !pixFound)) ||
                             (!rect && !rectFound))
                             cb->dropSiteStatus = XmINVALID_DROP_SITE;
                         else
                             cb->dropSiteStatus = XmVALID_DROP_SITE;

                         /*
                          * Display appropriate drag under visuals.  Only
                          * highlight the rectangle if we are changing rectangle
                          * attributes.
                          */
                         if (rect && bgFound || pixFound &&
                             cb->dropSiteStatus == XmVALID_DROP_SITE)



        B-30                                             May 9, 1992








                                       Drag and Drop Example Program


                             RectHighlight(w, rect);
                         break;

                     case XmCR_OPERATION_CHANGED:

                         if (rectFound) {

                             if (cb->operation == XmDROP_MOVE)
                                 appInfo->doMove = True;
                             else
                                 appInfo->doMove = False;

                         }
                         break;

                     default:

                         /* other messages we consider invalid */
                         cb->dropSiteStatus = XmINVALID_DROP_SITE;
                         break;

                 }

                 /* allow animation to be performed */
                 cb->animate = True;

             }


             /* This procedure handles the data that is being transfer */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             TransferProcCallback(w, closure, seltype, type, value, length,
                                  format)
             Widget w;
             XtPointer closure ;
             Atom *seltype ;
             Atom *type ;
             XtPointer value ;
             unsigned long *length ;
             int *format ;
             #else
             TransferProcCallback(Widget w, XtPointer closure, Atom *seltype,
             Atom *type, XtPointer value, unsigned long *length, int *format)
             #endif /* _NO_PROTO */
             {

                 DropTransfer    transferRec = (DropTransfer) closure;
                 Widget          wid = transferRec->widget;
                 Display         *display = XtDisplay(wid);



        May 9, 1992                                             B-31








        OSF/Motif Programmer's Guide


                 Atom    RECT_INFO = XmInternAtom(display, "RECT_INFO", False);
                 Atom    PIXEL = XmInternAtom(display, "PIXEL", False);
                 Atom    NULL_ATOM = XmInternAtom(display, "NULL", False);
                 Arg             args[10];
                 RectPtr         rect;
                 int              n;

                 /*
                  * The delete target returns a NULL_ATOM type and value equal
                  * to NULL so it isn't a failure.  Otherwise, check for NULL
                  * value or targets that we don't support and set transfer
                  * failure.
                  */
                 if (*type != NULL_ATOM && (!value ||
                     (*type != RECT_INFO && *type != PIXEL &&
                          *type != XA_DRAWABLE))) {

                     n = 0;
                     /*
                      * On failures set both transferStatus to
                      * XmTRANSFER_FAILURE and numDropTransfers to 0.
                      */
                     XtSetArg(args[n], XmNtransferStatus, XmTRANSFER_FAILURE);
                     n++;
                     XtSetArg(args[n], XmNnumDropTransfers, 0); n++;
                     XtSetValues(w, args, n);
                     /* Free the value if there is one, or we would have a
                      * memory leak */
                     if (value)
                         XtFree(value);

                     return;

                 }

                 /* Handle pixel type (i.e. change in background) */
                 if (*type == PIXEL) {
                     rect = RectFind(transferRec->x, transferRec->y);
                     RectSetColor(rect, display, XtWindow(wid),
                                  *((Pixel*)value));
                 }
                 /* Handle drawable type (i.e. change in pixmap) */
                 else if (*type == XA_DRAWABLE) {
                     rect = RectFind(transferRec->x, transferRec->y);
                     RectSetPixmap(rect, display, XtWindow(wid),
                                   *((Pixmap *)value));
                 }
                 /* Handle rect_info type (i.e. new rectangle) */
                 else if (*type == RECT_INFO) {
                     rect = (RectPtr) value;
                     RectRegister(rect, transferRec->x, transferRec->y);



        B-32                                             May 9, 1992








                                       Drag and Drop Example Program


                     value = NULL;
                     /* No need to free, it is being stored in RecTable */
                 }

                 /* Free the value if there is one, or we would have a memory
                  * leak */
                 if (value)
                     XtFree(value);

             }


             /* This procedure frees the data used the data transfer proc that
              * was passed from the drop procedure.
              */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             DropDestroyCB(w, clientData, callData)
             Widget      w;
             XtPointer   clientData;
             XtPointer   callData;
             #else
             DropDestroyCB(Widget w, XtPointer clientData, XtPointer callData)
             #endif /* NO_PROTO */
             {
                 XtFree((char *)clientData);
             }


             /* This procedure initiates the drop transfer. */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             HandleDrop(w, call)
             Widget w;
             XtPointer call;
             #else
             HandleDrop(Widget w, XtPointer call)
             #endif /* _NO_PROTO */
             {
                 static XtCallbackRec dropDestroyCB[] = {
                     {DropDestroyCB, NULL},
                     {NULL, NULL}
                 };

                 XmDropProcCallbackStruct *cb = (XmDropProcCallbackStruct *)call;
                 Display                     *display = XtDisplay(w);
                 Arg                         args[10];
                 int                         n;
                 Boolean                     rectFound, bgFound, pixFound;



        May 9, 1992                                             B-33








        OSF/Motif Programmer's Guide


                 DropTransfer                transferRec;
                 XmDropTransferEntryRec      transferEntries[2];
                 XmDropTransferEntryRec      *transferList = NULL;
                 Cardinal                    numTransfers = 0;
                 Boolean                     transferValid = False;
                 RectPtr                     rect;

                 /* Cancel the drop on invalid drop operations */
                 if (!(cb->operations & XmDROP_MOVE || cb->operations
                       & XmDROP_COPY)) {

                     n = 0;
                     cb->operation = XmDROP_NOOP;
                     cb->dropSiteStatus = XmINVALID_DROP_SITE;
                     XtSetArg(args[n], XmNtransferStatus, XmTRANSFER_FAILURE);
                     n++;
                     XtSetArg(args[n], XmNnumDropTransfers, 0); n++;
                 }
                 else {

                     /* Find out which nested dropsite contains the pointer */
                     rect = RectFind(cb->x, cb->y);

                     CheckTargets(cb->dragContext, display, &rectFound, &bgFound,
                                  &pixFound);

                     /* rect !NULL indicates we are within a nested dropsite */
                     if (rect) {

                         /* MY_RECT is a possible target, support it first */
                         if (rectFound)
                             transferValid = True;
                         else if (bgFound || pixFound) {
                             /* support only copy with the BACKGROUND and PIXMAP
                              * targets */
                             if (cb->operation != XmDROP_COPY)
                                 cb->operation = XmDROP_COPY;
                             transferValid = True;
                         }

                     }
                     else {
                         if (rectFound)
                             transferValid = True;
                     }

                     if (transferValid) {

                         /* initialize data to send to drop transfer callback */
                         transferRec = (DropTransfer)
                                        XtMalloc(sizeof(DropTransferRec));



        B-34                                             May 9, 1992








                                       Drag and Drop Example Program


                         transferRec->widget = w;
                         transferRec->x = cb->x;
                         transferRec->y = cb->y;

                         /* order of support is MY_RECT, then BACKGROUND, then
                          * PIXMAP */
                         if (rectFound)
                             transferEntries[0].target = XmInternAtom(display,
                                    "_MY_RECTANGLE", False);
                         else if (bgFound)
                             transferEntries[0].target = XmInternAtom(display,
                                    "BACKGROUND", False);
                         else if (pixFound)
                             transferEntries[0].target = XmInternAtom(display,
                                    "PIXMAP", False);

                         transferEntries[0].client_data =
                             (XtPointer) transferRec;

                         /* Set up move targets */
                         if (cb->operation == XmDROP_MOVE) {

                             transferEntries[1].client_data =
                                   (XtPointer) transferRec;
                             transferEntries[1].target = XmInternAtom(display,
                                   "DELETE", False);
                             numTransfers = 2;

                         }
                         else if (cb->operation == XmDROP_COPY)
                             numTransfers = 1;

                         transferList = transferEntries;

                         /* Setup transfer list */
                         n = 0;
                         cb->dropSiteStatus = XmVALID_DROP_SITE;
                         XtSetArg(args[n], XmNdropTransfers, transferList); n++;
                         XtSetArg(args[n], XmNnumDropTransfers, numTransfers);
                         n++;

                         /* Setup destroy callback to free transferRec */
                         dropDestroyCB[0].closure = (XtPointer) transferRec;
                         XtSetArg(args[n], XmNdestroyCallback, dropDestroyCB);
                         n++;

                         /* Setup transfer proc to accept the drop transfer data */
                         XtSetArg(args[n], XmNtransferProc, TransferProcCallback);
                         n++;

                     }



        May 9, 1992                                             B-35








        OSF/Motif Programmer's Guide


                     else {

                         n = 0;
                         cb->operation = XmDROP_NOOP;
                         cb->dropSiteStatus = XmINVALID_DROP_SITE;
                         XtSetArg(args[n], XmNtransferStatus,
                              XmTRANSFER_FAILURE); n++;
                         XtSetArg(args[n], XmNnumDropTransfers, 0); n++;

                     }

                 }

                 XmDropTransferStart(cb->dragContext, args, n);

             }


             /* This procedure is used with the drop help dialog to continue
              * with the drop */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             HandleOK(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             HandleOK(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 XmDropProcCallbackStruct *cb = (XmDropProcCallbackStruct *)client;

                 cb->operation = appInfo->operation;
                 HandleDrop(w, (XtPointer) cb);

             }


             /* This procedure is used with the drop help dialog to cancel the
              * drop */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             CancelDrop(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             CancelDrop(Widget w, XtPointer client, XtPointer call)



        B-36                                             May 9, 1992








                                       Drag and Drop Example Program


             #endif /* _NO_PROTO */
             {

                 XmDropProcCallbackStruct *cb = (XmDropProcCallbackStruct *)client;
                 Arg                         args[2];

                 /* On help, we need to cancel the drop transfer */
                 XtSetArg(args[0], XmNtransferStatus, XmTRANSFER_FAILURE);
                 XtSetArg(args[1], XmNnumDropTransfers, 0);

                 /* we need to start the drop transfer to cancel the transfer */
                 XmDropTransferStart(cb->dragContext, args, 2);

             }


             #ifdef _NO_PROTO
             XtCallbackProc ChangeOperation(widget, client_data, call_data)
             Widget widget;
             caddr_t client_data;
             XmAnyCallbackStruct *call_data;
             #else
             XtCallbackProc ChangeOperation(Widget widget, caddr_t client_data,
             XmAnyCallbackStruct *call_data)
             #endif
             {

                 if (client_data == 0)
                     appInfo->operation = XmDROP_MOVE;
                 else
                     appInfo->operation = XmDROP_COPY;

             }


             /* This procedure manages the help dialog and determines which
              * message is displayed in the dialog depending on the position
              * and the type of drop.
              */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             HandleHelp(w, call)
             Widget w;
             XtPointer call;
             #else
             HandleHelp(Widget w, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 XmDropProcCallbackStruct *cb = (XmDropProcCallbackStruct *)call;



        May 9, 1992                                             B-37








        OSF/Motif Programmer's Guide


                 static XmDropProcCallbackStruct client;
                 Boolean                         rectFound, bgFound, pixFound;
                 XmString                        helpStr;
                 RectPtr                         rect;
                 Arg                             args[5];
                 XmString                        tempStr, buttonArray[2];
                 int                             n = 0;

                 /* the drop is valid until it is determined invalid */
                 cb->dropSiteStatus = XmVALID_DROP_SITE;

                 /* if we haven't created a help dialog, create one now */
                 if (helpDialog == NULL) {

                     XtSetArg(args[n], XmNdialogStyle,
                           XmDIALOG_FULL_APPLICATION_MODAL); n++;
                     XtSetArg(args[n], XmNtitle, "Drop Help"); n++;
                     helpDialog = XmCreateMessageDialog(topLevel, "Help",
                           args, n);

                     n = 0;
                     buttonArray[0] = XmStringCreateSimple("Move");
                     buttonArray[1] = XmStringCreateSimple("Copy");
                     XtSetArg(args[n], XmNbuttons, buttonArray); n++;
                     XtSetArg(args[n], XmNbuttonCount, 2); n++;
                     XtSetArg(args[n], XmNbuttonSet, 0); n++;
                     XtSetArg(args[n], XmNsimpleCallback, ChangeOperation); n++;
                     tempStr = XmStringCreateSimple("Operations:");
                     XtSetArg(args[n], XmNoptionLabel, tempStr); n++;
                     helpMenu = XmCreateSimpleOptionMenu(helpDialog, "helpMenu",
                           args, n);
                     XmStringFree(tempStr);
                     XmStringFree(buttonArray[0]);
                     XmStringFree(buttonArray[1]);

                     XtAddCallback(helpDialog, XmNokCallback,
                          (XtCallbackProc) HandleOK, (XtPointer) &client);
                     XtAddCallback(helpDialog, XmNcancelCallback,
                          (XtCallbackProc) CancelDrop, (XtPointer) &client);

                     XtUnmanageChild(XmMessageBoxGetChild(helpDialog,
                           XmDIALOG_HELP_BUTTON));

                     XtRealizeWidget(helpDialog);

                 }

                 /* pass the necessary callback information along */
                 client.dragContext = cb->dragContext;
                 client.x = cb->x;
                 client.y = cb->y;



        B-38                                             May 9, 1992








                                       Drag and Drop Example Program


                 client.dropSiteStatus = cb->dropSiteStatus;
                 client.operation = cb->operation;
                 client.operations = cb->operations;

                 /* find the valid targets */
                 CheckTargets(cb->dragContext, XtDisplay(w), &rectFound,
                              &bgFound, &pixFound);

                 /* determine the appropriate help message */
                 if (rectFound) {

                     if (cb->operations == XmDROP_MOVE | XmDROP_COPY) {
                         XtManageChild(helpMenu);
                         helpStr = XmStringCreateLtoR(HELP_MSG4,
                                                      XmFONTLIST_DEFAULT_TAG);
                         XtManageChild(XmMessageBoxGetChild(helpDialog,
                                       XmDIALOG_OK_BUTTON));
                     }
                     else if (cb->operation == XmDROP_MOVE) {
                         XtUnmanageChild(helpMenu);
                         helpStr = XmStringCreateLtoR(HELP_MSG2,
                                                      XmFONTLIST_DEFAULT_TAG);
                         XtManageChild(XmMessageBoxGetChild(helpDialog,
                                       XmDIALOG_OK_BUTTON));
                     }
                     else if (cb->operation == XmDROP_COPY) {
                         XtUnmanageChild(helpMenu);
                         helpStr = XmStringCreateLtoR(HELP_MSG3,
                                                      XmFONTLIST_DEFAULT_TAG);
                         XtManageChild(XmMessageBoxGetChild(helpDialog,
                                       XmDIALOG_OK_BUTTON));
                     }

                 }
                 else if (bgFound || pixFound && cb->operation == XmDROP_COPY) {

                     XtUnmanageChild(helpMenu);
                     rect = RectFind(cb->x, cb->y);
                     if (rect) {
                         helpStr = XmStringCreateLtoR(HELP_MSG1,
                                                      XmFONTLIST_DEFAULT_TAG);
                         XtManageChild(XmMessageBoxGetChild(helpDialog,
                                       XmDIALOG_OK_BUTTON));
                     }
                     else {
                         helpStr = XmStringCreateLtoR(HELP_MSG5,
                                                      XmFONTLIST_DEFAULT_TAG);
                         XtUnmanageChild(XmMessageBoxGetChild(helpDialog,
                                         XmDIALOG_OK_BUTTON));
                     }




        May 9, 1992                                             B-39








        OSF/Motif Programmer's Guide


                 }
                 else {
                     XtUnmanageChild(helpMenu);
                     helpStr = XmStringCreateLtoR(HELP_MSG5,
                                                  XmFONTLIST_DEFAULT_TAG);
                     XtUnmanageChild(XmMessageBoxGetChild(helpDialog,
                                     XmDIALOG_OK_BUTTON));
                 }

                 /* set the help message into the dialog */
                 XtSetArg(args[0], XmNmessageString, helpStr);
                 XtSetValues(helpDialog, args, 1);

                 /* Free the XmString */
                 XmStringFree(helpStr);

                 /* map the help dialog */
                 XtManageChild(helpDialog);

             }


             /* The procedure either begins the drop of initiates the help
              * dialog depending on the dropAction.
              */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             DropProcCallback(w, client, call)
             Widget w;
             XtPointer client;
             XtPointer call;
             #else
             DropProcCallback(Widget w, XtPointer client, XtPointer call)
             #endif /* _NO_PROTO */
             {

                 XmDropProcCallbackStruct *cb = (XmDropProcCallbackStruct *)call;

                 if (appInfo->highlightRect != NULL)
                     RectUnhighlight(w);

                 if (cb->dropAction != XmDROP_HELP)
                     HandleDrop(w, call);
                 else
                     HandleHelp(w, call);

             }


             /* This procedure registers the drop targets and the drop site */



        B-40                                             May 9, 1992








                                       Drag and Drop Example Program


             static void
             #ifdef _NO_PROTO
             RegisterDropSite(w)
             Widget w;
             #else
             RegisterDropSite(Widget w)
             #endif /* _NO_PROTO */
             {

                 Display *display = XtDisplay(w);
                 Atom    targets[3];
                 Arg     args[5];
                 int     n = 0;

                 /* Only accept moves or copies */
                 XtSetArg(args[n], XmNdragOperations, XmDROP_COPY | XmDROP_MOVE);
                 n++;

                 /* set all possible targets for any of the nested drop sites */
                 targets[0] = XmInternAtom(display, "_MY_RECTANGLE", False);
                 targets[1] = XmInternAtom(display, "BACKGROUND", False);
                 targets[2] = XmInternAtom(display, "PIXMAP", False);
                 XtSetArg(args[n], XmNimportTargets, targets); n++;
                 XtSetArg(args[n], XmNnumImportTargets, 3); n++;

                 /* register a dragProc - necessary for simulating nested drop
                  * sites */
                 XtSetArg(args[n], XmNdragProc, DragProcCallback); n++;

                 /* register a dropProc */
                 XtSetArg(args[n], XmNdropProc, DropProcCallback); n++;
                 XmDropSiteRegister(w, args, n);

             }


             static void
             #ifdef _NO_PROTO
             SetInvalidIcon(w)
             Widget w;
             #else
             SetInvalidIcon(Widget w)
             #endif /* _NO_PROTO */
             {

                 Widget      invalidIcon;
                 char        *invalid_bits;
                 Dimension   width, height;
                 Arg         args[1];

                 if (appInfo->maxCursorWidth >= ICON_WIDTH &&



        May 9, 1992                                             B-41








        OSF/Motif Programmer's Guide


                     appInfo->maxCursorHeight >= ICON_HEIGHT) {
                     invalid_bits = INVALID_ICON_BITS;
                     width = ICON_WIDTH;
                     height = ICON_HEIGHT;
                 } else {
                     /* If the server will handle a small icon, create one */
                     invalid_bits = SMALL_INVALID_ICON_BITS;
                     width = SMALL_ICON_WIDTH;
                     height = SMALL_ICON_HEIGHT;
                 }

                 invalidIcon = GetDragIconFromBits(w, invalid_bits, invalid_bits,
                                   width, height, GetColor(DRAW_AREA_FG_COLOR),
                                   GetColor(DRAW_AREA_BG_COLOR));

                 XtSetArg(args[0], XmNdefaultInvalidCursorIcon, invalidIcon);
                 XtSetValues(XmGetXmScreen(XtScreen(w)), args, 1);

             }


             /* This procedure initializes the toolkit and other application
              * information */
             static void
             #ifdef _NO_PROTO
             InitializeApplication(argc, argv)
             int *argc;
             String *argv;
             #else
             InitializeApplication(int *argc, String *argv)
             #endif /* _NO_PROTO */
             {

                 static XtActionsRec new_actions[] = {
                     {"StartRect", StartRect},
                     {"ExtendRect", ExtendRect},
                     {"EndRect", EndRect},
                     {"StartMove", StartMove},
                     {"ColorRect", ColorRect},
                 };
                 Arg         args[5];
                 Cardinal    n = 0;

                 /* Ininialize struct that hold global information */
                 InitializeAppInfo();

                 /* Initialize Toolkit and create shell */
                 XtSetArg(args[n], XmNwidth, 295); n++;
                 XtSetArg(args[n], XmNheight, 270); n++;
                 topLevel = XtAppInitialize(&appContext, "DNDDemo", NULL, 0,
                                            argc, argv, NULL, args, n);



        B-42                                             May 9, 1992








                                       Drag and Drop Example Program


                 /* Set drag protocol styles */
                 n = 0;
                 XtSetArg(args[n], XmNdragInitiatorProtocolStyle,
                          XmDRAG_PREFER_RECEIVER); n++;
                 XtSetArg(args[n], XmNdragReceiverProtocolStyle, XmDRAG_DYNAMIC);
                 n++;
                 XtSetValues(XmGetXmDisplay(XtDisplay(topLevel)), args, n);

                 /* Initialize tables for holding rectangle information */
                 InitializeRectDpyTable();

                 /* Add new actions for use with translation tables */
                 XtAppAddActions(appContext, new_actions, 5);

                 /* Get the display server's best cursor size */
                 XQueryBestCursor(XtDisplay(topLevel),
                      RootWindowOfScreen(XtScreen(topLevel)), 64, 64,
                      &appInfo->maxCursorWidth, &appInfo->maxCursorHeight);

             }


             /* This the program start procedure */
             void
             #ifdef _NO_PROTO
             main (argc, argv)
             int argc;
             String *argv;
             #else
             main (int argc, String *argv)
             #endif /* _NO_PROTO */
             {

                 /* Initialize toolkit and application global values */
                 InitializeApplication(&argc, argv);

                 /* Create main window, drawing area, and color labels */
                 CreateLayout();

                 /* Register the drawing area as a drop site */
                 RegisterDropSite(drawingArea);

                 SetInvalidIcon(drawingArea);

                 /* Realize and map widget hiearchy */
                 XtRealizeWidget(topLevel);

                 /* Create GC for drawing rectangles */
                 CreateRectGC();

                 /* Begin event loop processing */



        May 9, 1992                                             B-43








        OSF/Motif Programmer's Guide


                 XtAppMainLoop(appContext);

             }



        B.3  DDNNDDDDrraaww..cc



             /*
              *    file: DNDDraw.c
              *
              *      File containing all the drawing routines needed to run
              *      DNDDemo program.
              *
              */

             #include "DNDDemo.h"


             /* The following character arrays hold the bits for
              * the source and state icons for both 32x32 and 16x16 drag icons.
              * The source is a color palette icon and the state is a paint
              * brush icon.
              */
             char SOURCE_ICON_BITS[] = {
                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0,
                 0xaa, 0x02, 0x00, 0x50, 0x55, 0x07, 0x00, 0x28, 0x00, 0x0c,
                 0x00, 0x94, 0x42, 0x19, 0x00, 0xca, 0xe5, 0x33, 0x00, 0x85,
                 0xc6, 0x33, 0x80, 0x42, 0xe7, 0x33, 0x40, 0x81, 0xc3, 0x31,
                 0xa0, 0x00, 0x00, 0x38, 0x50, 0x00, 0x00, 0x1c, 0x28, 0x00,
                 0x00, 0x0e, 0x90, 0x02, 0x00, 0x07, 0xc8, 0x05, 0x80, 0x03,
                 0x90, 0x07, 0xc0, 0x01, 0x48, 0x05, 0xe0, 0x00, 0x90, 0x03,
                 0x70, 0x00, 0x08, 0x00, 0x30, 0x00, 0x10, 0x14, 0x30, 0x00,
                 0x08, 0x2a, 0x30, 0x00, 0x10, 0x34, 0x30, 0x00, 0x28, 0x2a,
                 0x60, 0x00, 0x50, 0x9c, 0xe2, 0x00, 0xa0, 0x40, 0xc4, 0x01,
                 0x40, 0x01, 0x84, 0x01, 0x80, 0x42, 0x84, 0x03, 0x00, 0x85,
                 0x03, 0x03, 0x00, 0x0a, 0x00, 0x03, 0x00, 0xf4, 0xff, 0x03,
                 0x00, 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00};

             char SOURCE_ICON_MASK[] = {
                 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x07, 0x00, 0xf8,
                 0xff, 0x0f, 0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x3f,
                 0x00, 0xff, 0xff, 0x7f, 0x80, 0xff, 0xff, 0x7f, 0xc0, 0xff,
                 0xff, 0x7f, 0xe0, 0xff, 0xff, 0x7f, 0xf0, 0xff, 0xff, 0x7f,
                 0xf8, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x7f, 0xfc, 0xff,
                 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x0f,
                 0xfc, 0xff, 0xff, 0x07, 0xfc, 0xff, 0xff, 0x03, 0xfc, 0xff,
                 0xff, 0x01, 0xfc, 0xff, 0xff, 0x00, 0xfc, 0xff, 0x7f, 0x00,
                 0xfc, 0xff, 0x7f, 0x00, 0xfc, 0xff, 0xff, 0x00, 0xfc, 0xff,



        B-44                                             May 9, 1992








                                       Drag and Drop Example Program


                 0xff, 0x01, 0xfc, 0xff, 0xff, 0x03, 0xf8, 0xff, 0xff, 0x03,
                 0xf0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xc0, 0xff,
                 0xff, 0x07, 0x80, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07,
                 0x00, 0xfe, 0xff, 0x07, 0x00, 0xfc, 0xff, 0x03};

             char STATE_ICON_BITS[] = {
                 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x78, 0x00,
                 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
                 0xf8, 0x03, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0xf0, 0x07,
                 0x00, 0x00, 0xc0, 0x0d, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00,
                 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfc,
                 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00,
                 0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80,
                 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x7e, 0x00,
                 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,
                 0xf0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x07,
                 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00,
                 0x00, 0x1e, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x38,
                 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xc0};

             char STATE_ICON_MASK[] = {
                 0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03,
                 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00,
                 0xfc, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0xf8, 0x07,
                 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00,
                 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfc,
                 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00,
                 0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80,
                 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xfe, 0x01,
                 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00,
                 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x1f,
                 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00,
                 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfe,
                 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xf0};

             char INVALID_ICON_BITS[] = {
                 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xff,
                 0xff, 0x01, 0x80, 0xff, 0xff, 0x03, 0xc0, 0x1f, 0xf0, 0x07,
                 0xe0, 0x07, 0xc0, 0x0f, 0xf0, 0x07, 0x00, 0x1f, 0xf8, 0x0f,
                 0x00, 0x3e, 0xf8, 0x1f, 0x00, 0x3c, 0xfc, 0x3f, 0x00, 0x7c,
                 0x3c, 0x7f, 0x00, 0x78, 0x3c, 0xfe, 0x00, 0x78, 0x1e, 0xfc,
                 0x01, 0xf0, 0x1e, 0xf8, 0x03, 0xf0, 0x1e, 0xf0, 0x07, 0xf0,
                 0x1e, 0xe0, 0x0f, 0xf0, 0x1e, 0xc0, 0x1f, 0xf0, 0x1e, 0x80,
                 0x3f, 0xf0, 0x1e, 0x00, 0x7f, 0xf0, 0x3c, 0x00, 0xfe, 0x78,
                 0x3c, 0x00, 0xfc, 0x79, 0x7c, 0x00, 0xf8, 0x7f, 0x78, 0x00,
                 0xf0, 0x3f, 0xf8, 0x00, 0xe0, 0x3f, 0xf0, 0x01, 0xc0, 0x1f,
                 0xe0, 0x07, 0xc0, 0x0f, 0xc0, 0x1f, 0xf0, 0x07, 0x80, 0xff,
                 0xff, 0x03, 0x00, 0xff, 0xff, 0x01, 0x00, 0xfc, 0x7f, 0x00,
                 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00};

             char SMALL_SOURCE_ICON_BITS[] = {



        May 9, 1992                                             B-45








        OSF/Motif Programmer's Guide


                 0x80, 0x1f, 0x40, 0x60, 0x20, 0x91, 0x90, 0xaa, 0x08, 0x91,
                 0x08, 0x40, 0x08, 0x20, 0x08, 0x10, 0x28, 0x10, 0x78, 0x10,
                 0x28, 0x20, 0x08, 0x41, 0x90, 0x43, 0x20, 0x21, 0x40, 0x10,
                 0x80, 0x0f};

             char SMALL_SOURCE_ICON_MASK[] = {
                 0x80, 0x1f, 0xc0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0xf8, 0xff,
                 0xf8, 0x7f, 0xf8, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f,
                 0xf8, 0x3f, 0xf8, 0x7f, 0xf0, 0x7f, 0xe0, 0x3f, 0xc0, 0x1f,
                 0x80, 0x0f};

             char SMALL_STATE_ICON_BITS[] = {
                 0x0f, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x3c, 0x00, 0x50, 0x00,
                 0xe0, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e,
                 0x00, 0x1c, 0x00, 0x18, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80,
                 0x00, 0x00};

             char SMALL_STATE_ICON_MASK[] = {
                 0x0f, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x3c, 0x00, 0x70, 0x00,
                 0xe0, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e,
                 0x00, 0x1c, 0x00, 0x18, 0x00, 0x20, 0x00, 0x40, 0x00, 0x80,
                 0x00, 0x00};

             char SMALL_INVALID_ICON_BITS[] = {
                 0xe0, 0x03, 0xf8, 0x0f, 0x1c, 0x1c, 0x1e, 0x30, 0x3e, 0x30,
                 0x73, 0x60, 0xe3, 0x60, 0xc3, 0x61, 0x83, 0x63, 0x03, 0x67,
                 0x06, 0x3e, 0x06, 0x3c, 0x1c, 0x1c, 0xf8, 0x0f, 0xe0, 0x03,
                 0x00, 0x00};


             /* Globals variables */
             AppInfo appInfo;


             /* This is a string to pixel conversion function. */
             Pixel
             #ifdef _NO_PROTO
             GetColor(colorstr)
             char *colorstr;
             #else
             GetColor(char *colorstr)
             #endif /* _NO_PROTO */
             {

                 XrmValue    from, to;

                 from.size = strlen(colorstr) +1;
                 if (from.size < sizeof(String))
                     from.size = sizeof(String);
                 from.addr = colorstr;
                 to.addr = NULL;



        B-46                                             May 9, 1992








                                       Drag and Drop Example Program


                 XtConvert(topLevel, XmRString, &from, XmRPixel, &to);

                 if (to.addr != NULL)
                     return ((Pixel) *((Pixel *) to.addr));
                 else
                     return ( (XtArgVal) NULL);

             }


             /* This procedure is used to initialize the application information
              * structure */
             void
             #ifdef _NO_PROTO
             InitializeAppInfo()
             #else /* _NO_PROTO */
             InitializeAppInfo(void)
             #endif /* _NO_PROTO */
             {

                 if (!appInfo) {

                     appInfo = (AppInfo) XtMalloc(sizeof(AppInfoRec));
                     appInfo->rectGC = NULL;
                     appInfo->currentColor = 0;
                     appInfo->rectDpyTable = NULL;
                     appInfo->rectsAllocd = 0;
                     appInfo->numRects = 0;
                     appInfo->highlightRect = NULL;
                     appInfo->clearRect = NULL;
                     appInfo->doMove = True;
                     appInfo->creatingRect = True;
                     appInfo->operation = XmDROP_MOVE;
                     appInfo->maxCursorWidth = 64;
                     appInfo->maxCursorHeight = 64;
                     appInfo->rectX = 0;
                     appInfo->rectY = 0;
                     appInfo->rectX2 = 0;
                     appInfo->rectY2 = 0;

                 }

             }


             /* This procedure sets the color in the GC for drawing the
              * rectangles in a new color.
              */
             void
             #ifdef _NO_PROTO
             SetColor(display, color)



        May 9, 1992                                             B-47








        OSF/Motif Programmer's Guide


             Display *display;
             Pixel color;
             #else
             SetColor(Display *display, Pixel color)
             #endif /* _NO_PROTO */
             {

                 /*
                  * if the GC already has a foreground of this color,
                  * it would be wasteful to reset the color
                  */
                 if (color != appInfo->currentColor) {
                     XSetForeground(display, appInfo->rectGC,
                                    (unsigned long) color);
                     appInfo->currentColor = color;
                 }

             }


             /* This function draws the rectangle in the color provided */
             static int
             #ifdef _NO_PROTO
             RectDraw(display, window, rect)
             Display *display;
             Window window;
             RectPtr rect;
             #else
             RectDraw(Display *display, Window window, RectPtr rect)
             #endif /* _NO_PROTO */
             {

                 SetColor(display, rect->color);
                 XFillRectangle(display, window, appInfo->rectGC, rect->x,
                                rect->y, rect->width, rect->height);

             }


             /* This procedure draws the rectangle highlight in a specified
              * color */
             static void
             #ifdef _NO_PROTO
             RectDrawHighlight(w, rect, color )
             Widget w;
             RectPtr rect;
             Pixel color;
             #else
             RectDrawHighlight( Widget w, RectPtr rect, Pixel color )
             #endif /* _NO_PROTO */
             {



        B-48                                             May 9, 1992








                                       Drag and Drop Example Program


                 Display *display = XtDisplay(w);
                 Window window = XtWindow(w);
                 Pixel currentColor = rect->color;
                 XGCValues values;

                 values.foreground = color;
                 XChangeGC(display, appInfo->rectGC, GCForeground, &values);

                 XDrawRectangle(display, window, appInfo->rectGC,
                                rect->x + 1, rect->y + 1,
                                rect->width - HIGHLIGHT_THICKNESS,
                                rect->height - HIGHLIGHT_THICKNESS);

                 /* Return the GC to it's previous state */
                 values.foreground = appInfo->currentColor = currentColor;
                 XChangeGC(display, appInfo->rectGC, GCForeground, &values);

             }


             /* This procedure handles redrawing the rectangles.  It draws
              * them according to the order in the rectangle display table.
              * The rectangles at the top of the table are drawn first.
              */
             void
             #ifdef _NO_PROTO
             RedrawRectangles(w)
             Widget w;
             #else
             RedrawRectangles(Widget w)
             #endif /* _NO_PROTO */
             {

                 Display *display = XtDisplay(w);
                 RectPtr rect;
                 Window window = XtWindow(w);
                 int i;

                 for (i = 0; i < appInfo->numRects; i++) {

                     rect = appInfo->rectDpyTable[i];
                     /* Only draw the rectangles that haven't been cleared */
                     if (rect != appInfo->clearRect) {
                         RectDraw(display, window, rect);
                     }
                     /* Draw the rectangle highlight of the highlight
                      * rectangle */
                     if (rect == appInfo->highlightRect) {
                         RectDrawHighlight(w, rect, GetColor(HIGHLIGHT_COLOR));
                     }




        May 9, 1992                                             B-49








        OSF/Motif Programmer's Guide


                 }

             }


             /* This procedure will clear the current rectangle and redraw any
              * rectangles that were partially cleared by the rectangle that
              * was deleted.
              */
             /* ARGSUSED */
             void
             #ifdef _NO_PROTO
             RectHide(display, window, rect)
             Display *display;
             Window window;
             RectPtr rect;
             #else
             RectHide(Display *display, Window window, RectPtr rect)
             #endif /* _NO_PROTO */
             {

                 Pixel background, oldColor;
                 Arg args[1];

                 /* Get the background of the drawing area. */
                 XtSetArg(args[0], XmNbackground, &background);
                 XtGetValues(drawingArea, args, 1);

                 /* Save the old color for restoration purposes. */
                 oldColor = rect->color;

                 /* Clear the rectangle */
                 rect->color = background;
                 RectDraw(display, window, rect);
                 appInfo->clearRect = rect;

                 /* redraw the rest of the rectangles */
                 RedrawRectangles(drawingArea);

                 /* restore the rectangle color */
                 rect->color = oldColor;

             }

             /* This procedure draws the stipple rectangle that is used in
              * marking the old rectangle position during a rectangle move
              * operation.
              */
             /* ARGSUSED */
             void
             #ifdef _NO_PROTO



        B-50                                             May 9, 1992








                                       Drag and Drop Example Program


             RectDrawStippled(display, window, rect)
             Display *display;
             Window window;
             RectPtr rect;
             #else
             RectDrawStippled(Display *display, Window window, RectPtr rect)
             #endif /* _NO_PROTO */
             {

                 register int x = rect->x;
                 register int y = rect->y;
                 register Dimension width = rect->width;
                 register Dimension height = rect->height;
                 XGCValues values;
                 XSegment segments[4];

                 /* Set the rectangle color */
                 values.foreground = appInfo->currentColor = rect->color;
                 XChangeGC(display, appInfo->rectGC, GCForeground , &values);

                 /* Create the segments for drawing the stippled rectangle */
                 segments[0].x1 = segments[2].x1 = x;
                 segments[0].y1 = segments[0].y2 = y;
                 segments[0].x2 = x + width - 1;
                 segments[1].x1 = segments[1].x2 = x + width - 1;
                 segments[1].y1 = segments[3].y1 = y;
                 segments[3].y2 = y + height;
                 segments[2].y1 = segments[2].y2 = y + height - 1;
                 segments[3].x1 = segments[3].x2 = x;
                 segments[2].x2 = x + width;
                 segments[1].y2 = y + height;

                 /* Set the line attributes and draw */
                 XSetLineAttributes(display, appInfo->rectGC, 1, LineOnOffDash,
                     CapButt, JoinMiter);
                 XDrawSegments (display, window, appInfo->rectGC, segments, 4);

                 /* restore the default line settings */
                 values.line_width = HIGHLIGHT_THICKNESS;
                 values.line_style = LineSolid;
                 XChangeGC(display, appInfo->rectGC, GCLineWidth | GCLineStyle,
                           &values);

             }


             /* This procedure sets the highlight rectangle and
              * redraws the rectangles.  The expose routine will draw
              * the highlight around the highlighted rectangle.
              */
             /* ARGSUSED */



        May 9, 1992                                             B-51








        OSF/Motif Programmer's Guide


             void
             #ifdef _NO_PROTO
             RectHighlight(w, rect)
             Widget w;
             RectPtr rect;
             #else
             RectHighlight(Widget w, RectPtr rect)
             #endif /* _NO_PROTO */
             {

                 if (appInfo->highlightRect != rect) {
                     appInfo->highlightRect = rect;
                     RedrawRectangles(w);
                 }

             }

             /* This procedure sets the highlight rectangle to NULL and
              * redraws the rectangles.  The expose routine will clear
              * the highlight around the highlighted rectangle.
              */
             /* ARGSUSED */
             void
             #ifdef _NO_PROTO
             RectUnhighlight(w)
             Widget w;
             #else
             RectUnhighlight(Widget w)
             #endif /* _NO_PROTO */
             {

                 if (appInfo->highlightRect) {
                     appInfo->highlightRect = NULL;
                     RedrawRectangles(w);
                 }

             }

             /* This function creates and initialized a new rectangle */
             RectPtr
             #ifdef _NO_PROTO
             RectCreate(x, y, width, height, color, pixmap)
             Position x;
             Position y;
             Dimension width;
             Dimension height;
             Pixel color;
             Pixmap pixmap;
             #else
             RectCreate(Position x, Position y, Dimension width,
             Dimension height, Pixel color, Pixmap pixmap)



        B-52                                             May 9, 1992








                                       Drag and Drop Example Program


             #endif /* _NO_PROTO */
             {

                 RectPtr rect;

                 rect = (RectPtr)  XtMalloc(sizeof(RectStruct));

                 rect->x = x;
                 rect->y = y;
                 rect->width = width;
                 rect->height = height;
                 rect->color = color;
                 rect->pixmap = pixmap;

                 return(rect);

             }


             /* This procedure will move the rectangle to the end of the
              * rectangle display table (effectively raising it to top of
              * the displayed rectangles).
              */
             static void
             #ifdef _NO_PROTO
             RectToTop(rect)
             RectPtr rect;
             #else
             RectToTop(RectPtr rect)
             #endif /* _NO_PROTO */
             {

                 int    i, j;


                 if (rect) {

                     /* Get the index to the target rectangle */
                     for (i = 0; i < appInfo->numRects; i++) {
                         if (appInfo->rectDpyTable[i] == rect)
                             break;
                     }

                     /* Shift the other rectangles downward */
                     for (j = i; j < appInfo->numRects - 1; j++)
                         appInfo->rectDpyTable[j] = appInfo->rectDpyTable[j + 1];

                     /* Place the target rectangle at the end */
                     appInfo->rectDpyTable[j] = rect;

                 }



        May 9, 1992                                             B-53








        OSF/Motif Programmer's Guide


             }


             /* This procedure raises the rectangle to the top of the drawing
              * area */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             RectRaise(w, rect)
             Widget w;
             RectPtr rect;
             #else
             RectRaise(Widget w, RectPtr rect)
             #endif /* _NO_PROTO */
             {

                 RectToTop(rect);
                 RedrawRectangles(w);

             }


             /* This procedure moves the rectangle the the end of the display
              * stack, decrements the number of rectangles, and then frees the
              * rectangle.
              */
             void
             #ifdef _NO_PROTO
             RectFree(rect)
             RectPtr rect;
             #else
             RectFree(RectPtr rect)
             #endif /* _NO_PROTO */
             {

                 /* if the rectangle is registered */
                 if (rect) {

                     RectToTop(rect);
                     appInfo->numRects--;
                     XtFree((char *)rect);

                 }

             }


             /* This procedure added the rectangle to the rectangle display
              * table (reallocing the table if necessary).
              */
             void



        B-54                                             May 9, 1992








                                       Drag and Drop Example Program


             #ifdef _NO_PROTO
             RectRegister(rect, x, y)
             RectPtr rect;
             #else
             RectRegister(RectPtr rect, Position x, Position y)
             #endif /* _NO_PROTO */
             {

                 appInfo->numRects++;

                 /* rectangles can have their x and y values reset at
                  * registration time */
                 rect->x = x;
                 rect->y = y;

                 /* realloc the table if it is too small */
                 if (appInfo->numRects > appInfo->rectsAllocd) {

                     /* grow geometrically */
                     appInfo->rectsAllocd *= 2;
                     appInfo->rectDpyTable = (RectPtr *)
                          XtRealloc((char *) appInfo->rectDpyTable,
                          (unsigned) (sizeof(RectPtr) * appInfo->rectsAllocd));

                 }

                 /* Add to end of display table */
                 appInfo->rectDpyTable[appInfo->numRects - 1] = rect;

             }


             /* This function find the top most rectangle at the given x,y
              * position */
             RectPtr
             #ifdef _NO_PROTO
             RectFind(x, y)
             Position x;
             Position y;
             #else
             RectFind(Position x, Position y)
             #endif /* _NO_PROTO */
             {

                 RectPtr rect;
                 int     i;

                 /*
                  * Search from the end of the rectangle display table
                     * to find the top most rectangle.
                     */



        May 9, 1992                                             B-55








        OSF/Motif Programmer's Guide


                 for (i = appInfo->numRects - 1; i >= 0; i--) {

                     rect = appInfo->rectDpyTable[i];
                     if (rect->x <= x && rect->x + rect->width >= x &&
                         rect->y <= y && rect->y + rect->height >= y) {
                         return(rect);
                     }

                 }

                 /* If a rectangle is not found return NULL */
                 return(NULL);

             }


             /* This procedure sets the retangle's color */
             void
             #ifdef _NO_PROTO
             RectSetColor(rect, display, window, color)
             RectPtr rect;
             Display *display;
             Window window;
             Pixel color;
             #else
             RectSetColor(RectPtr rect, Display *display, Window window,
                          Pixel color)
             #endif /* _NO_PROTO */
             {

                 rect->color = color;
                 RectDraw(display, window, rect);

             }


             /* This function gets the retangle's color */
             Pixel
             #ifdef _NO_PROTO
             RectGetColor(rect)
             RectPtr rect;
             #else
             RectGetColor(RectPtr rect)
             #endif /* _NO_PROTO */
             {
                 return(rect->color);
             }


             /* This procedure sets the retangle's pixmap. The pixmap portion
              * of the rectangle is not currently being used.



        B-56                                             May 9, 1992








                                       Drag and Drop Example Program


              */
             /* ARGSUSED */
             void
             #ifdef _NO_PROTO
             RectSetPixmap(rect, display, window, pixmap)
             RectPtr rect;
             Display *display;
             Window window;
             Pixmap pixmap;
             #else
             RectSetPixmap(RectPtr rect, Display *display, Window window,
                           Pixmap pixmap)
             #endif /* _NO_PROTO */
             {

                 rect->pixmap = pixmap; /* not currently being looked at */
                 RectDraw(display, window, rect);

             }


             /* This function gets the retangle's pixmap. The pixmap portion of
              * the rectangle is not currently being used.
              */
             /* ARGSUSED */
             static Pixmap
             #ifdef _NO_PROTO
             RectGetPixmap(rect)
             RectPtr rect;
             #else
             RectGetPixmap(RectPtr rect)
             #endif /* _NO_PROTO */
             {
                 return (rect->pixmap);
             }


             /* This procedure gets the retangle's height and width.  */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             RectGetDimensions(rect, width, height)
             RectPtr rect;
             Dimension *width;
             Dimension *height;
             #else
             RectGetDimensions(RectPtr rect, Dimension *width,
                               Dimension *height)
             #endif /* _NO_PROTO */
             {




        May 9, 1992                                             B-57








        OSF/Motif Programmer's Guide


                 *width = rect->width;
                 *height = rect->height;

             }


             /* This function creates the rectangle bitmaps for the icon. */
             Pixmap
             #ifdef _NO_PROTO
             GetBitmapFromRect(w, rect, background, foreground, widthRtn,
                               heightRtn)
             Widget w;
             RectPtr rect;
             Pixel background;
             Pixel foreground;
             Dimension *widthRtn;
             Dimension *heightRtn;
             #else
             GetBitmapFromRect(Widget w, RectPtr rect, Pixel background,
             Pixel foreground, Dimension *widthRtn, Dimension *heightRtn)
             #endif /* _NO_PROTO */
             {

                 Dimension width, height, maxHeight, maxWidth;
                 GC fillGC;
                 Pixmap icon_pixmap;
                 Display *display = XtDisplay(w);
                 XGCValues values;

                 RectGetDimensions(rect, &width, &height);

                 /* Get the maximum allowable width and height allowed by the
                  * cursor */
                 maxWidth = appInfo->maxCursorWidth;
                 maxHeight = appInfo->maxCursorHeight;

                 /* if the dimensions aren't within the allowable dimensions
                  * resize then proportionally
                */
                 if (maxWidth < width || maxHeight < height) {

                     if (width > height) {
                         height = (height * maxWidth) / width;
                         width = appInfo->maxCursorWidth;
                     } else {
                         width = (width * maxHeight) / height;
                         height = appInfo->maxCursorHeight;
                     }

                 }




        B-58                                             May 9, 1992








                                       Drag and Drop Example Program


                 /* Create a depth 1 pixmap (bitmap) for use with the drag
                  * icon */
                 icon_pixmap = XCreatePixmap(display, XtWindow(w), width,
                                             height, 1);

                 /* create a GC for drawing into the bitmap */
                 fillGC = XCreateGC(display, icon_pixmap, 0,
                                    (XGCValues *)NULL);

                 /* fill the bitmap with 0's as a starting point */
                 XFillRectangle(display, icon_pixmap, fillGC, 0, 0, width,
                                height);

                 /* Change GC to be able to create the rectangle with 1's on
                  * the bitmap */
                 values.foreground = 1;
                 XChangeGC(display, fillGC, GCForeground, &values);

                 /*
                  * This draw a filled rectangle.  If only a outline is desired
                  * use the XDrawRectangle() call.  Note: the outline does not
                  * produce very effect icon melting.
                  */
                 XFillRectangle(display, icon_pixmap, fillGC, 0, 0, width,
                                height);

                 /* Free the fill GC */
                 XFreeGC(display, fillGC);

                 *widthRtn = width;
                 *heightRtn = height;

                 return(icon_pixmap);

             }


             /*************************************************************
              *************************************************************
                           Functions used in Drawing Outlines:
              *************************************************************
              *************************************************************/

             /*
              * This procedure changes the GC to do rubberband
              * drawing of a rectangle frame .
              */
             static void
             #ifdef _NO_PROTO
             SetXorGC(w)
             Widget w;



        May 9, 1992                                             B-59








        OSF/Motif Programmer's Guide


             #else
             SetXorGC(Widget w)
             #endif /* _NO_PROTO */
             {

                 unsigned long valueMask = GCFunction | GCForeground |
                                           GCLineWidth;
                 XGCValues values;

                 values.function = GXxor;
                 values.foreground = GetColor(DRAW_AREA_BG_COLOR);
                 values.line_width = 1;
                 XChangeGC(XtDisplay(w), appInfo->rectGC, valueMask, &values);

             }


             /* This procedure returns the GC to it's initial state.  */
             static void
             #ifdef _NO_PROTO
             SetNormGC(w)
             Widget w;
             #else
             SetNormGC(Widget w)
             #endif /* _NO_PROTO */
             {

                 unsigned long valueMask = GCFunction | GCLineWidth |
                                           GCForeground;
                 XGCValues values;

                 values.function = GXcopy;
                 values.foreground = appInfo->currentColor;
                 values.line_width = HIGHLIGHT_THICKNESS;
                 XChangeGC(XtDisplay(w), appInfo->rectGC, valueMask, &values);

             }


             /* This procedure returns the values of the current rectangle
              * outline */
             static void
             #ifdef _NO_PROTO
             OutlineGetDimensions(x, y, width, height)
             Position *x;
             Position *y;
             Dimension *width;
             Dimension *height;
             #else
             OutlineGetDimensions(Position *x, Position *y, Dimension *width,
             Dimension *height)



        B-60                                             May 9, 1992








                                       Drag and Drop Example Program


             #endif /* _NO_PROTO */
             {

                 if (appInfo->rectX < appInfo->rectX2) {
                     *x = appInfo->rectX;
                     *width = appInfo->rectX2 - *x;
                 } else {
                     *x = appInfo->rectX2;
                     *width = appInfo->rectX - *x;
                 }

                 if (appInfo->rectY < appInfo->rectY2) {
                     *y = appInfo->rectY;
                     *height = appInfo->rectY2 - *y;
                 } else {
                     *y = appInfo->rectY2;
                     *height = appInfo->rectY - *y;
                 }

                 if (*width < 0)
                     *width = 1;
                 if (*height < 0)
                     *height = 1;

             }


             static void
             #ifdef _NO_PROTO
             OutlineDraw(w)
             Widget w;
             #else
             OutlineDraw(Widget w)
             #endif /* _NO_PROTO */
             {

                 Position    x, y;
                 Dimension    width, height;

                 OutlineGetDimensions(&x, &y, &width, &height);

                 XDrawRectangle(XtDisplay(w), XtWindow(w), appInfo->rectGC,
                                x, y, width, height);

             }


             /* This procedure sets initializes the drawing positions */
             static void
             #ifdef _NO_PROTO
             OutlineSetPosition(x, y)



        May 9, 1992                                             B-61








        OSF/Motif Programmer's Guide


             Position x;
             Position y;
             #else
             OutlineSetPosition(Position x, Position y)
             #endif /* _NO_PROTO */
             {

                 appInfo->rectX = appInfo->rectX2 = x;
                 appInfo->rectY = appInfo->rectY2 = y;

             }


             /* This procedure resets outline end position */
             static void
             #ifdef _NO_PROTO
             OutlineResetPosition(x, y)
             Position x;
             Position y;
             #else
             OutlineResetPosition(Position x, Position y)
             #endif /* _NO_PROTO */
             {

                 appInfo->rectX2 = x;
                 appInfo->rectY2 = y;

             }


             /* This action procedure begins creating a rectangle at the x,y
              * position of the button event if a rectangle doesn't already
              * exist at that position.  Otherwise is raises the rectangle
              * to the top of the drawing area.
              */
             /* ARGSUSED */
             void
             #ifdef _NO_PROTO
             StartRect(w, event, params, num_params)
             Widget w;
             XEvent *event;
             String *params;
             Cardinal *num_params;
             #else
             StartRect(Widget w, XEvent *event, String *params,
                       Cardinal *num_params)
             #endif /* _NO_PROTO */
             {

                 Display *display = XtDisplay(w);
                 RectPtr rect;



        B-62                                             May 9, 1992








                                       Drag and Drop Example Program


                 Position x = event->xbutton.x;
                 Position y = event->xbutton.y;

                 rect = RectFind(x, y);

                 /* if there isn't a rectangle at this position, begin creating
                  * one */
                 if (!rect) {

                     appInfo->creatingRect = True;
                     /* set gc for drawing rubberband outline for rectangles */
                     SetXorGC(w);
                     /* set the initial outline positions */
                     OutlineSetPosition(x, y);
                     /* Draw the rectangle */
                     OutlineDraw(w);

                 }
                 else
                     RectRaise(w, rect);

             }


             /* This action procedure extends the drawing of the outline
              * for the rectangle to be created.
              */
             /* ARGSUSED */
             void
             #ifdef _NO_PROTO
             ExtendRect(w, event, params, num_params)
             Widget w;
             XEvent *event;
             String *params;
             Cardinal *num_params;
             #else
             ExtendRect(Widget w, XEvent *event, String *params,
                        Cardinal *num_params)
             #endif /* _NO_PROTO */
             {

                 if (appInfo->creatingRect) {

                     /* erase the old outline */
                     OutlineDraw(w);
                     /* set the new outline end positions */
                     OutlineResetPosition(event->xbutton.x, event->xbutton.y);
                     /* redraw the outline */
                     OutlineDraw(w);

                 }



        May 9, 1992                                             B-63








        OSF/Motif Programmer's Guide


             }


             /* This action procedure creates a rectangle depending on the
              * dimensions set in the StartRect and ExtendRect action procs.
              */
             /* ARGSUSED */
             void
             #ifdef _NO_PROTO
             EndRect(w, event, params, num_params)
             Widget w;
             XEvent *event;
             String *params;
             Cardinal *num_params;
             #else
             EndRect(Widget w, XEvent *event, String *params,
                     Cardinal *num_params)
             #endif /* _NO_PROTO */
             {

                 Position     x, y;
                 Dimension    width, height;
                 RectPtr     rect;


                 if (appInfo->creatingRect) {

                     /* erase the last outline */
                     OutlineDraw(w);
                     /* return GC to original state */
                     SetNormGC(w);

                     /* Get the outline dimensions for creating the rectangle */
                     OutlineGetDimensions(&x, &y, &width, &height);

                     /* don't want to create zero width or height rectangles */
                     if (width == 0 || height == 0){
                         appInfo->creatingRect = False;
                         return;
                     }

                     rect = RectCreate(x, y, width, height,
                            GetColor(RECT_START_COLOR), XmUNSPECIFIED_PIXMAP);

                     RectDraw(XtDisplay(w), XtWindow(w), rect);
                     RectRegister(rect, x, y);
                     appInfo->creatingRect = False;

                 }

             }



        B-64                                             May 9, 1992








                                       Drag and Drop Example Program


             /* The procedure assigns new translations the the given widget */
             static void
             #ifdef _NO_PROTO
             SetupTranslations(widget, new_translations)
             Widget widget;
             char *new_translations;
             #else
             SetupTranslations(Widget widget, char *new_translations)
             #endif /* _NO_PROTO */
             {

                 XtTranslations new_table;

                 new_table = XtParseTranslationTable(new_translations);
                 XtOverrideTranslations(widget, new_table);

             }


             /* This procedure handles exposure events and makes a call to
              * RedrawRectangles() to redraw the rectangles
              * The rectangles at the top of the table are drawn first.
              */
             /* ARGSUSED */
             static void
             #ifdef _NO_PROTO
             HandleExpose(w, closure, call_data)
             Widget w;
             XtPointer closure;
             XtPointer call_data;
             #else
             HandleExpose(Widget w, XtPointer closure, XtPointer call_data)
             #endif /* _NO_PROTO */
             {
                 RedrawRectangles(w);
             }


             /* This procedure sets up the drawing area */
             static void
             #ifdef _NO_PROTO
             CreateDrawingArea(parent)
             Widget parent;
             #else
             CreateDrawingArea(Widget parent)
             #endif /* _NO_PROTO */
             {

                 static char da_translations[] =
                     "#replace <Btn2Down>: StartMove() \n\
                     <Btn1Down>: StartRect() \n\



        May 9, 1992                                             B-65








        OSF/Motif Programmer's Guide


                     <Btn1Motion>: ExtendRect() \n\
                     <Btn1Up>: EndRect() \n\
                     c <Key>t: XtDisplayTranslations()";

                 Arg             args[10];
                 int             n = 0;
                 XtTranslations    new_table;

                 new_table = XtParseTranslationTable(da_translations);

                 /* create drawing area at the top of the form */
                 n = 0;
                 XtSetArg(args[n], XmNtranslations, new_table); n++;
                 XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
                 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
                 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
                 XtSetArg(args[n], XmNwidth, 295); n++;
                 XtSetArg(args[n], XmNheight, 180); n++;
                 XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
                 XtSetArg(args[n], XmNbackground, GetColor(DRAW_AREA_BG_COLOR));
                 n++;
                 XtSetArg(args[n], XmNforeground, GetColor(DRAW_AREA_FG_COLOR));
                 n++;
                 drawingArea = XmCreateDrawingArea(parent, "drawingArea", args, n);
                 XtManageChild(drawingArea);

                 /* add expose callback to redisplay rectangles */
                 XtAddCallback(drawingArea, XmNexposeCallback, HandleExpose,
                               (XtPointer) NULL);

             }


             /* This procedure sets up the area for obtaining rectangle colors */
             static void
             #ifdef _NO_PROTO
             CreateColorPushButtons(parent, separator)
             Widget parent;
             Widget separator;
             #else
             CreateColorPushButtons(Widget parent, Widget separator)
             #endif /* _NO_PROTO */
             {

                 static char label_translations[] = "<Btn2Down>: ColorRect()";
                 Widget         bulletinBoard;
                 Widget         children[6];
                 XmString    csString;
                 Arg         args[10];
                 int         n = 0;




        B-66                                             May 9, 1992








                                       Drag and Drop Example Program


                 /* Creating an empty compound string so the labels will have
                  * no text. */
                 csString = XmStringCreateSimple("");

                 /* Creating 6 color labels */
                 n = 0;
                 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
                 XtSetArg(args[n], XmNtopWidget, separator); n++;
                 XtSetArg(args[n], XmNtopOffset, 2); n++;
                 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
                 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
                 XtSetArg(args[n], XmNwidth, 295); n++;
                 bulletinBoard = XmCreateBulletinBoard(parent, "buletinBoard",
                                                       args, n);
                 XtManageChild(bulletinBoard);

                 n = 0;
                 XtSetArg(args[n], XmNx, BOX_X_MARGIN); n++;
                 XtSetArg(args[n], XmNy, BOX_Y_MARGIN); n++;
                 XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
                 XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
                 XtSetArg(args[n], XmNlabelString, csString); n++;
                 XtSetArg(args[n], XmNbackground, GetColor(LABEL1_COLOR)); n++;
                 XtSetArg(args[n], XmNborderWidth, 1); n++;
                 children[0] = XmCreatePushButton(bulletinBoard, "PushButton1",
                                                  args, n);

                 /* add translations for manipulating rectangles */
                 SetupTranslations(children[0], label_translations);

                 n = 0;
                 XtSetArg(args[n], XmNx, BOX_X_MARGIN + BOX_X_OFFSET); n++;
                 XtSetArg(args[n], XmNy, BOX_Y_MARGIN); n++;
                 XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
                 XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
                 XtSetArg(args[n], XmNlabelString, csString); n++;
                 XtSetArg(args[n], XmNbackground, GetColor(LABEL2_COLOR)); n++;
                 XtSetArg(args[n], XmNborderWidth, 1); n++;
                 children[1] = XmCreatePushButton(bulletinBoard, "PushButton1",
                                                  args, n);

                 /* add translations for manipulating rectangles */
                 SetupTranslations(children[1], label_translations);

                 n = 0;
                 XtSetArg(args[n], XmNx, BOX_X_MARGIN + (2 * BOX_X_OFFSET)); n++;
                 XtSetArg(args[n], XmNy, BOX_Y_MARGIN); n++;
                 XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
                 XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
                 XtSetArg(args[n], XmNlabelString, csString); n++;
                 XtSetArg(args[n], XmNbackground, GetColor(LABEL3_COLOR)); n++;



        May 9, 1992                                             B-67








        OSF/Motif Programmer's Guide


                 XtSetArg(args[n], XmNborderWidth, 1); n++;
                 children[2] = XmCreatePushButton(bulletinBoard, "PushButton3",
                                                  args, n);

                 /* add translations for manipulating rectangles */
                 SetupTranslations(children[2], label_translations);

                 n = 0;
                 XtSetArg(args[n], XmNx, BOX_X_MARGIN); n++;
                 XtSetArg(args[n], XmNy, BOX_Y_MARGIN + BOX_Y_OFFSET); n++;
                 XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
                 XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
                 XtSetArg(args[n], XmNlabelString, csString); n++;
                 XtSetArg(args[n], XmNbackground, GetColor(LABEL4_COLOR)); n++;
                 XtSetArg(args[n], XmNborderWidth, 1); n++;
                 children[3] = XmCreatePushButton(bulletinBoard, "PushButton4",
                                                  args, n);

                 /* add translations for manipulating rectangles */
                 SetupTranslations(children[3], label_translations);

                 n = 0;
                 XtSetArg(args[n], XmNx, BOX_X_MARGIN + BOX_X_OFFSET); n++;
                 XtSetArg(args[n], XmNy, BOX_Y_MARGIN + BOX_Y_OFFSET); n++;
                 XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
                 XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
                 XtSetArg(args[n], XmNtopWidget, children[0]); n++;
                 XtSetArg(args[n], XmNlabelString, csString); n++;
                 XtSetArg(args[n], XmNbackground, GetColor(LABEL5_COLOR)); n++;
                 XtSetArg(args[n], XmNborderWidth, 1); n++;
                 children[4] = XmCreatePushButton(bulletinBoard, "PushButton5",
                                                  args, n);

                 /* add translations for manipulating rectangles */
                 SetupTranslations(children[4], label_translations);

                 n = 0;
                 XtSetArg(args[n], XmNx, BOX_X_MARGIN + (2 * BOX_X_OFFSET)); n++;
                 XtSetArg(args[n], XmNy, BOX_Y_MARGIN + BOX_Y_OFFSET); n++;
                 XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
                 XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
                 XtSetArg(args[n], XmNlabelString, csString); n++;
                 XtSetArg(args[n], XmNbackground, GetColor(LABEL6_COLOR)); n++;
                 XtSetArg(args[n], XmNborderWidth, 1); n++;
                 children[5] = XmCreatePushButton(bulletinBoard, "PushButton6",
                                                  args, n);

                 /* add translations for manipulating rectangles */
                 SetupTranslations(children[5], label_translations);

                 /* Managing the children all at once helps performance */



        B-68                                             May 9, 1992








                                       Drag and Drop Example Program


                 XtManageChildren(children, 6);

                 /* Freeing compound string.  It is no longer necessary. */
                 XmStringFree(csString);

             }


             /* This procedure initializes the rectangle display table */
             void
             #ifdef _NO_PROTO
             InitializeRectDpyTable()
             #else
             InitializeRectDpyTable(void)
             #endif /* _NO_PROTO */
             {
                 /*
                  * Initialize display table.  This is used to maintain the
                  * order in which the rectangles are displayed
                  */
                 appInfo->rectDpyTable =
                        (RectPtr *) XtMalloc((unsigned)sizeof(RectPtr));

                 /* Initialize rectangle counter.  This is used in reallocing
                  * the tables */
                 appInfo->rectsAllocd = 1;

             }


             /* This procedure creates the components to be displayed */
             void
             #ifdef _NO_PROTO
             CreateLayout()
             #else
             CreateLayout(void)
             #endif /* _NO_PROTO */
             {

                 Widget    mainWindow, form, separator;
                 Arg     args[10];
                 int     n = 0;

                 /* Create main window */
                 mainWindow = XmCreateMainWindow(topLevel, "mainWindow", args, n);
                 XtManageChild(mainWindow);

                 /* Create form for hold drawing area, separator, and color
                  * labels */
                 n = 0;
                 XtSetArg(args[n], XmNwidth, 300); n++;



        May 9, 1992                                             B-69








        OSF/Motif Programmer's Guide


                 form = XmCreateForm(mainWindow, "form", args, n);
                 XtManageChild(form);

                 /* Create area for drawing rectangles */
                 CreateDrawingArea(form);

                 /* Create separator to separate drawing area from color labels */
                 n = 0;
                 XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
                 XtSetArg(args[n], XmNtopWidget, drawingArea); n++;
                 XtSetArg(args[n], XmNtopOffset, 5); n++;
                 XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
                 XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
                 XtSetArg(args[n], XmNwidth, 300); n++;
                 separator = XmCreateSeparatorGadget(form, "separator", args, n);
                 XtManageChild(separator);

                 /* Create color labels for changing colors of buttons */
                 CreateColorPushButtons(form, separator);

                 /* Make form the work window of the main window */
                 n = 0;
                 XtSetArg(args[n], XmNworkWindow, form); n++;
                 XtSetValues(mainWindow, args, n);

             }


             /* This procedure initializes the GC for drawing rectangles */
             void
             #ifdef _NO_PROTO
             CreateRectGC()
             #else
             CreateRectGC(void)
             #endif /* _NO_PROTO */
             {

                 XGCValues    values;

                 values.line_style = LineSolid;
                 values.line_width = HIGHLIGHT_THICKNESS;
                 values.foreground = appInfo->currentColor =
                                     GetColor(RECT_START_COLOR);
                 appInfo->rectGC = XCreateGC(XtDisplay(topLevel),
                                     XtWindow(drawingArea),
                                     GCLineStyle | GCLineWidth | GCForeground,
                                     &values);

             }





        B-70                                             May 9, 1992






 
