geometry.c revision 352bf44e
1/*
2 *
3Copyright 1989, 1998  The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in 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 */
40static void AddToFlashList ( TreeInfo * tree_info, GetGeomInfo * geom_info,
41			     char ** errors );
42static void _AddToFlashList ( TreeInfo * tree_info, char ** errors,
43			      WNode * node, int x, int y, unsigned int width,
44			      unsigned int height );
45static void CreateFlashWidget ( TreeInfo * tree_info, int x, int y,
46				unsigned int width, unsigned int height );
47static void FlashWidgets ( TreeInfo * tree_info );
48static void FlashWidgetsOn ( XtPointer info_ptr, XtIntervalId * id );
49static void FlashWidgetsOff ( XtPointer info_ptr, XtIntervalId * id );
50static 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
58void
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
95void
96DisplayChild(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
127void
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
163char *
164HandleFlashWidget(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
186static void
187AddToFlashList(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->visible) {
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
229static void
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
297static void
298CreateFlashWidget(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
341static void
342FlashWidgets(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 */
373static void
374FlashWidgetsOn(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 */
395static void
396FlashWidgetsOff(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 */
413static void
414FlashWidgetsCleanup(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