1 /* $XConsortium: Xm.c /main/6 1995/10/25 20:28:03 cde-sun $ */
2 /*
3  * Motif
4  *
5  * Copyright (c) 1987-2012, The Open Group. All rights reserved.
6  *
7  * These libraries and programs are free software; you can
8  * redistribute them and/or modify them under the terms of the GNU
9  * Lesser General Public License as published by the Free Software
10  * Foundation; either version 2 of the License, or (at your option)
11  * any later version.
12  *
13  * These libraries and programs are distributed in the hope that
14  * they will be useful, but WITHOUT ANY WARRANTY; without even the
15  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16  * PURPOSE. See the GNU Lesser General Public License for more
17  * details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with these librararies and programs; if not, write
21  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
22  * Floor, Boston, MA 02110-1301 USA
23  */
24 /*
25  * HISTORY
26  */
27 
28 #ifdef HAVE_CONFIG_H
29 #include <config.h>
30 #endif
31 
32 
33 #include "XmI.h"
34 #include "MessagesI.h"
35 #include <Xm/PrimitiveP.h>
36 #include <Xm/ManagerP.h>
37 #include <Xm/GadgetP.h>
38 #include <Xm/IconGP.h>
39 #include <Xm/LabelGP.h>
40 #ifdef FIX_345
41 #include <X11/keysym.h>
42 #endif
43 
44 
45 /**************************************************************************
46  *   This is Xm.c
47  *    It contains global API that:
48  *      - it's not widget specific
49  *      - it's already used by various widgets (you don't get useless
50  *          code by linking with this module: all the functions
51  *          are useful and used.
52  *   For example, TrackingLocate or ResolvePartOffset do not belong
53  *   here because they are not used by everybody.
54  *************************************************************************/
55 
56 #ifdef FIX_345
57 Boolean _init_modifiers = TRUE;
58 unsigned int NumLockMask = 0;
59 unsigned int ScrollLockMask = 0;
60 
61 
62 /*************************************<->*************************************
63  *
64  *  _XmInitModifiers (void)
65  *
66  *   Description:
67  *   -----------
68  *     Sets the appropriate mask for NumLock and ScrollLock
69  *
70  *
71  *   Inputs:
72  *   ------
73  *     None
74  *
75  *   Outputs:
76  *   -------
77  *     None
78  *
79  *   Procedures Called
80  *   -----------------
81  *     None
82  *
83  *************************************<->***********************************/
84 void
_XmInitModifiers(void)85 _XmInitModifiers (void)
86 {
87     XModifierKeymap *modmap;
88     Display *dpy;
89     KeySym *keymap;
90     unsigned int keycode;
91     int min_keycode;
92     int max_keycode;
93     int keysyms_per_keycode;
94     int i;
95 
96     dpy = _XmGetDefaultDisplay();
97     NumLockMask = 0;
98     ScrollLockMask = 0;
99     keysyms_per_keycode = 0;
100     min_keycode = 0;
101     max_keycode = 0;
102 
103     XDisplayKeycodes (dpy, &min_keycode, &max_keycode);
104     modmap = XGetModifierMapping (dpy);
105     keymap = XGetKeyboardMapping (dpy, min_keycode, max_keycode - min_keycode + 1, &keysyms_per_keycode);
106 
107     if (modmap && keymap) {
108 	for (i = 3 * modmap->max_keypermod; i < 8 * modmap->max_keypermod; i++) {
109 	    keycode = modmap->modifiermap[i];
110 	    if ((keycode >= min_keycode) && (keycode <= max_keycode)) {
111 		int j;
112 		KeySym *syms = keymap + (keycode - min_keycode) * keysyms_per_keycode;
113 
114 		for (j = 0; j < keysyms_per_keycode; j++)
115 		    if (!NumLockMask && (syms[j] == XK_Num_Lock))
116 			NumLockMask = (1 << (i / modmap->max_keypermod));
117 		    else if (!ScrollLockMask && (syms[j] == XK_Scroll_Lock))
118 			ScrollLockMask = (1 << (i / modmap->max_keypermod));
119 	    }
120 	}
121     }
122 
123     /* Cleanup memory */
124     if (modmap)
125 	XFreeModifiermap (modmap);
126 
127     if (keymap)
128 	XFree (keymap);
129 }
130 #endif
131 
132 
133 /**************************************************************************
134  *                                                                        *
135  * _XmSocorro - Help dispatch function.  Start at the widget help was     *
136  *   invoked on, find the first non-null help callback list, and call it. *
137  *   -- Called by various widgets across Xm                               *
138  *                                                                        *
139  *************************************************************************/
140 /* ARGSUSED */
141 void
_XmSocorro(Widget w,XEvent * event,String * params,Cardinal * num_params)142 _XmSocorro(
143         Widget w,
144         XEvent *event,
145         String *params,		/* unused */
146         Cardinal *num_params )	/* unused */
147 {
148     XmAnyCallbackStruct cb;
149 
150     if (w == NULL) return;
151 
152     cb.reason = XmCR_HELP;
153     cb.event = event;
154 
155     do {
156         if ((XtHasCallbacks(w, XmNhelpCallback) == XtCallbackHasSome))
157         {
158             XtCallCallbacks (w, XmNhelpCallback, &cb);
159             return;
160         }
161         else
162             w = XtParent(w);
163     }
164     while (w != NULL);
165 }
166 
167 
168 /****************************************************************
169  *
170  * _XmParentProcess
171  *    This is the entry point for parent processing.
172  *   -- Called by various widgets across Xm
173  *
174  ****************************************************************/
175 Boolean
_XmParentProcess(Widget widget,XmParentProcessData data)176 _XmParentProcess(
177         Widget widget,
178         XmParentProcessData data )
179 {
180     XmManagerWidgetClass manClass ;
181 
182     manClass = (XmManagerWidgetClass) widget->core.widget_class ;
183 
184     if(    XmIsManager( widget)
185        && manClass->manager_class.parent_process    ) {
186 	return( (*manClass->manager_class.parent_process)( widget, data)) ;
187     }
188 
189     return( FALSE) ;
190 }
191 
192 
193 
194 /************************************************************************
195  *
196  *  _XmDestroyParentCallback
197  *     Destroy parent. Used by various dialog subclasses
198  *
199  ************************************************************************/
200 /* ARGSUSED */
201 void
_XmDestroyParentCallback(Widget w,XtPointer client_data,XtPointer call_data)202 _XmDestroyParentCallback(
203         Widget w,
204         XtPointer client_data,	/* unused */
205         XtPointer call_data )	/* unused */
206 {
207    XtDestroyWidget (XtParent (w));
208 }
209 
210 
211 
212 /************************************************************************
213  *
214  *  _XmClearShadowType
215  *	Clear the right and bottom border area and save
216  *	the old width, height and shadow type.
217  *      Used by various subclasses for resize larger situation, where the
218  *      inside shadow is not exposed.
219  *   Maybe that should be moved in Draw.c, maybe not, since it's a widget API
220  *
221  ************************************************************************/
222 void
_XmClearShadowType(Widget w,int old_width,int old_height,int old_shadow_thickness,int old_highlight_thickness)223 _XmClearShadowType(
224         Widget w,
225 #if NeedWidePrototypes
226         int old_width,
227         int old_height,
228         int old_shadow_thickness,
229         int old_highlight_thickness )
230 #else
231         Dimension old_width,
232         Dimension old_height,
233         Dimension old_shadow_thickness,
234         Dimension old_highlight_thickness )
235 #endif /* NeedWidePrototypes */
236 {
237 
238     if (old_shadow_thickness == 0) return;
239 
240     if (XtIsRealized(w)) {
241       if (old_width <= w->core.width)
242 	  XClearArea (XtDisplay (w), XtWindow (w),
243 		      old_width - old_shadow_thickness -
244 		      old_highlight_thickness, 0,
245 		      old_shadow_thickness, old_height -
246 		      old_highlight_thickness,
247 		      False);
248 
249       if (old_height <= w->core.height)
250 	  XClearArea (XtDisplay (w), XtWindow (w),
251 		      0, old_height - old_shadow_thickness -
252 		      old_highlight_thickness,
253 		      old_width - old_highlight_thickness,
254 		      old_shadow_thickness,
255 		      False);
256    }
257 }
258 
259 
260 
261 /**********************************************************************
262  *
263  * _XmReOrderResourceList
264  *   This procedure moves the given resource right after the
265  *   insert_after name in this class resource list.
266  *   (+ insert_after NULL means insert in front)
267  *
268  *   ----Replace by a call to an Xt function in R6.-----
269  **********************************************************************/
270 void
_XmReOrderResourceList(WidgetClass widget_class,String res_name,String insert_after)271 _XmReOrderResourceList(
272 	WidgetClass widget_class,
273         String res_name,
274         String insert_after)
275 {
276     XrmResource **list;
277     int len;
278     XrmQuark res_nameQ = XrmPermStringToQuark(res_name);
279     XrmResource *tmp ;
280     int n ;
281 
282     _XmProcessLock();
283     list = (XrmResource **) widget_class->core_class.resources ;
284     len = widget_class->core_class.num_resources;
285 
286     /* look for the named resource slot */
287     n = 0;
288     while ((n < len) && (list[n]->xrm_name != res_nameQ))
289       n++;
290 
291     if (n < len) {
292 	int m, i;
293 	XrmQuark insert_afterQ ;
294 
295 	if (insert_after) {
296 	    insert_afterQ = XrmPermStringToQuark(insert_after) ;
297 	    /* now look for the insert_after resource slot */
298 	    m = 0;
299 	    while ((m < len) && (list[m]->xrm_name != insert_afterQ))
300 	      m++;
301 	} else m = len ;
302 	if (m == len) m = -1 ;
303 
304 	/* now do the insertion/packing, both cases */
305 	tmp = list[n] ;
306 
307 	if (n > m) {
308 	    for (i = n; i > m+1; i--)
309 		list[i] = list[i-1];
310 	    list[m+1] = tmp;
311 	} else {
312 	    for (i = n; i < m; i++)
313 		list[i] = list[i+1];
314 	    list[m] = tmp;
315 	}
316     }
317     _XmProcessUnlock();
318 }
319 
320 
321 
322 /************************************************************************
323  *
324  *  _XmWarningMsg
325  *	Add XME_WARNING to Message list so MotifWarningHandler will
326  *      add Name: & Class:
327  *
328  ************************************************************************/
329 void
_XmWarningMsg(Widget w,char * type,char * message,char ** params,Cardinal num_params)330 _XmWarningMsg(Widget w,
331 	      char *type,
332 	      char *message,
333 	      char **params,
334 	      Cardinal num_params)
335 {
336   Display * dpy;
337   char *new_params[11];
338   Cardinal num_new_params = num_params + 1;
339   int i;
340 
341   if (num_new_params > 11) num_new_params = 11;
342   for (i = 0; i < num_new_params-1; i++)
343     new_params[i] = params[i];
344   new_params[num_new_params-1] = XME_WARNING;
345 
346   if (w != NULL) {
347     XtAppWarningMsg (XtWidgetToApplicationContext(w),
348 		     XrmQuarkToString (w->core.xrm_name),
349 		     type,
350 		     w->core.widget_class->core_class.class_name,
351 		     message, new_params, &num_new_params);
352   } else
353     XtWarning(message);
354 }
355 
356 /* ARGSUSED */
357 Boolean
_XmIsISO10646(Display * dpy,XFontStruct * font)358 _XmIsISO10646(Display *dpy, XFontStruct *font)
359 {
360     Boolean ok;
361     int i;
362     char *regname;
363     Atom registry;
364     XFontProp *xfp;
365 
366     ok = False;
367     registry = XInternAtom(dpy, "CHARSET_REGISTRY", False);
368 
369     for (i = 0, xfp = font->properties;
370 	 ok == False && i < font->n_properties; xfp++, i++) {
371 	if (xfp->name == registry) {
372 	    regname = XGetAtomName(dpy, (Atom) xfp->card32);
373 	    if (strcmp(regname, "ISO10646") == 0 ||
374 		strcmp(regname, "iso10646") == 0)
375 	      ok = True;
376 	    XFree(regname);
377 	}
378     }
379     return ok;
380 }
381 
382 XChar2b*
_XmUtf8ToUcs2(char * draw_text,size_t seg_len,size_t * ret_str_len)383 _XmUtf8ToUcs2(char *draw_text, size_t seg_len, size_t *ret_str_len)
384 {
385     char *ep;
386     unsigned short codepoint;
387     XChar2b *ptr;
388     XChar2b *buf2b;
389 
390     /*
391      * Convert to UCS2 string on the fly.
392      */
393 
394      buf2b = (XChar2b *)XtMalloc(seg_len * sizeof(XChar2b));
395 
396      ep = draw_text + seg_len;
397      for (ptr = buf2b; draw_text < ep; ptr++) {
398 	if((draw_text[0]&0x80)==0) {
399 	    codepoint=draw_text[0];
400 	    draw_text++;
401 	} else if((draw_text[0]&0x20)==0) {
402 	    codepoint = (draw_text[0]&0x1F)<<6 | (draw_text[1]&0x3F);
403 	    draw_text+=2;
404         } else if((draw_text[0]&0x10)==0) {
405 	    codepoint = (draw_text[0]&0x0F)<<12
406 			    | (draw_text[1]&0x3F)<<6
407 			    | (draw_text[2]&0x3F);
408 	    draw_text+=3;
409 	} else {                    /* wrong UTF-8 */
410 	    codepoint=(unsigned)'?';
411 	    draw_text++;
412 	}
413 	ptr->byte1 = (codepoint >> 8) & 0xff;;
414 	ptr->byte2 = codepoint & 0xff;
415      }
416      *ret_str_len = ptr - buf2b;
417      return buf2b;
418 }
419 
420 
421 /***************************************/
422 /********---- PUBLIC API ----**********/
423 /*************************************/
424 
425 
426 
427 
428 /************************************************************************
429  *
430  *  XmeWarning
431  *	Build up a warning message and call Xt to get it displayed.
432  *
433  ************************************************************************/
434 void
XmeWarning(Widget w,char * message)435 XmeWarning(Widget w,
436 	   char *message )
437 {
438   char *params[1];
439   Cardinal num_params = 0;
440   Display * dpy;
441 
442   if (w != NULL) {
443     /* the MotifWarningHandler installed in VendorS.c knows about
444        this convention */
445     params[0] = XME_WARNING;
446     num_params++;
447 
448     XtAppWarningMsg (XtWidgetToApplicationContext(w),
449 		     XrmQuarkToString (w->core.xrm_name),
450 		     "XmeWarning",
451 		     w->core.widget_class->core_class.class_name,
452 		     message, params, &num_params);
453   } else
454     	XtWarning(message);
455 }
456 
457 
458 /************************************************************************
459  *
460  *  XmObjectAtPoint
461  *	new implementation that ask a manager class method
462  *   -- Called by various widgets across Xm
463  *
464  ************************************************************************/
465 Widget
XmObjectAtPoint(Widget wid,Position x,Position y)466 XmObjectAtPoint(
467         Widget wid,
468         Position x,
469         Position y )
470 {
471     XmManagerWidgetClass mw = (XmManagerWidgetClass) XtClass(wid);
472     XmManagerClassExt *mext ;
473     Widget return_wid = NULL;
474     _XmWidgetToAppContext(wid);
475 
476     _XmAppLock(app);
477 
478     if (!XmIsManager(wid)) {
479 	_XmAppUnlock(app);
480 	return NULL;
481     }
482 
483     mext = (XmManagerClassExt *)
484 	_XmGetClassExtensionPtr( (XmGenericClassExt *)
485 				&(mw->manager_class.extension), NULLQUARK) ;
486     if (!*mext) {
487 	_XmAppUnlock(app);
488 	return NULL;
489     }
490 
491     if ((*mext)->object_at_point)
492 	return_wid = ((*mext)->object_at_point)(wid, x, y);
493 
494     _XmAppUnlock(app);
495     return return_wid;
496 }
497 
498 #ifdef FIX_1381
499 /************************************************************************
500  *
501  *  _XmAssignInsensitiveColor
502  *  Allocate the Gray color for display widget like insensitive.
503  *
504  *
505  ************************************************************************/
506 
507 Pixel
_XmAssignInsensitiveColor(Widget w)508 _XmAssignInsensitiveColor(Widget w)
509 {
510 	Pixel p = 0;
511 
512 	if (XmIsPrimitive(w)) {
513 		XmPrimitiveWidget pw = (XmPrimitiveWidget) w;
514 		p = pw->primitive.bottom_shadow_color;
515 	}
516 	else if (XmIsGadget(w)) {
517 		if (XmIsLabelGadget(w)) {
518 			XmLabelGadget lg = (XmLabelGadget) w;
519 			p = LabG_BottomShadowColor(lg);
520 		}
521 		if (XmIsIconGadget(w)) {
522 			XmIconGadget  ig = (XmIconGadget) w;
523 			p = IG_BottomShadowColor(ig);
524 		}
525 	}
526 	else {
527 		p = 0;
528 	}
529 
530 	return p;
531 }
532 #endif
533 
534