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  */
24 
25 /************************************************************
26 *	INCLUDE FILES
27 *************************************************************/
28 #include <stdio.h>
29 #include <stdarg.h>
30 #include <X11/IntrinsicP.h>
31 
32 #include "XmI.h"
33 #include <Xm/XmP.h>
34 #include <Xm/PrimitiveP.h>
35 #include <Xm/GadgetP.h>
36 #include <Xm/ExtP.h>
37 
38 /************************************************************
39 *	TYPEDEFS AND DEFINES
40 *************************************************************/
41 
42 typedef struct _PixmapCache {
43     Screen *screen;
44     Pixmap pixmap;
45     Pixel foreground, background;
46     unsigned int depth;
47     int ref_count;
48     struct _PixmapCache *next;
49 } CacheEntry;
50 
51 /************************************************************
52 *	MACROS
53 *************************************************************/
54 
55 /************************************************************
56 *	GLOBAL DECLARATIONS
57 *************************************************************/
58 
59 
60 
61 String xm_std_filter[] = { XmNx, XmNy, XmNwidth, XmNheight,
62 			   XmNdestroyCallback, XmNsensitive, XmNuserData,
63 			   XmNnavigationType, NULL };
64 
65 String xm_std_constraint_filter[] = { XmNx, XmNy, XmNwidth, XmNheight,
66 			   XmNdestroyCallback, XmNsensitive, XmNuserData,
67 			   XmNnavigationType, XmNbottomAttachment,
68 			   XmNbottomOffset, XmNbottomPosition, XmNbottomWidget,
69 			   XmNbottomAttachment, XmNtopAttachment,
70 			   XmNleftOffset, XmNleftPosition, XmNleftWidget,
71 			   XmNtopOffset, XmNtopPosition, XmNtopWidget,
72 			   XmNrightOffset, XmNrightPosition, XmNrightWidget,
73 			   XmNrightAttachment, XmNleftAttachment,
74 			   XmNallowResize, XmNpaneMinimum, XmNshowSash,
75 			   XmNpaneMaximum, XmNpreferredPaneSize,
76 			   XmNresizeToPreferred, XmNskipAdjust,
77 			   XmNdFieldPrefHeight, XmNdFieldMaxHeight,
78 			   XmNdFieldPrefWidth, XmNdFieldMaxWidth,
79                            XmNdFieldMinHeight, XmNdFieldMinWidth,
80 			   /* CR03683 */ XmNpixmapWidth, XmNpixmapHeight,
81 			   NULL };
82 
83 /************************************************************
84 *	EXTERNAL DECLARATIONS
85 *************************************************************/
86 
87 /************************************************************
88 *	STATIC DECLARATIONS
89 *************************************************************/
90 
91 static CacheEntry *pixmapCache = NULL;
92 
93 /************************************************************
94 *	GLOBAL CODE
95 *************************************************************/
96 
97 /*	Function Name: _XmRequestNewSize
98  *	Description:   Asks our parent for a new size.
99  *	Arguments:     w - the data request tree widget.
100  *                     query_only - only ask what would happen, don't
101  *                                  change anything.
102  *                     width, height - size to request.
103  *                     r_width, r_height - allowed size.
104  *	Returns:       none.
105  */
106 
107 XtGeometryResult
_XmRequestNewSize(Widget w,Boolean query_only,Dimension width,Dimension height,Dimension * r_width,Dimension * r_height)108 _XmRequestNewSize(Widget w, Boolean query_only,
109 		  Dimension width, Dimension height,
110 		  Dimension * r_width, Dimension * r_height)
111 {
112     XtGeometryResult ret_val;
113     XtWidgetGeometry request, result;
114 
115     request.width = width;
116     request.height = height;
117     request.request_mode = CWWidth | CWHeight;
118 
119     if (query_only)
120 	request.request_mode |= XtCWQueryOnly;
121 
122     ret_val = XtMakeGeometryRequest(w, &request, &result);
123 
124     if (ret_val == XtGeometryAlmost) {
125 	if (!query_only)
126 	    ret_val = XtMakeGeometryRequest(w, &result, NULL);
127 
128 	*r_width = result.width;
129 	*r_height = result.height;
130     }
131     else if (ret_val == XtGeometryYes) {
132 	*r_width = request.width;
133 	*r_height = request.height;
134     }
135     else {
136 	*r_width = w->core.width;
137 	*r_height = w->core.height;
138     }
139 
140     return(ret_val);
141 }
142 
143 /*	Function Name: _XmHWQuery
144  *	Description:   Handles much of the generic height and width query
145  *                     geometry processing.
146  *	Arguments:     w - the widget to process.
147  *                     intended, preferred - The values from the real query
148  *                                           procedure.  It is assumed
149  *                                           that preferred is already
150  *                                           filled with the correct desired
151  *                                           size.
152  *	Returns:       an XtGeometryResult.
153  */
154 
155 XtGeometryResult
_XmHWQuery(Widget w,XtWidgetGeometry * intended,XtWidgetGeometry * preferred)156 _XmHWQuery(Widget w, XtWidgetGeometry * intended, XtWidgetGeometry * preferred)
157 {
158     if (intended == NULL) {
159 	if ((preferred->width == w->core.width) &&
160  	    (preferred->height == w->core.height))
161 	{
162 	    return(XtGeometryNo);
163 	}
164     }
165     else {
166 	if ((intended->request_mode & CWWidth) &&
167 	    (intended->request_mode & CWHeight))
168 	{
169 	    if ((intended->width == preferred->width) &&
170 		(intended->height == preferred->height))
171 	    {
172 		return(XtGeometryYes);
173 	    }
174 	    else {
175 		return(XtGeometryNo);
176 	    }
177 	}
178     }
179 
180     preferred->request_mode = CWWidth | CWHeight;
181     return(XtGeometryAlmost);
182 }
183 
184 /*	Function Name: _XmGadgetWarning
185  *	Description: Checks to see if this is a gadget.  If it is then
186  *                   print out a warning, and return True.
187  *	Arguments: w - the widget to check.
188  *	Returns: True if this object is a gadget.
189  */
190 
191 Boolean
_XmGadgetWarning(Widget w)192 _XmGadgetWarning(Widget w)
193 {
194     if (!XtIsRectObj(w) || XtIsWidget(w))
195 	return(False);
196 
197     XmeWarning(XtParent(w), XmNnoGadgetSupportMsg);
198 
199     return(True);
200 }
201 
202 /*	Function Name: _XmGetFocus
203  *	Description:   Gets the XmFocus.
204  *	Arguments:     w - the icon button widget.
205  *                     event - the event that caused this action.
206  *                     params, num_params - action routine parameters.
207  *	Returns:       none.
208  */
209 
210 /* ARGSUSED */
211 void
_XmGetFocus(Widget w,XEvent * event,String * params,Cardinal * num_params)212 _XmGetFocus(Widget w, XEvent * event, String * params, Cardinal * num_params)
213 {
214 #ifdef VMS
215     if (XtIsRealized(w))
216 #endif
217 	(void) XmProcessTraversal(w, XmTRAVERSE_CURRENT);
218 }
219 
220 /*	Function Name: _XmFilterArgs
221  *	Description: Filters certain resources out of an argument list.
222  *	Arguments: args, num_args - the input argument list.
223  *                 filter - the list of resources (by name) to remove.
224  * RETURNED        filtered_args, num_filtered_args - new filtered list.
225  *	Returns: none.
226  *
227  * NOTE The caller of this function is responsible for freeing "filtered_args"
228  *      with XtFree() when it is no longer in use.
229  */
230 
231 void
_XmFilterArgs(ArgList args,Cardinal num_args,String * filter,ArgList * filtered_args,Cardinal * num_filtered_args)232 _XmFilterArgs(ArgList args, Cardinal num_args, String *filter,
233 	      ArgList *filtered_args, Cardinal *num_filtered_args)
234 {
235     ArgList fargs = (ArgList) XtMalloc(sizeof(Arg) * num_args);
236     register int i;
237     String *ptr;
238 
239     *filtered_args = fargs;
240     *num_filtered_args = 0;
241     for (i = 0; i < num_args; i++) {
242 	Boolean match = False;
243 	for (ptr = filter; *ptr != NULL; ptr++) {
244 	    if (streq(*ptr, args[i].name)) {
245 		match = True;
246 		break;
247 	    }
248 	}
249 	if (!match) {
250 	    *fargs++ = args[i];
251 	    (*num_filtered_args)++;
252 	}
253     }
254 }
255 
256 /*	Function Name: _XmSetValuesOnChildren
257  *	Description: Calls setvalues on all children of this widget,
258  *                   and then recurses.
259  *	Arguments: w - the widget to set.
260  *                 args, num_args - arguments to set.
261  *	Returns: none.
262  */
263 
264 void
_XmSetValuesOnChildren(Widget w,ArgList args,Cardinal num_args)265 _XmSetValuesOnChildren(Widget w, ArgList args, Cardinal num_args)
266 {
267     Widget *childP;
268 
269     if (!XtIsSubclass(w, compositeWidgetClass))
270 	return;
271 
272     ForAllChildren((CompositeWidget) w, childP) {
273 	XtSetValues(*childP, args, num_args);
274 	_XmSetValuesOnChildren(*childP, args, num_args);
275     }
276 }
277 
278 /*      Function Name: _XmUtilIsSubclassByNameQ
279  *      Description:   Determines whether this is a subclass of the named
280  *                     class.
281  *      Arguments:     w - the widget to check.
282  *                     nameq - a quarkified name for the class to check.
283  *      Returns:       True if this is a subclass.
284  */
285 
286 Boolean
_XmUtilIsSubclassByNameQ(Widget w,XrmQuark nameq)287 _XmUtilIsSubclassByNameQ(Widget w, XrmQuark nameq)
288 {
289     WidgetClass class;
290 
291     Boolean returnValue = False;
292 
293     _XmProcessLock();
294     for (class = XtClass(w) ;
295          class != NULL ;
296          class = class->core_class.superclass)
297     {
298         if (nameq == XrmStringToQuark(class->core_class.class_name))
299         {
300             returnValue = True;
301             break;
302         }
303     }
304     _XmProcessUnlock();
305 
306     return(returnValue);
307 }
308 
309 /*	Function Name: _XmGetMBStringFromXmString
310  *	Description: Given an Xm String, returns an MB string
311  *	Arguments: xmstr - an Xm String.
312  *	Returns: A multi byte string.
313  */
314 
315 String
_XmGetMBStringFromXmString(XmString xmstr)316 _XmGetMBStringFromXmString(XmString xmstr)
317 {
318     String 			text;
319     XmStringContext 		context;   /* context for conversion	*/
320     char			*newText;  /* new text string        	*/
321     XmStringCharSet		charset;   /* dummy			*/
322     XmStringDirection   	direction; /* dummy			*/
323     XmStringComponentType	u_tag;	   /* is newline		*/
324     int				length;    /* length of string		*/
325     unsigned short		u_length;  /* bogus length		*/
326     unsigned char		*u_value;  /* bogus value		*/
327     XmStringComponentType 	type;	   /* type			*/
328     Boolean			done, separator; /* done with it	*/
329 
330     if ( !XmStringInitContext(&context, xmstr) )
331     {
332       XmStringFree(xmstr);
333       return(NULL);
334     }
335 
336     /*
337      * First path to get length.
338      */
339     length = 0;
340     if ( XmStringPeekNextComponent(context) == XmSTRING_COMPONENT_UNKNOWN ) {
341       XmStringFree(xmstr);
342       XmStringFreeContext(context);
343       return(NULL);
344     }
345 
346     done = False;
347     while( !done )
348     {
349 	newText = NULL;		/* By source code inspection I have */
350 	charset = NULL;		/* Determined that this will make sure */
351 	u_value = NULL;		/* that no memory is leaked (I hope). */
352 
353 	type = XmStringGetNextComponent( context, &newText, &charset,
354 		&direction, &u_tag, &u_length, &u_value );
355 
356         switch( type )
357 	{
358     	case XmSTRING_COMPONENT_TEXT:
359 	case XmSTRING_COMPONENT_LOCALE_TEXT:
360 	    length += strlen( newText );
361 	    break;
362  	case XmSTRING_COMPONENT_SEPARATOR:
363 	    length += 1;
364 	    break;
365 	case XmSTRING_COMPONENT_USER_BEGIN:
366 	case XmSTRING_COMPONENT_USER_END:
367 	case XmSTRING_COMPONENT_CHARSET:
368 	case XmSTRING_COMPONENT_DIRECTION:
369 	    break;
370 	case XmSTRING_COMPONENT_END:
371 	default:
372 	    done = True;
373 	}
374 
375 	XtFree((XtPointer) newText);
376 	XtFree((XtPointer) charset);
377 	XtFree((XtPointer) u_value);
378    }
379 
380     /*
381      * If XmStringGetNextComponent() fails on the current xmstring,
382      * try by using XmStringGetNextSegment(). AIX 4.3.2 currently
383      * fails to obtain the compound string from
384      * XmStringGetNextComponent. (Change Reguest: CR03841)
385      */
386 
387     if(length == 0) {
388 	while ( XmStringGetNextSegment(context, &newText, &charset,
389 				       &direction, &separator) ) {
390 
391 	length = strlen(newText);
392 	if (separator == True) {
393 	  length += 1;     ;
394 	}
395 
396 	text = XtMalloc( length + 1 );
397 	text[0] = '\0';
398 	strcat(text, newText);
399 
400 	if (separator == True) {
401 	  strcat(text, "\n");
402 	}
403 
404 	XtFree(newText);
405 	XmStringFreeContext(context);
406 
407 	return (text);
408       }
409     }
410 
411     /*
412      * Failed to obtain any compound string, return with NULL pointer.
413      */
414     if(length == 0) return(NULL);
415 
416     XmStringFreeContext( context );
417     text = XtMalloc( length + 1 );
418     text[0] = '\0';
419 
420     /*
421      * Fill in the string.
422      */
423     XmStringInitContext(&context, xmstr);
424 
425     done = False;
426     while( !done )
427     {
428 	newText = NULL;		/* By source code inspection I have */
429 	charset = NULL;		/* Determined that this will make sure */
430 	u_value = NULL;		/* that no memory is leaked (I hope). */
431 
432 	type = XmStringGetNextComponent( context, &newText, &charset,
433 		&direction, &u_tag, &u_length, &u_value );
434         switch( type )
435 	{
436     	case XmSTRING_COMPONENT_TEXT:
437 	case XmSTRING_COMPONENT_LOCALE_TEXT:
438 	    strcat(text, newText);
439 	    break;
440  	case XmSTRING_COMPONENT_SEPARATOR:
441 	    strcat(text, "\n");
442 	    break;
443 	case XmSTRING_COMPONENT_USER_BEGIN:
444 	case XmSTRING_COMPONENT_USER_END:
445 	case XmSTRING_COMPONENT_CHARSET:
446 	case XmSTRING_COMPONENT_DIRECTION:
447 	    break;
448 	case XmSTRING_COMPONENT_END:
449 	default:
450 	    done = True;
451 	}
452 
453 	XtFree((XtPointer) newText);
454 	XtFree((XtPointer) charset);
455 	XtFree((XtPointer) u_value);
456    }
457 
458     XmStringFreeContext(context);
459     return(text);
460 }
461 
462 /*	Function Name: _XiWoveWidget
463  *	Description: Wrapper for XtMoveWidget to deal with Motif1.2
464  *                   drag N drop.
465  *	Arguments: w - The widget to change
466  *                 x, y - The new location for this widget.
467  *	Returns: none.
468  */
469 
470 void
_XmMoveWidget(Widget w,Position x,Position y)471 _XmMoveWidget(Widget w, Position x, Position y)
472 {
473     XmDropSiteStartUpdate(w);
474     XtMoveWidget(w, x, y);
475     XmDropSiteEndUpdate(w);
476 }
477 
478 /*	Function Name: _XmResizeWidget
479  *	Description: Wrapper for XtResizeWidget to deal with Motif1.2
480  *                   drag N drop.
481  *	Arguments: w - The widget to change
482  *                 width, height, bw - The new size for the widget.
483  *	Returns: none.
484  */
485 
486 void
_XmResizeWidget(Widget w,Dimension width,Dimension height,Dimension bw)487 _XmResizeWidget(Widget w, Dimension width, Dimension height, Dimension bw)
488 {
489     XmDropSiteStartUpdate(w);
490     XtResizeWidget(w, width, height, bw);
491     XmDropSiteEndUpdate(w);
492 }
493 
494 /*	Function Name: _XmConfigureWidget
495  *	Description: Wrapper for XtConfigureWidget to deal with Motif1.2
496  *                   drag N drop.
497  *	Arguments: w - The widget to change
498  *                 x, y - The new location for this widget.
499  *                 width, height, bw - The new size for the widget.
500  *	Returns: none.
501  */
502 
503 void
_XmConfigureWidget(Widget w,Position x,Position y,Dimension width,Dimension height,Dimension bw)504 _XmConfigureWidget(Widget w, Position x, Position y,
505 		   Dimension width, Dimension height, Dimension bw)
506 {
507     /* 0x0 will sometimes result in a BadValue Error for X_ConfigureWindow */
508     if (height < 1) height = 1;
509     if (width < 1) width = 1;
510 
511     XmDropSiteStartUpdate(w);
512     XtConfigureWidget(w, x, y, width, height, bw);
513     XmDropSiteEndUpdate(w);
514 
515 }
516 
517 /************************************************************
518  *
519  *  This code is taken from the MIT X Consortium's Xmu
520  *  Utility Library.
521  *
522  ************************************************************/
523 
524 #define  XK_LATIN1
525 #include <X11/keysymdef.h>
526 
527 /*
528  * ISO Latin-1 case conversion routine
529  */
530 
531 /*
532  * Function:
533  *	XmCompareISOLatin1(first, second)
534  * Description:
535  *	Compares two ISO Latin 1 strings to determine if they are equivalent.
536  *	Case is not considered for the comparison.
537  * Input:
538  *	first  : char * - the first ISO Latin 1 String
539  *	second : char * - the second ISO Latin 1 String
540  * Output:
541  *	int - (-1) -> first < second
542  *            ( 0) -> first == second
543  *            ( 1) -> first > second
544  */
545 int
546 #ifndef _NO_PROTO
XmCompareISOLatin1(char * first,char * second)547 XmCompareISOLatin1(char *first, char *second)
548 #else
549 XmCompareISOLatin1(first, second)
550     char *first, *second;
551 #endif
552 {
553     register unsigned char *ap, *bp;
554 
555     for (ap = (unsigned char *) first, bp = (unsigned char *) second;
556          *ap && *bp; ap++, bp++) {
557         register unsigned char a, b;
558 
559         if ((a = *ap) != (b = *bp)) {
560             /* try lowercasing and try again */
561 
562             if ((a >= XK_A) && (a <= XK_Z))
563 		a += (XK_a - XK_A);
564             else if ((a >= XK_Agrave) && (a <= XK_Odiaeresis))
565               a += (XK_agrave - XK_Agrave);
566             else if ((a >= XK_Ooblique) && (a <= XK_Thorn))
567               a += (XK_oslash - XK_Ooblique);
568 
569             if ((b >= XK_A) && (b <= XK_Z))
570               b += (XK_a - XK_A);
571             else if ((b >= XK_Agrave) && (b <= XK_Odiaeresis))
572               b += (XK_agrave - XK_Agrave);
573             else if ((b >= XK_Ooblique) && (b <= XK_Thorn))
574               b += (XK_oslash - XK_Ooblique);
575 
576             if (a != b) break;
577         }
578     }
579     return (((int) *bp) - ((int) *ap));
580 }
581 
582 void
XmCopyISOLatin1Lowered(dst,src)583 XmCopyISOLatin1Lowered(dst, src)
584     char *dst, *src;
585 {
586     register unsigned char *dest, *source;
587 
588     for (dest = (unsigned char *)dst, source = (unsigned char *)src;
589 	 *source;
590 	 source++, dest++)
591     {
592 	if ((*source >= XK_A) && (*source <= XK_Z))
593 	    *dest = *source + (XK_a - XK_A);
594 	else if ((*source >= XK_Agrave) && (*source <= XK_Odiaeresis))
595 	    *dest = *source + (XK_agrave - XK_Agrave);
596 	else if ((*source >= XK_Ooblique) && (*source <= XK_Thorn))
597 	    *dest = *source + (XK_oslash - XK_Ooblique);
598 	else
599 	    *dest = *source;
600     }
601     *dest = '\0';
602 }
603 
604 /*
605  *	Creates a stippled pixmap of specified depth
606  *	caches these so that multiple requests share the pixmap
607  */
608 
609 #define pixmap_width 2
610 #define pixmap_height 2
611 
612 Pixmap
XiCreateStippledPixmap(Screen * screen,Pixel fore,Pixel back,unsigned int depth)613 XiCreateStippledPixmap(Screen *screen,
614 		       Pixel fore, Pixel back, unsigned int depth)
615 {
616     register Display *display = DisplayOfScreen(screen);
617     CacheEntry *cachePtr;
618     Pixmap stippled_pixmap;
619     static unsigned char pixmap_bits[] = {
620 	0x02, 0x01,
621     };
622 
623     /* see if we already have a pixmap suitable for this screen */
624     for (cachePtr = pixmapCache; cachePtr; cachePtr = cachePtr->next) {
625 	if (cachePtr->screen == screen && cachePtr->foreground == fore &&
626 	    cachePtr->background == back && cachePtr->depth == depth)
627 	    return( cachePtr->ref_count++, cachePtr->pixmap );
628     }
629 
630     stippled_pixmap = XCreatePixmapFromBitmapData (display,
631 			RootWindowOfScreen(screen), (char *)pixmap_bits,
632 			pixmap_width, pixmap_height, fore, back, depth);
633 
634     /* and insert it at the head of the cache */
635     cachePtr = XtNew(CacheEntry);
636     cachePtr->screen = screen;
637     cachePtr->foreground = fore;
638     cachePtr->background = back;
639     cachePtr->depth = depth;
640     cachePtr->pixmap = stippled_pixmap;
641     cachePtr->ref_count = 1;
642 
643     _XmProcessLock();
644     cachePtr->next = pixmapCache;
645     pixmapCache = cachePtr;
646     _XmProcessUnlock();
647     return( stippled_pixmap );
648 }
649 
650 void
XiReleaseStippledPixmap(Screen * screen,Pixmap pixmap)651 XiReleaseStippledPixmap(Screen *screen, Pixmap pixmap)
652 {
653     register Display *display = DisplayOfScreen(screen);
654     CacheEntry *cachePtr, **prevP;
655 
656     _XmProcessLock();
657     for (prevP = &pixmapCache, cachePtr = pixmapCache; cachePtr;)
658     {
659         if (cachePtr->screen == screen && cachePtr->pixmap == pixmap)
660         {
661 	        if (--cachePtr->ref_count == 0)
662             {
663 		        XFreePixmap( display, pixmap );
664 		        *prevP = cachePtr->next;
665 		        XtFree( (char*)cachePtr );
666 		        break;
667 	        }
668 	    }
669 	    prevP = &cachePtr->next;
670 	    cachePtr = *prevP;
671     }
672     _XmProcessUnlock();
673 }
674 
675 /*
676  * Function:
677  *	XmCompareXtWidgetGeometryToWidget(geom, widget)
678  * Description:
679  *	This function compares an XtWidgetGeometry structure to the
680  *	actual values contained in a widget.
681  * Input:
682  *	geom   : XtWidgetGeometry* - the geometry to test against the widget
683  *	widget : Widget            - the widget to use in the comparison
684  * Output:
685  *	Boolean - True if the geometry fits the specified widget, else False
686  */
687 Boolean
XmCompareXtWidgetGeometryToWidget(XtWidgetGeometry * geom,Widget widget)688 XmCompareXtWidgetGeometryToWidget(XtWidgetGeometry *geom, Widget widget)
689 {
690     Boolean returnValue = True;
691 
692     _XmProcessLock();
693     if( (geom->request_mode & CWX && geom->x != widget->core.x) ||
694         (geom->request_mode & CWY && geom->y != widget->core.y) ||
695         (geom->request_mode & CWWidth && geom->width != XtHeight(widget)) ||
696         (geom->request_mode & CWHeight && geom->height != XtHeight(widget)) ||
697         (geom->request_mode & CWBorderWidth && geom->border_width != widget->core.border_width) )
698     {
699         returnValue = False;
700     }
701     _XmProcessUnlock();
702     return( returnValue );
703 }
704 
705 /*
706  * Function:
707  *	XmCompareXtWidgetGeometry(geom1, geom2)
708  * Description:
709  *	Compares to XtWidgetGeometry structures to check for equality.
710  * Input:
711  *	geom1 : XtWidgetGeometry* - geometry to compare
712  *	geom2 : XtWidgetGeometry* - geometry to compare
713  * Output:
714  *	Boolean - True if both the request_mode and values match, else False
715  */
716 Boolean
XmCompareXtWidgetGeometry(XtWidgetGeometry * geom1,XtWidgetGeometry * geom2)717 XmCompareXtWidgetGeometry(XtWidgetGeometry *geom1, XtWidgetGeometry *geom2)
718 {
719     if( geom1->request_mode != geom2->request_mode )
720         return( False );
721 
722     if( (geom1->request_mode & CWX              && (geom1->x != geom2->x)) ||
723         (geom1->request_mode & CWY              && (geom1->y != geom2->y)) ||
724         (geom1->request_mode & CWWidth          && (geom1->width != geom2->width)) ||
725         (geom1->request_mode & CWHeight         && (geom1->height != geom2->height)) ||
726         (geom1->request_mode & CWBorderWidth    && (geom1->border_width != geom2->border_width)) ||
727         (geom1->request_mode & CWSibling        && (geom1->sibling != geom2->sibling)) ||
728         (geom1->request_mode & CWStackMode      && (geom1->stack_mode != geom2->stack_mode)) )
729         return( False );
730 
731     return( True );
732 }
733 
734 /************************************************************
735  *
736  *  Static functions
737  *
738  ************************************************************/
739 
740 #include <Xm/XmP.h>
741 
742 /*************************************************************************/
743 /* The following code is snipped directly from OSF Motif 1.2.4           */
744 /* DEC did not compile this correctly (ALIGN_SUBCLASS_PARTS was not def- */
745 /* ined) on all versions of Motif for Digital Unix.  We include it here  */
746 /* to get correct behavior.                                              */
747 /*************************************************************************/
748 /* and now there's a fix added; refer to OSF contact number 24617 for
749 ** details
750 */
751 /* And rewritten to support manual alignment.  HP/UX aligns doubles to
752 ** 8 bytes, but everthing else to 4.  There is NO WAY to discover at
753 ** runtime whether or not a structure contains doubles.  It cannot be
754 ** done, period; thus, the OSF mechanism won't work for PA-RISC
755 ** processors.  We get around that by specifying an extra flag (see
756 ** XiResolvePartOffsets64) saying "align my subpart (only) to 8
757 ** bytes".  This is needed in EPak only for the XiPanner widget.
758 ** Note, this mechanism does NOT work for subclasses of 8-byte-aligned
759 ** subparts.  We'd need to provide a "copy my parents offset array"
760 ** flag for that.  Since EPak doesn't need it, we don't.  Beware...
761 */
762 
763 #define ALIGN_SUBCLASS_PARTS
764 
765 #ifdef ALIGN_SUBCLASS_PARTS
766 #define _ALIGN(size) (((size) + (sizeof(double)-1)) & ~(sizeof(double)-1))
767 #else
768 #define _ALIGN(size) (size)
769 #endif
770 
771 /*
772  *  FIX for 5178: remove dependency on Xt private data
773  */
774 static Boolean
IsSubclassOf(WidgetClass wc,WidgetClass sc)775 IsSubclassOf(
776 	WidgetClass wc,
777 	WidgetClass sc)
778 {
779 	WidgetClass p = wc;
780 
781     _XmProcessLock();
782 	for(; (p) && (p != sc); p = p->core_class.superclass);
783     _XmProcessUnlock();
784 
785 	return (p == sc);
786 }
787 
788 
789 #define XtIsConstraintClass(wc) IsSubclassOf(wc, constraintWidgetClass)
790 /*
791  *  end FIX for 5178.
792  */
793 
794 void
_XiResolveAllPartOffsets(WidgetClass w_class,XmOffsetPtr * offset,XmOffsetPtr * constraint_offset,Boolean align64)795 _XiResolveAllPartOffsets(
796         WidgetClass w_class,
797         XmOffsetPtr *offset,
798         XmOffsetPtr *constraint_offset,
799 	Boolean     align64)
800 {
801     WidgetClass c, super = w_class->core_class.superclass;
802     ConstraintWidgetClass cc = NULL, scc = NULL;
803     int i, classcount = 0;
804     XmPartResource *pr;
805 
806     Boolean do_align = False;
807 
808     _XmProcessLock();
809     if (sizeof(int) != sizeof(void*))
810 	do_align = True;
811 
812     /*
813      *  Set up constraint class pointers
814      */
815     if (XtIsConstraintClass(super))
816     {
817 	cc = (ConstraintWidgetClass)w_class;
818 	scc = (ConstraintWidgetClass)super;
819     }
820 
821     /*
822      *  Update the part size value (initially, it is the size of this part)
823      */
824 
825     if (do_align)
826     {
827 	w_class->core_class.widget_size =
828 	    w_class->core_class.widget_size
829 	    + _ALIGN(super->core_class.widget_size);
830 	w_class->core_class.widget_size =
831 	    _ALIGN(w_class->core_class.widget_size);
832     }
833     else
834     {
835 	w_class->core_class.widget_size =
836 	    w_class->core_class.widget_size + super->core_class.widget_size;
837     }
838 
839     /*
840      * Another nasty hack.  Just plain old DON'T allow the size to be
841      * a multiple of anything smaller than 4.  This causes bus errors on
842      * most platforms when the constraint record is appended (by Xt)
843      * to the widget struct.  Just round up.
844      * The do_align flag above does the same thing, but only on 8 byte
845      * boundaries on 64 bit systems.  All of this code desperately
846      * needs to be re-written.
847      */
848     if(w_class->core_class.widget_size & 3) {
849 	int size = w_class->core_class.widget_size;
850 	w_class->core_class.widget_size = 4 * ((size / 4) + 1);
851     }
852 
853     if (cc && scc)
854     {
855 	if (do_align)
856 	{
857 	    cc->constraint_class.constraint_size =
858 		cc->constraint_class.constraint_size
859 		+ _ALIGN(scc->constraint_class.constraint_size);
860 	    cc->constraint_class.constraint_size =
861 		_ALIGN(cc->constraint_class.constraint_size);
862 	}
863 	else
864 	    cc->constraint_class.constraint_size =
865 		cc->constraint_class.constraint_size +
866 		scc->constraint_class.constraint_size;
867     }
868 
869     /*
870      *  Count the number of superclasses and allocate the offset record(s)
871      */
872     for (c = w_class; c != NULL; c = c->core_class.superclass) classcount++;
873 
874     *offset = (XmOffsetPtr) XtMalloc(classcount * sizeof(XmOffset));
875     if (cc)
876 	*constraint_offset = (XmOffsetPtr) XtMalloc(classcount
877 						    * sizeof(XmOffset));
878     else
879 	if(constraint_offset != NULL) *constraint_offset = NULL;
880 
881     /*
882      *  Fill in the offset table(s) with the offset of all parts
883      */
884     for (i = classcount-1, c = super; i > 0; c = c->core_class.superclass, i--)
885     {
886 	/*
887 	 * The do_align flag is true iff _all_ subparts must be 8-byte
888 	 * aligned (e.g. on an Alpha).
889 	 *
890 	 * align64 is true only if the _current_ widget part must be
891 	 * 8-byte aligned (e.g. subparts containing doubles on HP/UX)
892 	 */
893 	if (do_align ||
894 	    (c == super && align64))
895 	    (*offset)[i] = (long)_ALIGN((c->core_class.widget_size));
896 	else
897 	    (*offset)[i] = (long)(c->core_class.widget_size);
898     }
899 
900     (*offset)[0] = 0;
901 
902     if (constraint_offset != NULL && *constraint_offset != NULL) {
903 	for (i = classcount-1, scc = (ConstraintWidgetClass) super; i > 0;
904 	     scc = (ConstraintWidgetClass)(scc->core_class.superclass), i--)
905 	    if (XtIsConstraintClass((WidgetClass)scc))
906 	    {
907 		if (do_align)
908 		    (*constraint_offset)[i] =
909 			(long)_ALIGN((scc->constraint_class.constraint_size));
910 		else
911 		    (*constraint_offset)[i] =
912 			(long)(scc->constraint_class.constraint_size);
913 	    }
914 	    else
915 		(*constraint_offset)[i] = 0;
916 
917 	(*constraint_offset)[0] = 0;
918     }
919 
920     /*
921      *  Update the resource list(s) offsets in place
922      */
923     for (i = 0; i < w_class->core_class.num_resources; i++)
924     {
925 	pr = (XmPartResource *) &w_class->core_class.resources[i];
926 
927 	/* The next line updates this in place--be careful */
928 
929 	w_class->core_class.resources[i].resource_offset =
930 	    XmGetPartOffset(pr, offset);
931     }
932 
933     if (cc)
934 	for (i = 0; i < cc->constraint_class.num_resources; i++)
935 	{
936 	    pr = (XmPartResource *) &cc->constraint_class.resources[i];
937 
938 	    /* The next line updates this in place--be careful */
939 
940 	    cc->constraint_class.resources[i].resource_offset =
941 		XmGetPartOffset(pr, constraint_offset);
942 	}
943     _XmProcessUnlock();
944 }
945 
946 void
XiResolveAllPartOffsets(WidgetClass w_class,XmOffsetPtr * offset,XmOffsetPtr * constraint_offset)947 XiResolveAllPartOffsets(
948         WidgetClass w_class,
949         XmOffsetPtr *offset,
950         XmOffsetPtr *constraint_offset )
951 {
952     _XiResolveAllPartOffsets( w_class, offset, constraint_offset, False );
953 }
954 
955 void
XmResolveAllPartOffsets64(WidgetClass w_class,XmOffsetPtr * offset,XmOffsetPtr * constraint_offset)956 XmResolveAllPartOffsets64(
957         WidgetClass w_class,
958         XmOffsetPtr *offset,
959         XmOffsetPtr *constraint_offset )
960 {
961 #ifdef XM_ALIGN_64
962     _XiResolveAllPartOffsets( w_class, offset, constraint_offset, True );
963 #else
964     _XiResolveAllPartOffsets( w_class, offset, constraint_offset, False );
965 #endif
966 }
967 
968 
969 /* -------------------------------------------------------------------------- */
970 
971 
972 
973 
974 /************************************************************************
975  *
976  *  The border highlighting and unhighlighting routines.
977  *
978  *  These routines were originally in Primitive.c but not used anywhere.
979  *
980  ************************************************************************/
981 
982 void
_XmExtHighlightBorder(Widget w)983 _XmExtHighlightBorder(Widget w )
984 {
985 XtWidgetProc border_highlight;
986     if(XmIsPrimitive(w))
987     {
988         _XmProcessLock();
989         border_highlight = xmPrimitiveClassRec.primitive_class.border_highlight;
990         _XmProcessUnlock();
991 
992         (*border_highlight) (w);
993     }
994     else
995     {
996 	    if(XmIsGadget(w))
997         {
998             _XmProcessLock();
999             border_highlight = xmGadgetClassRec.gadget_class.border_highlight;
1000             _XmProcessUnlock();
1001 
1002             (*border_highlight) (w);
1003 	    }
1004     }
1005     return ;
1006 }
1007 
1008 
1009 void
_XmExtUnhighlightBorder(Widget w)1010 _XmExtUnhighlightBorder(Widget w)
1011 {
1012 XtWidgetProc border_unhighlight;
1013 
1014     if( XmIsPrimitive(w))
1015     {
1016         _XmProcessLock();
1017         border_unhighlight = xmPrimitiveClassRec.primitive_class.border_unhighlight;
1018         _XmProcessUnlock();
1019         (*border_unhighlight)(w) ;
1020     }
1021     else
1022     {
1023         if(XmIsGadget(w))
1024         {
1025             _XmProcessLock();
1026             border_unhighlight = xmGadgetClassRec.gadget_class.border_unhighlight;
1027             _XmProcessUnlock();
1028             (*border_unhighlight)(w);
1029         }
1030     }
1031     return ;
1032 }
1033