1 /*
2  * Motif
3  *
4  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22 */
23 #ifdef REV_INFO
24 #ifndef lint
25 static char rcsid[] = "$TOG: DNDDraw.c /main/7 1997/03/31 13:33:37 dbl $"
26 #endif
27 #endif
28 /*
29  *    file: DNDDraw.c
30  *
31  *	File containing all the drawing routines needed to run DNDDemo
32  *	program.
33  *
34  */
35 
36 #include "DNDDemo.h"
37 static void	RectDraw(Display *, Window , RectPtr );
38 
39 
40 /* The following character arrays hold the bits for
41  * the source and state icons for both 32x32 and 16x16 drag icons.
42  * The source is a color palette icon and the state is a paint brush icon.
43  */
44 unsigned char SOURCE_ICON_BITS[] = {
45     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0xaa, 0x02,
46     0x00, 0x50, 0x55, 0x07, 0x00, 0x28, 0x00, 0x0c, 0x00, 0x94, 0x42, 0x19,
47     0x00, 0xca, 0xe5, 0x33, 0x00, 0x85, 0xc6, 0x33, 0x80, 0x42, 0xe7, 0x33,
48     0x40, 0x81, 0xc3, 0x31, 0xa0, 0x00, 0x00, 0x38, 0x50, 0x00, 0x00, 0x1c,
49     0x28, 0x00, 0x00, 0x0e, 0x90, 0x02, 0x00, 0x07, 0xc8, 0x05, 0x80, 0x03,
50     0x90, 0x07, 0xc0, 0x01, 0x48, 0x05, 0xe0, 0x00, 0x90, 0x03, 0x70, 0x00,
51     0x08, 0x00, 0x30, 0x00, 0x10, 0x14, 0x30, 0x00, 0x08, 0x2a, 0x30, 0x00,
52     0x10, 0x34, 0x30, 0x00, 0x28, 0x2a, 0x60, 0x00, 0x50, 0x9c, 0xe2, 0x00,
53     0xa0, 0x40, 0xc4, 0x01, 0x40, 0x01, 0x84, 0x01, 0x80, 0x42, 0x84, 0x03,
54     0x00, 0x85, 0x03, 0x03, 0x00, 0x0a, 0x00, 0x03, 0x00, 0xf4, 0xff, 0x03,
55     0x00, 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00};
56 
57 unsigned char SOURCE_ICON_MASK[] = {
58     0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x07, 0x00, 0xf8, 0xff, 0x0f,
59     0x00, 0xfc, 0xff, 0x1f, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0xff, 0xff, 0x7f,
60     0x80, 0xff, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0x7f,
61     0xf0, 0xff, 0xff, 0x7f, 0xf8, 0xff, 0xff, 0x7f, 0xfc, 0xff, 0xff, 0x7f,
62     0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x0f,
63     0xfc, 0xff, 0xff, 0x07, 0xfc, 0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0x01,
64     0xfc, 0xff, 0xff, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0xfc, 0xff, 0x7f, 0x00,
65     0xfc, 0xff, 0xff, 0x00, 0xfc, 0xff, 0xff, 0x01, 0xfc, 0xff, 0xff, 0x03,
66     0xf8, 0xff, 0xff, 0x03, 0xf0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07,
67     0xc0, 0xff, 0xff, 0x07, 0x80, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x07,
68     0x00, 0xfe, 0xff, 0x07, 0x00, 0xfc, 0xff, 0x03};
69 
70 unsigned char STATE_ICON_BITS[] = {
71     0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
72     0xf8, 0x01, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0xf8, 0x03, 0x00, 0x00,
73     0xf0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0xc0, 0x0d, 0x00, 0x00,
74     0x00, 0x1b, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
75     0x00, 0xfc, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00,
76     0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80, 0x1f, 0x00,
77     0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfc, 0x00,
78     0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0xe0, 0x03,
79     0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x1f,
80     0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x38,
81     0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0xc0};
82 
83 unsigned char STATE_ICON_MASK[] = {
84     0x3f, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00,
85     0xfc, 0x03, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00,
86     0xfc, 0x07, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00,
87     0xe0, 0x1f, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,
88     0x00, 0xfc, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00, 0xf0, 0x03, 0x00,
89     0x00, 0xe0, 0x07, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x80, 0x1f, 0x00,
90     0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0xfc, 0x03,
91     0x00, 0x00, 0xf8, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x0f,
92     0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x7f,
93     0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0xfe,
94     0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0xf0};
95 
96 unsigned char INVALID_ICON_BITS[] = {
97     0x00, 0xe0, 0x0f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xff, 0xff, 0x01,
98     0x80, 0xff, 0xff, 0x03, 0xc0, 0x1f, 0xf0, 0x07, 0xe0, 0x07, 0xc0, 0x0f,
99     0xf0, 0x07, 0x00, 0x1f, 0xf8, 0x0f, 0x00, 0x3e, 0xf8, 0x1f, 0x00, 0x3c,
100     0xfc, 0x3f, 0x00, 0x7c, 0x3c, 0x7f, 0x00, 0x78, 0x3c, 0xfe, 0x00, 0x78,
101     0x1e, 0xfc, 0x01, 0xf0, 0x1e, 0xf8, 0x03, 0xf0, 0x1e, 0xf0, 0x07, 0xf0,
102     0x1e, 0xe0, 0x0f, 0xf0, 0x1e, 0xc0, 0x1f, 0xf0, 0x1e, 0x80, 0x3f, 0xf0,
103     0x1e, 0x00, 0x7f, 0xf0, 0x3c, 0x00, 0xfe, 0x78, 0x3c, 0x00, 0xfc, 0x79,
104     0x7c, 0x00, 0xf8, 0x7f, 0x78, 0x00, 0xf0, 0x3f, 0xf8, 0x00, 0xe0, 0x3f,
105     0xf0, 0x01, 0xc0, 0x1f, 0xe0, 0x07, 0xc0, 0x0f, 0xc0, 0x1f, 0xf0, 0x07,
106     0x80, 0xff, 0xff, 0x03, 0x00, 0xff, 0xff, 0x01, 0x00, 0xfc, 0x7f, 0x00,
107     0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00};
108 
109 unsigned char SMALL_SOURCE_ICON_BITS[] = {
110     0x80, 0x1f, 0x40, 0x60, 0x20, 0x91, 0x90, 0xaa, 0x08, 0x91, 0x08, 0x40,
111     0x08, 0x20, 0x08, 0x10, 0x28, 0x10, 0x78, 0x10, 0x28, 0x20, 0x08, 0x41,
112     0x90, 0x43, 0x20, 0x21, 0x40, 0x10, 0x80, 0x0f};
113 
114 unsigned char SMALL_SOURCE_ICON_MASK[] = {
115     0x80, 0x1f, 0xc0, 0x7f, 0xe0, 0xff, 0xf0, 0xff, 0xf8, 0xff, 0xf8, 0x7f,
116     0xf8, 0x3f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x3f, 0xf8, 0x7f,
117     0xf0, 0x7f, 0xe0, 0x3f, 0xc0, 0x1f, 0x80, 0x0f};
118 
119 unsigned char SMALL_STATE_ICON_BITS[] = {
120     0x0f, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x3c, 0x00, 0x50, 0x00, 0xe0, 0x00,
121     0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x18,
122     0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00};
123 
124 unsigned char SMALL_STATE_ICON_MASK[] = {
125     0x0f, 0x00, 0x1e, 0x00, 0x1e, 0x00, 0x3c, 0x00, 0x70, 0x00, 0xe0, 0x00,
126     0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c, 0x00, 0x18,
127     0x00, 0x20, 0x00, 0x40, 0x00, 0x80, 0x00, 0x00};
128 
129 unsigned char SMALL_INVALID_ICON_BITS[] = {
130     0xe0, 0x03, 0xf8, 0x0f, 0x1c, 0x1c, 0x1e, 0x30, 0x3e, 0x30, 0x73, 0x60,
131     0xe3, 0x60, 0xc3, 0x61, 0x83, 0x63, 0x03, 0x67, 0x06, 0x3e, 0x06, 0x3c,
132     0x1c, 0x1c, 0xf8, 0x0f, 0xe0, 0x03, 0x00, 0x00};
133 
134 
135 /* Globals variables */
136 AppInfo appInfo;
137 
138 
139 /* This is a string to pixel conversion function. */
140 Pixel
GetColor(char * colorstr)141 GetColor(char *colorstr)
142 {
143 
144     XrmValue    from, to;
145 
146     from.size = strlen(colorstr) +1;
147     if (from.size < sizeof(String))
148         from.size = sizeof(String);
149     from.addr = colorstr;
150     to.addr = NULL;
151     XtConvert(topLevel, XmRString, &from, XmRPixel, &to);
152 
153     if (to.addr != NULL)
154         return ((Pixel) *((Pixel *) to.addr));
155     else
156         return ( (XtArgVal) NULL);
157 
158 }
159 
160 
161 /* This procedure is used to initalize the application information structure */
162 void
InitializeAppInfo(void)163 InitializeAppInfo(void)
164 {
165 
166     if (!appInfo) {
167 
168         appInfo = (AppInfo) XtMalloc(sizeof(AppInfoRec));
169         appInfo->rectGC = NULL;
170         appInfo->currentColor = 0;
171         appInfo->rectDpyTable = NULL;
172         appInfo->rectsAllocd = 0;
173         appInfo->numRects = 0;
174         appInfo->highlightRect = NULL;
175         appInfo->clearRect = NULL;
176         appInfo->doMove = True;
177         appInfo->creatingRect = True;
178         appInfo->operation = XmDROP_MOVE;
179         appInfo->maxCursorWidth = 64;
180         appInfo->maxCursorHeight = 64;
181         appInfo->rectX = 0;
182         appInfo->rectY = 0;
183         appInfo->rectX2 = 0;
184         appInfo->rectY2 = 0;
185 
186     }
187 
188 }
189 
190 
191 /* This procedure sets the color in the GC for drawing the rectangles
192  * in a new color.
193  */
194 void
SetColor(Display * display,Pixel color)195 SetColor(Display *display, Pixel color)
196 {
197 
198     /*
199      * if the GC already has a foreground of this color,
200      * it would be wasteful to reset the color
201      */
202     if (color != appInfo->currentColor) {
203         XSetForeground(display, appInfo->rectGC, (unsigned long) color);
204         appInfo->currentColor = color;
205     }
206 
207 }
208 
209 
210 /* This function draws the rectangle in the color provided */
211 static void
RectDraw(Display * display,Window window,RectPtr rect)212 RectDraw(Display *display, Window window, RectPtr rect)
213 {
214 
215     SetColor(display, rect->color);
216     XFillRectangle(display, window, appInfo->rectGC, rect->x,
217                    rect->y, rect->width, rect->height);
218 
219 }
220 
221 
222 /* This procedure draws the rectangle highlight in a specified color*/
223 static void
RectDrawHighlight(Widget w,RectPtr rect,Pixel color)224 RectDrawHighlight( Widget w, RectPtr rect, Pixel color )
225 {
226 
227     Display *display = XtDisplay(w);
228     Window window = XtWindow(w);
229     Pixel currentColor = rect->color;
230     XGCValues values;
231 
232     values.foreground = color;
233     XChangeGC(display, appInfo->rectGC, GCForeground, &values);
234 
235     XDrawRectangle(display, window, appInfo->rectGC,
236                    rect->x + 1, rect->y + 1,
237                    rect->width - HIGHLIGHT_THICKNESS,
238                    rect->height - HIGHLIGHT_THICKNESS);
239 
240     /* Return the GC to it's previous state */
241     values.foreground = appInfo->currentColor = currentColor;
242     XChangeGC(display, appInfo->rectGC, GCForeground, &values);
243 
244 }
245 
246 
247 /* This procedure handles redrawing the rectangles.  It draws
248  * them according to the order in the rectangle display table.
249  * The rectangles at the top of the table are drawn first.
250  */
251 void
RedrawRectangles(Widget w)252 RedrawRectangles(Widget w)
253 {
254 
255     Display *display = XtDisplay(w);
256     RectPtr rect;
257     Window window = XtWindow(w);
258     int i;
259 
260     for (i = 0; i < appInfo->numRects; i++) {
261 
262         rect = appInfo->rectDpyTable[i];
263         /* Only draw the rectangles that haven't been cleared */
264         if (rect != appInfo->clearRect) {
265             RectDraw(display, window, rect);
266         }
267         /* Draw the rectangle highlight of the highlight rectangle */
268         if (rect == appInfo->highlightRect) {
269             RectDrawHighlight(w, rect, GetColor(HIGHLIGHT_COLOR));
270         }
271 
272     }
273 
274 }
275 
276 
277 /* This procedure will clear the current rectangle and redraw any rectangles
278  * that were partially cleared by the rectangle that was deleted.
279  */
280 /* ARGSUSED */
281 void
RectHide(Display * display,Window window,RectPtr rect)282 RectHide(Display *display, Window window, RectPtr rect)
283 {
284 
285     Pixel background, oldColor;
286     Arg args[1];
287 
288     /* Get the background of the drawing area. */
289     XtSetArg(args[0], XmNbackground, &background);
290     XtGetValues(drawingArea, args, 1);
291 
292     /* Save the old color for restoration purposes. */
293     oldColor = rect->color;
294 
295     /* Clear the rectangle */
296     rect->color = background;
297     RectDraw(display, window, rect);
298     appInfo->clearRect = rect;
299 
300     /* redraw the rest of the rectangles */
301     RedrawRectangles(drawingArea);
302 
303     /* restore the rectangle color */
304     rect->color = oldColor;
305 
306 }
307 
308 /* This procedure draws the stipple rectangle that is used in marking
309  * the old rectangle position during a rectangle move operation.
310  */
311 /* ARGSUSED */
312 void
RectDrawStippled(Display * display,Window window,RectPtr rect)313 RectDrawStippled(Display *display, Window window, RectPtr rect)
314 {
315 
316     register int x = rect->x;
317     register int y = rect->y;
318     register Dimension width = rect->width;
319     register Dimension height = rect->height;
320     XGCValues values;
321     XSegment segments[4];
322 
323     /* Set the rectangle color */
324     values.foreground = appInfo->currentColor = rect->color;
325     XChangeGC(display, appInfo->rectGC, GCForeground , &values);
326 
327     /* Create the segments for drawing the stippled rectangle */
328     segments[0].x1 = segments[2].x1 = x;
329     segments[0].y1 = segments[0].y2 = y;
330     segments[0].x2 = x + width - 1;
331     segments[1].x1 = segments[1].x2 = x + width - 1;
332     segments[1].y1 = segments[3].y1 = y;
333     segments[3].y2 = y + height;
334     segments[2].y1 = segments[2].y2 = y + height - 1;
335     segments[3].x1 = segments[3].x2 = x;
336     segments[2].x2 = x + width;
337     segments[1].y2 = y + height;
338 
339     /* Set the line attributes and draw */
340     XSetLineAttributes(display, appInfo->rectGC, 1, LineOnOffDash,
341         CapButt, JoinMiter);
342     XDrawSegments (display, window, appInfo->rectGC, segments, 4);
343 
344     /* restore the default line settings */
345     values.line_width = HIGHLIGHT_THICKNESS;
346     values.line_style = LineSolid;
347     XChangeGC(display, appInfo->rectGC, GCLineWidth | GCLineStyle, &values);
348 
349 }
350 
351 
352 /* This procedure sets the highlight rectangle and
353  * redraws the rectangles.  The expose routine will draw
354  * the highlight around the highlighted rectangle.
355  */
356 /* ARGSUSED */
357 void
RectHighlight(Widget w,RectPtr rect)358 RectHighlight(Widget w, RectPtr rect)
359 {
360 
361     if (appInfo->highlightRect != rect) {
362         appInfo->highlightRect = rect;
363         RedrawRectangles(w);
364     }
365 
366 }
367 
368 /* This procedure sets the highlight rectangle to NULL and
369  * redraws the rectangles.  The expose routine will clear
370  * the highlight around the highlighted rectangle.
371  */
372 /* ARGSUSED */
373 void
RectUnhighlight(Widget w)374 RectUnhighlight(Widget w)
375 {
376 
377     if (appInfo->highlightRect) {
378         appInfo->highlightRect = NULL;
379         RedrawRectangles(w);
380     }
381 
382 }
383 
384 /* This function creates and initialized a new rectangle */
385 RectPtr
RectCreate(Position x,Position y,Dimension width,Dimension height,Pixel color,Pixmap pixmap)386 RectCreate(Position x, Position y, Dimension width,
387 Dimension height, Pixel color, Pixmap pixmap)
388 {
389 
390     RectPtr rect;
391 
392     rect = (RectPtr)  XtMalloc(sizeof(RectStruct));
393 
394     rect->x = x;
395     rect->y = y;
396     rect->width = width;
397     rect->height = height;
398     rect->color = color;
399     rect->pixmap = pixmap;
400 
401     return(rect);
402 
403 }
404 
405 
406 /* This procedure will move the rectangle to the end of the rectangle
407  * display table (effectively raising it to top of the displayed
408  * rectangles).
409  */
410 static void
RectToTop(RectPtr rect)411 RectToTop(RectPtr rect)
412 {
413 
414     int    i, j;
415 
416 
417     if (rect) {
418 
419         /* Get the index to the target rectangle */
420         for (i = 0; i < appInfo->numRects; i++) {
421             if (appInfo->rectDpyTable[i] == rect)
422                 break;
423         }
424 
425         /* Shift the other rectangles downward */
426         for (j = i; j < appInfo->numRects - 1; j++)
427             appInfo->rectDpyTable[j] = appInfo->rectDpyTable[j + 1];
428 
429         /* Place the target rectangle at the end */
430         appInfo->rectDpyTable[j] = rect;
431 
432     }
433 
434 }
435 
436 
437 /* This procedure raises the rectangle to the top of the drawing area */
438 /* ARGSUSED */
439 static void
RectRaise(Widget w,RectPtr rect)440 RectRaise(Widget w, RectPtr rect)
441 {
442 
443     RectToTop(rect);
444     RedrawRectangles(w);
445 
446 }
447 
448 
449 /* This procedure moves the rectangle the the end of the display stack,
450  * decrements the number of rectangles, and then frees the rectangle.
451  */
452 void
RectFree(RectPtr rect)453 RectFree(RectPtr rect)
454 {
455 
456     /* if the rectangle is registered */
457     if (rect) {
458 
459         RectToTop(rect);
460         appInfo->numRects--;
461         XtFree((char *)rect);
462 
463     }
464 
465 }
466 
467 
468 /* This procedure added the rectangle to the rectangle display table
469  * (reallocing the table if necessary).
470  */
471 void
RectRegister(RectPtr rect,Position x,Position y)472 RectRegister(RectPtr rect, Position x, Position y)
473 {
474 
475     appInfo->numRects++;
476 
477     /* rectangles can have their x and y values reset at registration time */
478     rect->x = x;
479     rect->y = y;
480 
481     /* realloc the table if it is too small */
482     if (appInfo->numRects > appInfo->rectsAllocd) {
483 
484         /* grow geometrically */
485         appInfo->rectsAllocd *= 2;
486         appInfo->rectDpyTable = (RectPtr *)
487                                  XtRealloc((char *) appInfo->rectDpyTable,
488                                            (unsigned) (sizeof(RectPtr) *
489                                            appInfo->rectsAllocd));
490 
491     }
492 
493     /* Add to end of display table */
494     appInfo->rectDpyTable[appInfo->numRects - 1] = rect;
495 
496 }
497 
498 
499 /* This function find the top most rectangle at the given x,y position */
500 RectPtr
RectFind(Position x,Position y)501 RectFind(Position x, Position y)
502 {
503 
504     RectPtr rect;
505     int     i;
506 
507     /*
508      * Search from the end of the rectangle display table
509         * to find the top most rectangle.
510         */
511     for (i = appInfo->numRects - 1; i >= 0; i--) {
512 
513         rect = appInfo->rectDpyTable[i];
514         if (rect->x <= x && rect->x + rect->width >= x &&
515             rect->y <= y && rect->y + rect->height >= y) {
516             return(rect);
517         }
518 
519     }
520 
521     /* If a rectangle is not found return NULL */
522     return(NULL);
523 
524 }
525 
526 
527 /* This procedure sets the retangle's color */
528 void
RectSetColor(RectPtr rect,Display * display,Window window,Pixel color)529 RectSetColor(RectPtr rect, Display *display, Window window, Pixel color)
530 {
531 
532     rect->color = color;
533     RectDraw(display, window, rect);
534 
535 }
536 
537 
538 /* This function gets the retangle's color */
539 Pixel
RectGetColor(RectPtr rect)540 RectGetColor(RectPtr rect)
541 {
542     return(rect->color);
543 }
544 
545 
546 /* This procedure sets the retangle's pixmap. The pixmap portion of the
547  * rectangle is not currently being used.
548  */
549 /* ARGSUSED */
550 void
RectSetPixmap(RectPtr rect,Display * display,Window window,Pixmap pixmap)551 RectSetPixmap(RectPtr rect, Display *display, Window window, Pixmap pixmap)
552 {
553 
554     rect->pixmap = pixmap; /* not currently being looked at */
555     RectDraw(display, window, rect);
556 
557 }
558 
559 
560 /* This function gets the retangle's pixmap. The pixmap portion of the
561  * rectangle is not currently being used.
562  */
563 /* ARGSUSED */
564 static Pixmap
RectGetPixmap(RectPtr rect)565 RectGetPixmap(RectPtr rect)
566 {
567     return (rect->pixmap);
568 }
569 
570 
571 /* This procedure gets the retangle's height and width.  */
572 /* ARGSUSED */
573 static void
RectGetDimensions(RectPtr rect,Dimension * width,Dimension * height)574 RectGetDimensions(RectPtr rect, Dimension *width, Dimension *height)
575 {
576 
577     *width = rect->width;
578     *height = rect->height;
579 
580 }
581 
582 
583 /* This function creates the rectangle bitmaps for the icon. */
584 Pixmap
GetBitmapFromRect(Widget w,RectPtr rect,Pixel background,Pixel foreground,Dimension * widthRtn,Dimension * heightRtn)585 GetBitmapFromRect(Widget w, RectPtr rect, Pixel background, Pixel foreground,
586 Dimension *widthRtn, Dimension *heightRtn)
587 {
588     Dimension width, height, maxHeight, maxWidth;
589     GC fillGC;
590     Pixmap icon_pixmap;
591     Display *display = XtDisplay(w);
592     XGCValues values;
593     unsigned long mask;
594 
595     RectGetDimensions(rect, &width, &height);
596 
597     /* Get the maximum allowable width and height allowed by the cursor */
598     maxWidth = appInfo->maxCursorWidth;
599     maxHeight = appInfo->maxCursorHeight;
600 
601     /* if the dimensions aren't within the allowable dimensions resize
602    * then proportionally
603    */
604     if (maxWidth < width || maxHeight < height) {
605 
606         if (width > height) {
607             height = (height * maxWidth) / width;
608             width = appInfo->maxCursorWidth;
609         } else {
610             width = (width * maxHeight) / height;
611             height = appInfo->maxCursorHeight;
612         }
613 
614     }
615 
616     /* Create a depth 1 pixmap (bitmap) for use with the drag icon */
617     icon_pixmap = XCreatePixmap(display, XtWindow(w), width, height, 1);
618 
619     mask = GCFunction | GCForeground | GCBackground;
620     values.foreground = 1;
621     values.background = 0;
622     values.function = GXcopy;
623     /* create a GC for drawing into the bitmap */
624     fillGC = XCreateGC(display, icon_pixmap, mask, &values);
625 
626     /*
627      * This draws a filled rectangle.  If only an outline is desired
628      * use a XDrawRectangle() call.  Note: the outline does not
629      * produce a very nice melt effect.
630      */
631     XFillRectangle(display, icon_pixmap, fillGC, 0, 0, width, height);
632 
633     /* Free the fill GC */
634     XFreeGC(display, fillGC);
635 
636     *widthRtn = width;
637     *heightRtn = height;
638 
639     return(icon_pixmap);
640 
641 }
642 
643 
644 /***************************************************************************
645  ***************************************************************************
646                   Functions used in Drawing Outlines:
647  ***************************************************************************
648  ***************************************************************************/
649 
650 /*
651  * This procedure changes the GC to do rubberband
652  * drawing of a rectangle frame .
653  */
654 static void
SetXorGC(Widget w)655 SetXorGC(Widget w)
656 {
657 
658     unsigned long valueMask = GCFunction | GCForeground | GCLineWidth |
659                               GCPlaneMask;
660     XGCValues values;
661     Pixel bg, fg;
662 
663 
664     XtVaGetValues (w, XmNbackground, &bg, XmNforeground, &fg, NULL);
665 
666     values.function = GXxor;
667     values.plane_mask = fg^bg;   /* Better fix for 5127 */
668     values.foreground = bg;
669     values.line_width = 1;
670     XChangeGC(XtDisplay(w), appInfo->rectGC, valueMask, &values);
671 
672 }
673 
674 
675 /* This procedure returns the GC to it's initial state.  */
676 static void
SetNormGC(Widget w)677 SetNormGC(Widget w)
678 {
679 
680     unsigned long valueMask = GCFunction | GCLineWidth | GCForeground |
681       			      GCPlaneMask;
682     XGCValues values;
683 
684     values.function = GXcopy;
685     values.foreground = appInfo->currentColor;
686     values.line_width = HIGHLIGHT_THICKNESS;
687     values.plane_mask = 0xFFFFFFFF;
688     XChangeGC(XtDisplay(w), appInfo->rectGC, valueMask, &values);
689 
690 }
691 
692 
693 /* This procedure returns the values of the current rectangle outline */
694 static void
OutlineGetDimensions(Position * x,Position * y,Dimension * width,Dimension * height)695 OutlineGetDimensions(Position *x, Position *y, Dimension *width,
696 Dimension *height)
697 {
698 
699     if (appInfo->rectX < appInfo->rectX2) {
700         *x = appInfo->rectX;
701         *width = appInfo->rectX2 - *x;
702     } else {
703         *x = appInfo->rectX2;
704         *width = appInfo->rectX - *x;
705     }
706 
707     if (appInfo->rectY < appInfo->rectY2) {
708         *y = appInfo->rectY;
709         *height = appInfo->rectY2 - *y;
710     } else {
711         *y = appInfo->rectY2;
712         *height = appInfo->rectY - *y;
713     }
714 
715 }
716 
717 
718 static void
OutlineDraw(Widget w)719 OutlineDraw(Widget w)
720 {
721 
722     Position    x, y;
723     Dimension    width, height;
724 
725     OutlineGetDimensions(&x, &y, &width, &height);
726 
727     XDrawRectangle(XtDisplay(w), XtWindow(w), appInfo->rectGC,
728                    x, y, width, height);
729 
730 }
731 
732 
733 /* This procedure sets intializes the drawing positions */
734 static void
OutlineSetPosition(Position x,Position y)735 OutlineSetPosition(Position x, Position y)
736 {
737 
738     appInfo->rectX = appInfo->rectX2 = x;
739     appInfo->rectY = appInfo->rectY2 = y;
740 
741 }
742 
743 
744 /* This procedure resets outline end position */
745 static void
OutlineResetPosition(Position x,Position y)746 OutlineResetPosition(Position x, Position y)
747 {
748 
749     appInfo->rectX2 = x;
750     appInfo->rectY2 = y;
751 
752 }
753 
754 
755 /* This action procedure begins creating a rectangle at the x,y position
756  * of the button event if a rectangle doesn't already exist at
757  * that position.  Otherwise is raises the rectangle to the top
758  * of the drawing area.
759  */
760 /* ARGSUSED */
761 void
StartRect(Widget w,XEvent * event,String * params,Cardinal * num_params)762 StartRect(Widget w, XEvent *event, String *params, Cardinal *num_params)
763 {
764 
765     Display *display = XtDisplay(w);
766     RectPtr rect;
767     Position x = event->xbutton.x;
768     Position y = event->xbutton.y;
769 
770     rect = RectFind(x, y);
771 
772     /* if there isn't a rectangle at this position, begin creating one */
773     if (!rect) {
774 
775         appInfo->creatingRect = True;
776         /* set gc for drawing rubberband outline for rectangles */
777         SetXorGC(w);
778         /* set the initial outline positions */
779         OutlineSetPosition(x, y);
780         /* Draw the rectangle */
781         OutlineDraw(w);
782 
783     }
784     else
785         RectRaise(w, rect);
786 
787 }
788 
789 
790 /* This action procedure extends the drawing of the outline
791  * for the rectangle to be created.
792  */
793 /* ARGSUSED */
794 void
ExtendRect(Widget w,XEvent * event,String * params,Cardinal * num_params)795 ExtendRect(Widget w, XEvent *event, String *params, Cardinal *num_params)
796 {
797 
798     if (appInfo->creatingRect) {
799 
800         /* erase the old outline */
801         OutlineDraw(w);
802         /* set the new outline end positions */
803         OutlineResetPosition(event->xbutton.x, event->xbutton.y);
804         /* redraw the outline */
805         OutlineDraw(w);
806 
807     }
808 
809 }
810 
811 
812 /* This action procedure creates a rectangle depending on the
813  * dimensions set in the StartRect and ExtendRect action procs.
814  */
815 /* ARGSUSED */
816 void
EndRect(Widget w,XEvent * event,String * params,Cardinal * num_params)817 EndRect(Widget w, XEvent *event, String *params, Cardinal *num_params)
818 {
819 
820     Position     x, y;
821     Dimension    width, height;
822     RectPtr     rect;
823 
824 
825     if (appInfo->creatingRect) {
826 
827         /* erase the last outline */
828         OutlineDraw(w);
829         /* return GC to original state */
830         SetNormGC(w);
831 
832         /* Get the outline dimensions for creating the rectangle */
833         OutlineGetDimensions(&x, &y, &width, &height);
834 
835         /* we don't want to create zero width or height rectangles */
836         if (width == 0 || height == 0){
837             appInfo->creatingRect = False;
838             return;
839         }
840 
841         rect = RectCreate(x, y, width, height,
842                           GetColor(RECT_START_COLOR), XmUNSPECIFIED_PIXMAP);
843 
844         RectDraw(XtDisplay(w), XtWindow(w), rect);
845         RectRegister(rect, x, y);
846         appInfo->creatingRect = False;
847 
848     }
849 
850 }
851 
852 
853 /* The procedure assigns new translations the the given widget */
854 static void
SetupTranslations(Widget widget,char * new_translations)855 SetupTranslations(Widget widget, char *new_translations)
856 {
857 
858     XtTranslations new_table;
859 
860     new_table = XtParseTranslationTable(new_translations);
861     XtOverrideTranslations(widget, new_table);
862 
863 }
864 
865 
866 /* This procedure handles exposure events and makes a call to
867  * RedrawRectangles() to redraw the rectangles
868  * The rectangles at the top of the table are drawn first.
869  */
870 /* ARGSUSED */
871 static void
HandleExpose(Widget w,XtPointer closure,XtPointer call_data)872 HandleExpose(Widget w, XtPointer closure, XtPointer call_data)
873 {
874     RedrawRectangles(w);
875 }
876 
877 
878 /* This procedure sets up the drawing area */
879 static void
CreateDrawingArea(Widget parent)880 CreateDrawingArea(Widget parent)
881 {
882 
883     static char da_translations[] =
884         "#replace <Btn2Down>: StartMove() \n\
885         <Btn1Down>: StartRect() \n\
886         <Btn1Motion>: ExtendRect() \n\
887         <Btn1Up>: EndRect() \n\
888         c <Key>t: XtDisplayTranslations()";
889 
890     Arg             args[10];
891     int             n = 0;
892     XtTranslations    new_table;
893 
894     new_table = XtParseTranslationTable(da_translations);
895 
896     /* create drawing area at the top of the form */
897     n = 0;
898     XtSetArg(args[n], XmNtranslations, new_table); n++;
899     XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++;
900     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
901     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
902     XtSetArg(args[n], XmNwidth, 295); n++;
903     XtSetArg(args[n], XmNheight, 180); n++;
904     XtSetArg(args[n], XmNresizePolicy, XmRESIZE_NONE); n++;
905     XtSetArg(args[n], XmNbackground, GetColor(DRAW_AREA_BG_COLOR)); n++;
906     XtSetArg(args[n], XmNforeground, GetColor(DRAW_AREA_FG_COLOR)); n++;
907     drawingArea = XmCreateDrawingArea(parent, "drawingArea", args, n);
908     XtManageChild(drawingArea);
909 
910     /* add expose callback to redisplay rectangles */
911     XtAddCallback(drawingArea, XmNexposeCallback, HandleExpose,
912                   (XtPointer) NULL);
913 
914     /* add callbacks for UTM */
915     XtAddCallback(drawingArea, XmNdestinationCallback,
916 		  (XtCallbackProc) handleDestination, (XtPointer) NULL);
917     XtAddCallback(drawingArea, XmNconvertCallback,
918 		  (XtCallbackProc) RectConvert, (XtPointer) NULL);
919 }
920 
921 
922 /* This procedure sets up the area for obtaining rectangle colors */
923 static void
CreateColorPushButtons(Widget parent,Widget separator)924 CreateColorPushButtons(Widget parent, Widget separator)
925 {
926 
927     static char label_translations[] = "<Btn2Down>: ColorRect()";
928     Widget         bulletinBoard;
929     Widget         children[6];
930     XmString    csString;
931     Arg         args[10];
932     int         n = 0;
933 
934     /* Creating an empty compound string so the labels will have no text. */
935     csString = XmStringCreateSimple("");
936 
937     /* Creating 6 color labels */
938     n = 0;
939     XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
940     XtSetArg(args[n], XmNtopWidget, separator); n++;
941     XtSetArg(args[n], XmNtopOffset, 2); n++;
942     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
943     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
944     XtSetArg(args[n], XmNwidth, 295); n++;
945     bulletinBoard = XmCreateBulletinBoard(parent, "buletinBoard", args, n);
946     XtManageChild(bulletinBoard);
947 
948     n = 0;
949     XtSetArg(args[n], XmNx, BOX_X_MARGIN); n++;
950     XtSetArg(args[n], XmNy, BOX_Y_MARGIN); n++;
951     XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
952     XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
953     XtSetArg(args[n], XmNlabelString, csString); n++;
954     XtSetArg(args[n], XmNbackground, GetColor(LABEL1_COLOR)); n++;
955     XtSetArg(args[n], XmNborderWidth, 1); n++;
956     children[0] = XmCreatePushButton(bulletinBoard, "PushButton1", args, n);
957 
958     /* add translations for manipulating rectangles */
959     SetupTranslations(children[0], label_translations);
960 
961     n = 0;
962     XtSetArg(args[n], XmNx, BOX_X_MARGIN + BOX_X_OFFSET); n++;
963     XtSetArg(args[n], XmNy, BOX_Y_MARGIN); n++;
964     XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
965     XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
966     XtSetArg(args[n], XmNlabelString, csString); n++;
967     XtSetArg(args[n], XmNbackground, GetColor(LABEL2_COLOR)); n++;
968     XtSetArg(args[n], XmNborderWidth, 1); n++;
969     children[1] = XmCreatePushButton(bulletinBoard, "PushButton1", args, n);
970 
971     /* add translations for manipulating rectangles */
972     SetupTranslations(children[1], label_translations);
973 
974     n = 0;
975     XtSetArg(args[n], XmNx, BOX_X_MARGIN + (2 * BOX_X_OFFSET)); n++;
976     XtSetArg(args[n], XmNy, BOX_Y_MARGIN); n++;
977     XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
978     XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
979     XtSetArg(args[n], XmNlabelString, csString); n++;
980     XtSetArg(args[n], XmNbackground, GetColor(LABEL3_COLOR)); n++;
981     XtSetArg(args[n], XmNborderWidth, 1); n++;
982     children[2] = XmCreatePushButton(bulletinBoard, "PushButton3", args, n);
983 
984     /* add translations for manipulating rectangles */
985     SetupTranslations(children[2], label_translations);
986 
987     n = 0;
988     XtSetArg(args[n], XmNx, BOX_X_MARGIN); n++;
989     XtSetArg(args[n], XmNy, BOX_Y_MARGIN + BOX_Y_OFFSET); n++;
990     XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
991     XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
992     XtSetArg(args[n], XmNlabelString, csString); n++;
993     XtSetArg(args[n], XmNbackground, GetColor(LABEL4_COLOR)); n++;
994     XtSetArg(args[n], XmNborderWidth, 1); n++;
995     children[3] = XmCreatePushButton(bulletinBoard, "PushButton4", args, n);
996 
997     /* add translations for manipulating rectangles */
998     SetupTranslations(children[3], label_translations);
999 
1000     n = 0;
1001     XtSetArg(args[n], XmNx, BOX_X_MARGIN + BOX_X_OFFSET); n++;
1002     XtSetArg(args[n], XmNy, BOX_Y_MARGIN + BOX_Y_OFFSET); n++;
1003     XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
1004     XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
1005     XtSetArg(args[n], XmNtopWidget, children[0]); n++;
1006     XtSetArg(args[n], XmNlabelString, csString); n++;
1007     XtSetArg(args[n], XmNbackground, GetColor(LABEL5_COLOR)); n++;
1008     XtSetArg(args[n], XmNborderWidth, 1); n++;
1009     children[4] = XmCreatePushButton(bulletinBoard, "PushButton5", args, n);
1010 
1011     /* add translations for manipulating rectangles */
1012     SetupTranslations(children[4], label_translations);
1013 
1014     n = 0;
1015     XtSetArg(args[n], XmNx, BOX_X_MARGIN + (2 * BOX_X_OFFSET)); n++;
1016     XtSetArg(args[n], XmNy, BOX_Y_MARGIN + BOX_Y_OFFSET); n++;
1017     XtSetArg(args[n], XmNwidth, BOX_WIDTH); n++;
1018     XtSetArg(args[n], XmNheight, BOX_HEIGHT); n++;
1019     XtSetArg(args[n], XmNlabelString, csString); n++;
1020     XtSetArg(args[n], XmNbackground, GetColor(LABEL6_COLOR)); n++;
1021     XtSetArg(args[n], XmNborderWidth, 1); n++;
1022     children[5] = XmCreatePushButton(bulletinBoard, "PushButton6", args, n);
1023 
1024     /* add translations for manipulating rectangles */
1025     SetupTranslations(children[5], label_translations);
1026 
1027     /* Managing the children all at once helps performance */
1028     XtManageChildren(children, 6);
1029 
1030     /* Add convert callbacks */
1031     for(n = 0; n < 6; n++)
1032       XtAddCallback(children[n], XmNconvertCallback,
1033 		    (XtCallbackProc) ColorConvert, (XtPointer) NULL);
1034 
1035     /* Freeing compound string.  It is no longer necessary. */
1036     XmStringFree(csString);
1037 
1038 }
1039 
1040 
1041 /* This procedure initalizes the rectangle display table */
1042 void
InitializeRectDpyTable(void)1043 InitializeRectDpyTable(void)
1044 {
1045     /*
1046      * Initialize display table.  This is used to maintain the
1047      * order in which the rectangles are displayed
1048      */
1049     appInfo->rectDpyTable = (RectPtr *) XtMalloc((unsigned)sizeof(RectPtr));
1050 
1051     /* Initialize rectangle counter.  This is used in reallocing the tables */
1052     appInfo->rectsAllocd = 1;
1053 
1054 }
1055 
1056 
1057 /* This procedure creates the components to be displayed */
1058 void
CreateLayout(void)1059 CreateLayout(void)
1060 {
1061 
1062     Widget    mainWindow, form, separator;
1063     Arg     args[10];
1064     int     n = 0;
1065 
1066     /* Create main window */
1067     mainWindow = XmCreateMainWindow(topLevel, "mainWindow", args, n);
1068     XtManageChild(mainWindow);
1069 
1070     /* Create form for hold drawing area, separator, and color labels */
1071     n = 0;
1072     XtSetArg(args[n], XmNwidth, 300); n++;
1073     form = XmCreateForm(mainWindow, "form", args, n);
1074     XtManageChild(form);
1075 
1076     /* Create area for drawing rectangles */
1077     CreateDrawingArea(form);
1078 
1079     /* Create separator to separate drawing area from color labels */
1080     n = 0;
1081     XtSetArg(args[n], XmNtopAttachment, XmATTACH_WIDGET); n++;
1082     XtSetArg(args[n], XmNtopWidget, drawingArea); n++;
1083     XtSetArg(args[n], XmNtopOffset, 5); n++;
1084     XtSetArg(args[n], XmNleftAttachment, XmATTACH_FORM); n++;
1085     XtSetArg(args[n], XmNrightAttachment, XmATTACH_FORM); n++;
1086     XtSetArg(args[n], XmNwidth, 300); n++;
1087     separator = XmCreateSeparatorGadget(form, "separator", args, n);
1088     XtManageChild(separator);
1089 
1090     /* Create color labels for changing colors of buttons */
1091     CreateColorPushButtons(form, separator);
1092 
1093     /* Make form the work window of the main window */
1094     n = 0;
1095     XtSetArg(args[n], XmNworkWindow, form); n++;
1096     XtSetValues(mainWindow, args, n);
1097 
1098 }
1099 
1100 
1101 /* This procedure initializes the GC for drawing rectangles */
1102 void
CreateRectGC(void)1103 CreateRectGC(void)
1104 {
1105 
1106     XGCValues    values;
1107 
1108     values.line_style = LineSolid;
1109     values.line_width = HIGHLIGHT_THICKNESS;
1110     values.foreground = appInfo->currentColor = GetColor(RECT_START_COLOR);
1111     appInfo->rectGC = XCreateGC(XtDisplay(topLevel), XtWindow(drawingArea),
1112                       GCLineStyle | GCLineWidth | GCForeground, &values);
1113 
1114 }
1115