1 /*
2  *
3 Copyright 1989, 1998  The Open Group
4 
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24  *
25  * Author:  Chris D. Peterson, MIT X Consortium
26  */
27 
28 #include <X11/Intrinsic.h>
29 #include <X11/StringDefs.h>
30 #include <X11/Shell.h>
31 #include <stdio.h>
32 
33 #include <X11/Xaw/Cardinals.h>
34 
35 #include "editresP.h"
36 
37 /*
38  * Local function definitions
39  */
40 static void AddToFlashList ( TreeInfo * tree_info, GetGeomInfo * geom_info,
41 			     char ** errors );
42 static void _AddToFlashList ( TreeInfo * tree_info, char ** errors,
43 			      WNode * node, int x, int y, unsigned int width,
44 			      unsigned int height );
45 static void CreateFlashWidget ( TreeInfo * tree_info, int x, int y,
46 				unsigned int width, unsigned int height );
47 static void FlashWidgets ( TreeInfo * tree_info );
48 static void FlashWidgetsOn ( XtPointer info_ptr, XtIntervalId * id );
49 static void FlashWidgetsOff ( XtPointer info_ptr, XtIntervalId * id );
50 static void FlashWidgetsCleanup ( XtPointer info_ptr, XtIntervalId * id );
51 
52 /*	Function Name: _FindWidget
53  *	Description: Finds a widget in the tree and shows it to the user.
54  *	Arguments: w - any widget in the application.
55  *	Returns: none.
56  */
57 
58 void
_FindWidget(Widget w)59 _FindWidget(Widget w)
60 {
61     char msg[BUFSIZ];
62     WNode * node;
63     Window win;
64     int x, y;			/* location of event in root coordinates. */
65 
66     snprintf(msg, sizeof(msg), res_labels[14]);
67 
68     SetMessage(global_screen_data.info_label, msg);
69 
70     if ( (win = GetClientWindow(w, &x, &y)) != None) {
71 	node = FindWidgetFromWindow(global_tree_info, win);
72 	if (node != NULL) {
73 	    ProtocolStream * stream = &(global_client.stream);
74 
75 	    _XEditResResetStream(stream);
76 	    InsertWidgetFromNode(stream, node);
77 	    _XEditResPut16(stream, (short) x);
78 	    _XEditResPut16(stream, (short) y);
79 	    SetCommand(w, LocalFindChild, NULL);
80 	    return;
81 	}
82     }
83 
84     SetMessage(global_screen_data.info_label,
85       res_labels[15]);
86 }
87 
88 
89 /*	Function Name: DisplayChild
90  *	Description: Displays the child node returned by the client
91  *	Arguments: event - the event from the client.
92  *	Returns: none.
93  */
94 
95 void
DisplayChild(Event * event)96 DisplayChild(Event *event)
97 {
98     FindChildEvent * find_event = (FindChildEvent *) event;
99     WNode * node;
100     char msg[BUFSIZ];
101 
102     node = FindNode(global_tree_info->top_node, find_event->widgets.ids,
103 		    find_event->widgets.num_widgets);
104 
105     if (node == NULL) {
106 	snprintf(msg, sizeof(msg), res_labels[13]);
107 	SetMessage(global_screen_data.info_label, msg);
108 	return;
109     }
110 
111     SetAndCenterTreeNode(node);
112 
113     node = node->tree_info->top_node;
114 
115     snprintf(msg, sizeof(msg), res_labels[12], node->name, node->class);
116     SetMessage(global_screen_data.info_label, msg);
117 
118     _FlashActiveWidgets(global_tree_info);
119 }
120 
121 /*	Function Name: _FlashActiveWidgets
122  *	Description: Highlights all active widgets in the tree.
123  *	Arguments: tree_info - information about the current tree.
124  *	Returns: none.
125  */
126 
127 void
_FlashActiveWidgets(TreeInfo * tree_info)128 _FlashActiveWidgets(TreeInfo *tree_info)
129 {
130     Cardinal i;
131     ProtocolStream * stream = &(global_client.stream);
132 
133     if (tree_info == NULL) {
134 	SetMessage(global_screen_data.info_label,
135 		   res_labels[17]);
136 	return;
137     }
138 
139     if (tree_info->num_nodes == 0) {
140 	SetMessage(global_screen_data.info_label,res_labels[18]);
141 	return;
142     }
143 
144     _XEditResResetStream(stream);
145     /*
146      * Insert the number of widgets.
147      */
148     _XEditResPut16(stream, (unsigned short) tree_info->num_nodes);
149 
150     for (i = 0; i < tree_info->num_nodes; i++)
151 	InsertWidgetFromNode(stream, global_tree_info->active_nodes[i]);
152 
153     SetCommand(tree_info->tree_widget, LocalFlashWidget, NULL);
154 }
155 
156 /*	Function Name: HandleFlashWidget
157  *	Description: Is called when client has returned geometry of all widget
158  *                   to flash.
159  *	Arguments: event - the event containing the client info.
160  *	Returns: none.
161  */
162 
163 char *
HandleFlashWidget(Event * event)164 HandleFlashWidget(Event *event)
165 {
166     GetGeomEvent * geom_event = (GetGeomEvent *) event;
167     char * errors = NULL;
168     int i;
169 
170     for (i = 0; i < (int)geom_event->num_entries; i++)
171 	AddToFlashList(global_tree_info, geom_event->info + i, &errors);
172 
173     FlashWidgets(global_tree_info);
174 
175     return(errors);
176 }
177 
178 /*	Function Name: AddWidgetToFlashList
179  *	Description: Adds a widget to the list of widget to flash.
180  *	Arguments: tree_info - info about this tree.
181  *                 geom_info - the info from the client about this widget.
182  *                 errors - a string containing the errors.
183  *	Returns: none
184  */
185 
186 static void
AddToFlashList(TreeInfo * tree_info,GetGeomInfo * geom_info,char ** errors)187 AddToFlashList(TreeInfo *tree_info, GetGeomInfo *geom_info, char **errors)
188 {
189     WNode * node;
190     char buf[BUFSIZ];
191 
192     node = FindNode(tree_info->top_node,
193 		    geom_info->widgets.ids, geom_info->widgets.num_widgets);
194 
195     if (node == NULL) {
196 	snprintf(buf, sizeof(buf),
197                  "Editres Internal Error: Unable to FindNode.\n");
198 	AddString(errors, buf);
199 	return;
200     }
201 
202     if (geom_info->error) {
203 	AddString(errors, geom_info->message);
204 	return;
205     }
206 
207     if (!geom_info->visable) {
208 	snprintf(buf, sizeof(buf), "%s(0x%lx) - This widget is not mapped\n",
209 		node->name, node->id);
210 	AddString(errors, buf);
211 	return;
212     }
213 
214     _AddToFlashList(tree_info, errors, node,
215 		    geom_info->x, geom_info->y,
216 		    geom_info->width + geom_info->border_width,
217 		    geom_info->height + geom_info->border_width);
218 }
219 
220 /*	Function Name: _AddToFlashList
221  *	Description: adds the window to the current client's flash list.
222  *	Arguments: errors - a string to stuff any errors encountered.
223  *                 node - the node associated with this object.
224  *                 x, y - location of the flash widget in root coords.
225  *                 width, height - size of the flash widget.
226  *	Returns: none.
227  */
228 
229 static void
_AddToFlashList(TreeInfo * tree_info,char ** errors,WNode * node,int x,int y,unsigned int width,unsigned int height)230 _AddToFlashList(TreeInfo *tree_info, char **errors, WNode *node,
231 		int x, int y, unsigned int width, unsigned int height)
232 {
233     Display * dpy = XtDisplay(tree_info->tree_widget);
234     Window window = (Window) node->window;
235     XWindowAttributes attrs;
236 
237     if (window == EDITRES_IS_OBJECT)
238 	window = node->parent->window;
239 
240     if (window == EDITRES_IS_UNREALIZED) {
241 	char buf[BUFSIZ];
242 
243 	if (node->window == EDITRES_IS_OBJECT)
244 	    snprintf(buf, sizeof(buf),
245                      "%s(0x%lx) - This object's parent is unrealized\n",
246                      node->name, node->id);
247 	else
248 	    snprintf(buf, sizeof(buf),
249                      "%s(0x%lx) - This widget is unrealized\n",
250                      node->name, node->id);
251 
252 	AddString(errors, buf);
253 	return;
254     }
255 
256     global_error_code = NO_ERROR;                 /* Reset Error code. */
257     global_old_error_handler = XSetErrorHandler(HandleXErrors);
258     global_serial_num = NextRequest(dpy);
259 
260     XGetWindowAttributes(dpy, window, &attrs);
261 
262     XSync(dpy, FALSE);
263     XSetErrorHandler(global_old_error_handler);
264     if (global_error_code == NO_WINDOW) {
265 	char buf[BUFSIZ];
266 
267 	snprintf(buf, sizeof(buf),
268                  "%s(0x%lx) - This widget's window no longer exists.\n",
269                  node->name, node->id);
270 	AddString(errors, buf);
271 	return;
272     }
273 
274     if (attrs.map_state != IsViewable) {
275 	char buf[BUFSIZ];
276 
277 	snprintf(buf, sizeof(buf), "%s(0x%lx) - This widget is not mapped.\n",
278                  node->name, node->id);
279 	AddString(errors, buf);
280 	return;
281     }
282 
283     CreateFlashWidget(tree_info, x, y, width, height);
284 }
285 
286 /*	Function Name: CreateFlashWidget
287  *	Description: Creates a widget of the size specified that
288  *                   will flash on the display, and adds it to the list
289  *                   of widgets to flash.
290  *	Arguments: tree_info - the tree information structure.
291  *                 x,y,width, height - size and location of the flash widget.
292  *	Returns: none.
293  */
294 
295 #define MORE_FLASH_WIDGETS 5
296 
297 static void
CreateFlashWidget(TreeInfo * tree_info,int x,int y,unsigned int width,unsigned int height)298 CreateFlashWidget(TreeInfo *tree_info, int x, int y,
299 		  unsigned int width, unsigned int height)
300 {
301     Widget shell;
302     Arg args[3];
303     Cardinal num = 0;
304     Dimension bw;
305 
306     XtSetArg(args[num], XtNx, x); num++;
307     XtSetArg(args[num], XtNy, y); num++;
308     XtSetArg(args[num], XtNbackground, global_resources.flash_color); num++;
309 
310     shell = XtCreatePopupShell("flash", overrideShellWidgetClass,
311 			       tree_info->tree_widget, args, num);
312 
313     num = 0;
314     XtSetArg(args[num], XtNborderWidth, &bw); num++;
315     XtGetValues(shell, args, num);
316 
317     bw *= 2;
318 
319     num = 0;
320     XtSetArg(args[num], XtNwidth, (width - bw)); num++;
321     XtSetArg(args[num], XtNheight, (height - bw)); num++;
322     XtSetValues(shell, args, num);
323 
324     if (tree_info->num_flash_widgets + 1 > tree_info->alloc_flash_widgets) {
325 	tree_info->alloc_flash_widgets += MORE_FLASH_WIDGETS;
326 	tree_info->flash_widgets =
327 	    (Widget *) XtRealloc((char *)tree_info->flash_widgets,
328 			      sizeof(Widget) * tree_info->alloc_flash_widgets);
329     }
330 
331     tree_info->flash_widgets[tree_info->num_flash_widgets] = shell;
332     tree_info->num_flash_widgets++;
333 }
334 
335 /*	Function Name: FlashWidgets
336  *	Description: Starts the widgets flashing.
337  *	Arguments: tree_info - the info about the tree (contains flash list)
338  *	Returns: none
339  */
340 
341 static void
FlashWidgets(TreeInfo * tree_info)342 FlashWidgets(TreeInfo *tree_info)
343 {
344     int i;
345     unsigned long wait, half_flash;
346     XtAppContext ac = XtWidgetToApplicationContext(tree_info->tree_widget);
347 
348     if (tree_info->flash_widgets == NULL) /* no widgets to flash. */
349 	return;
350 
351     wait = half_flash = global_resources.flash_time/2;
352     for (i = 1; i < global_resources.num_flashes; i++) {
353 	XtAppAddTimeOut(ac, wait, FlashWidgetsOff,(XtPointer)tree_info);
354 	wait += half_flash;
355 	XtAppAddTimeOut(ac, wait, FlashWidgetsOn,(XtPointer)tree_info);
356 	wait += half_flash;
357     }
358 
359     wait += half_flash;
360     XtAppAddTimeOut(ac, wait, FlashWidgetsCleanup, (XtPointer)tree_info);
361 
362     FlashWidgetsOn((XtPointer) tree_info, (XtIntervalId *) NULL);
363 }
364 
365 /*	Function Name: FlashWidgetsOn
366  *	Description: Turns on all the Flash Widgets.
367  *	Arguments: info_ptr - pointer to the tree info.
368  *                 id - *** UNUSED ***.
369  *	Returns: none
370  */
371 
372 /* ARGSUSED */
373 static void
FlashWidgetsOn(XtPointer info_ptr,XtIntervalId * id)374 FlashWidgetsOn(XtPointer info_ptr, XtIntervalId *id)
375 {
376 
377     Cardinal i;
378     TreeInfo * tree_info = (TreeInfo *) info_ptr;
379 
380     for (i = 0; i < tree_info->num_flash_widgets; i++) {
381 	XtRealizeWidget(tree_info->flash_widgets[i]);
382 	XMapRaised(XtDisplay(tree_info->flash_widgets[i]),
383 		   XtWindow(tree_info->flash_widgets[i]));
384     }
385 }
386 
387 /*	Function Name: FlashWidgetsOff
388  *	Description: Turns off all the Flash Widgets.
389  *	Arguments: info_ptr - pointer to the tree info.
390  *                 id - *** UNUSED ***.
391  *	Returns: none
392  */
393 
394 /* ARGSUSED */
395 static void
FlashWidgetsOff(XtPointer info_ptr,XtIntervalId * id)396 FlashWidgetsOff(XtPointer info_ptr, XtIntervalId *id)
397 {
398     Cardinal i;
399     TreeInfo * tree_info = (TreeInfo *) info_ptr;
400 
401     for (i = 0; i < tree_info->num_flash_widgets; i++)
402 	XtUnmapWidget(tree_info->flash_widgets[i]);
403 }
404 
405 /*	Function Name: FlashWidgetsCleanup
406  *	Description: Destroys all the Flash Widgets.
407  *	Arguments: info_ptr - pointer to the tree info.
408  *                 id - *** UNUSED ***.
409  *	Returns: none
410  */
411 
412 /* ARGSUSED */
413 static void
FlashWidgetsCleanup(XtPointer info_ptr,XtIntervalId * id)414 FlashWidgetsCleanup(XtPointer info_ptr, XtIntervalId *id)
415 {
416     Cardinal i;
417     TreeInfo * tree_info = (TreeInfo *) info_ptr;
418 
419 /*
420  * Unmap 'em first for consistency.
421  */
422 
423     for (i = 0; i < tree_info->num_flash_widgets; i++)
424 	XtUnmapWidget(tree_info->flash_widgets[i]);
425 
426     XFlush(XtDisplay(tree_info->tree_widget));
427 
428     for (i = 0; i < tree_info->num_flash_widgets; i++)
429 	XtDestroyWidget(tree_info->flash_widgets[i]);
430 
431     XtFree((char *)tree_info->flash_widgets);
432     tree_info->flash_widgets = NULL;
433     tree_info->num_flash_widgets = tree_info->alloc_flash_widgets = 0;
434 }
435