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