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 HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26 
27 
28 #ifdef REV_INFO
29 #ifndef lint
30 static char rcsid[] = "$XConsortium: Mrmwrefs.c /main/14 1996/11/13 14:07:43 drk $"
31 #endif
32 #endif
33 
34 
35 /*
36  *++
37  *  FACILITY:
38  *
39  *      UIL Resource Manager (URM):
40  *
41  *  ABSTRACT:
42  *
43  *	This module contains all routines which manage references to
44  *	widgets which must be handled during or immediately after
45  *	widget creation.
46  *
47  *--
48  */
49 
50 
51 /*
52  *
53  *  INCLUDE FILES
54  *
55  */
56 
57 #include <stdio.h>
58 #include <Mrm/MrmAppl.h>
59 #include <Mrm/Mrm.h>
60 #include "MrmMsgI.h"
61 
62 
63 /*
64  *++
65  *
66  *  PROCEDURE DESCRIPTION:
67  *
68  *	routine acquires a resource context, and initializes
69  *	it for use a a widget reference structure.
70  *
71  *  FORMAL PARAMETERS:
72  *
73  *	wref_id		to return pointer to initialized context
74  *
75  *  IMPLICIT INPUTS:
76  *
77  *  IMPLICIT OUTPUTS:
78  *
79  *  FUNCTION VALUE:
80  *
81  *      See UrmGetResourceContext
82  *
83  *  SIDE EFFECTS:
84  *
85  *--
86  */
87 
88 Cardinal
89 Urm__CW_InitWRef (URMResourceContextPtr		*wref_id)
90 {
91   Cardinal		result;		/* function results */
92   URMWRefStructPtr	refdsc;		/* buffer as reference structure */
93 
94 
95   /*
96    * Acquire and initialize resource context
97    */
98   result = UrmGetResourceContext ((char *(*)())NULL,(void(*)())NULL,
99 				  500, wref_id);
100   if ( result != MrmSUCCESS ) return result;
101 
102   refdsc = (URMWRefStructPtr) UrmRCBuffer (*wref_id);
103   refdsc->num_refs = 0;
104   refdsc->heap_size = 0;
105 
106   return MrmSUCCESS;
107 
108 }
109 
110 
111 
112 /*
113  *++
114  *
115  *  PROCEDURE DESCRIPTION:
116  *
117  *	This routine adds a widget definition to the widget reference structure
118  *
119  *  FORMAL PARAMETERS:
120  *
121  *	wref_id		widget reference structure
122  *	w_name		name of the widget to enter
123  *	w_id		widget id
124  *
125  *  IMPLICIT INPUTS:
126  *
127  *  IMPLICIT OUTPUTS:
128  *
129  *  FUNCTION VALUE:
130  *
131  *      See UrmResizeResourceContext
132  *
133  *  SIDE EFFECTS:
134  *
135  *--
136  */
137 
138 Cardinal
Urm__CW_AddWRef(URMResourceContextPtr wref_id,String w_name,Widget w_id)139 Urm__CW_AddWRef (URMResourceContextPtr	wref_id,
140 		 String			w_name,
141 		 Widget			w_id)
142 {
143   /*
144    *  Local variables
145    */
146   Cardinal		result;		/* function results */
147   URMWRefStructPtr	refdsc;		/* buffer as reference structure */
148   MrmCount		name_bytes;	/* # bytes for name & NULL */
149   MrmCount		bytes_needed;	/* # bytes for whole ref */
150   Cardinal		ndx;		/* entry index in structure */
151   MrmOffset		new_offs;	/* new offset in heap */
152   Cardinal		old_size;	/* old buffer size */
153   Cardinal		new_size;	/* new buffer size */
154   Cardinal		delta;		/* difference in size */
155   char			*old_heap;	/* old heap address */
156   char			*new_heap;	/* new heap address */
157 
158 
159   /*
160    * Set up pointers. Compute size needed and available, and resize structure
161    * if required. Name need not be entered if it is compiler-generated
162    * (contains non-legal character '-')
163    */
164   refdsc = (URMWRefStructPtr) UrmRCBuffer (wref_id);
165   name_bytes = strlen(w_name);
166   for ( ndx=0 ; ndx<name_bytes ; ndx++ )
167     if ( w_name[ndx] == '-' ) return MrmFAILURE;
168   name_bytes += 1;
169 
170   bytes_needed = sizeof(URMWRef) + name_bytes;
171   bytes_needed = _FULLWORD(bytes_needed);
172   if ( bytes_needed > (UrmRCBufSize(wref_id)-UrmWRefBytesUsed(refdsc)) )
173     {
174       old_size = UrmRCBufSize (wref_id);
175       new_size = 2 * old_size;
176       delta = new_size - old_size;
177       result = UrmResizeResourceContext (wref_id, new_size);
178       if ( result != MrmSUCCESS ) return result;
179       refdsc = (URMWRefStructPtr) UrmRCBuffer (wref_id);
180       old_heap = (char *) refdsc+old_size-refdsc->heap_size;
181       new_heap = (char *) (old_heap+delta);
182       UrmBCopy (old_heap, new_heap, refdsc->heap_size);
183       for ( ndx=0 ; ndx<refdsc->num_refs ; ndx++ )
184 	refdsc->refs[ndx].w_name_offs += delta;
185     }
186 
187   /*
188    * There is enough space. Copy in the name, and set up the descriptor.
189    */
190   new_offs = UrmRCBufSize(wref_id) - refdsc->heap_size - name_bytes;
191   ndx = refdsc->num_refs;
192   refdsc->refs[ndx].w_id = w_id;
193   refdsc->refs[ndx].w_name_offs = new_offs;
194   refdsc->num_refs += 1;
195   refdsc->heap_size += name_bytes;
196   strcpy ((String)refdsc+new_offs, w_name);
197 
198   return MrmSUCCESS;
199 }
200 
201 
202 
203 /*
204  *++
205  *
206  *  PROCEDURE DESCRIPTION:
207  *
208  *	This routine searches the widget reference structure for a widget,
209  *	and returns its id if found.
210  *
211  *  FORMAL PARAMETERS:
212  *
213  *	wref_id		widget reference structure
214  *	w_name		name of widget to be found
215  *	w_id_return	to return widget id
216  *
217  *  IMPLICIT INPUTS:
218  *
219  *  IMPLICIT OUTPUTS:
220  *
221  *  FUNCTION VALUE:
222  *
223  *      MrmSUCCESS	- found, id is returned
224  *	MrmNOT_FOUND	- not found
225  *
226  *  SIDE EFFECTS:
227  *
228  *--
229  */
230 
231 Cardinal
Urm__CW_FindWRef(URMResourceContextPtr wref_id,String w_name,Widget * w_id_return)232 Urm__CW_FindWRef (URMResourceContextPtr	wref_id,
233 		  String		w_name,
234 		  Widget		*w_id_return)
235 {
236   /*
237    *  Local variables
238    */
239   URMWRefStructPtr	refdsc;		/* buffer as reference structure */
240   int			ndx;		/* loop index */
241 
242 
243   /*
244    * Search the vector for the name, returning the id if found. Search
245    * backwards, so the most recent definitions are searched first.
246    */
247   refdsc = (URMWRefStructPtr) UrmRCBuffer (wref_id);
248   for ( ndx=refdsc->num_refs-1 ; ndx>=0 ; ndx-- )
249     if ( strcmp(w_name,UrmWRefNameN(refdsc,ndx)) == 0 )
250       {
251 	*w_id_return = UrmWRefIdN (refdsc, ndx);
252 	return MrmSUCCESS;
253       }
254   return MrmNOT_FOUND;
255 
256 }
257 
258 
259 
260 /*
261  *++
262  *
263  *  PROCEDURE DESCRIPTION:
264  *
265  *	This routine creates a SetValues descriptor, initializes it from
266  *	the resource descriptor, and appends it to the list. The id of the
267  *	widget to be modified is set NULL to identify this descriptor as
268  *	one to be set.
269  *
270  *  FORMAL PARAMETERS:
271  *
272  *	file_id		file from which to uncompress argtag
273  *	svlist		list of SetValues of descriptor
274  *	w_name		widget name
275  *	argtag		Argument tag code
276  *	argname		Argument tag name if code is URMcUnknown
277  *
278  *  IMPLICIT INPUTS:
279  *
280  *  IMPLICIT OUTPUTS:
281  *
282  *  FUNCTION VALUE:
283  *
284  *  SIDE EFFECTS:
285  *
286  *--
287  */
288 
289 void
Urm__CW_AppendSVWidgetRef(IDBFile file_id,URMPointerListPtr * svlist,String w_name,MrmCode argtag,String argname)290 Urm__CW_AppendSVWidgetRef (IDBFile		file_id,
291 			   URMPointerListPtr	*svlist,
292 			   String		w_name,
293 			   MrmCode		argtag,
294 			   String		argname)
295 {
296   /*
297    *  Local variables
298    */
299   URMSetValuesDescPtr	svdesc ;	/* new descriptor */
300   Cardinal		uncmp_res;	/* function result */
301   char			errmsg[300];
302 
303 
304   /*
305    * Initialize the pointer list if required
306    */
307   if ( *svlist == NULL )
308     UrmPlistInit (10, svlist) ;
309 
310   /*
311    * Create and set the new descriptor. The argument tag must be uncompressed
312    * into its string now, when the compression code for it is available from the
313    * file. If the tag code is unknown, then the string must be copied into
314    * allocated memory.
315    */
316   svdesc = (URMSetValuesDescPtr) XtMalloc (sizeof(URMSetValuesDesc)) ;
317   svdesc->setw = NULL ;
318   svdesc->type = URMsvWidgetRef ;
319   svdesc->tagcode = argtag ;
320   if ( argtag == UilMrmUnknownCode )
321     {
322       svdesc->tagname = (String) XtMalloc (strlen(argname)+1);
323       strcpy (svdesc->tagname, argname);
324     }
325   else
326     {
327       uncmp_res = Urm__UncompressCode (file_id, argtag, &svdesc->tagname);
328       if ( uncmp_res != MrmSUCCESS )
329 	{
330 	  sprintf (errmsg, _MrmMMsg_0108, argtag);
331 	  XtFree ((char *)svdesc);
332 	  Urm__UT_Error ("Urm__CW_AppendSVWidgetRef", errmsg,
333 			 NULL, NULL, MrmNOT_FOUND);
334 	  return;
335 	}
336     }
337   svdesc->done = FALSE ;
338   svdesc->sv.wname = Urm__UT_AllocString (w_name) ;
339   UrmPlistAppendPointer (( URMPointerListPtr)*svlist, (XtPointer) svdesc) ;
340 
341 }
342 
343 
344 
345 /*
346  *++
347  *
348  *  PROCEDURE DESCRIPTION:
349  *
350  *	This routine creates a SetValues descriptor, initializes it from
351  *	the resource descriptor, adds the callback list and appends it to the
352  *	list. The id of the
353  *	widget to be modified is set NULL to identify this descriptor as
354  *	one to be set.
355  *
356  *  FORMAL PARAMETERS:
357  *
358  *	file_id		file from which to uncompress argtag
359  *	svlist		list of SetValues of descriptor
360  *	w_name		widget name
361  *	argtag		Argument tag code
362  *	argname		Argument tag name if code is URMcUnknown
363  *	cbptr		Callback description pointer
364  *
365  *  IMPLICIT INPUTS:
366  *
367  *  IMPLICIT OUTPUTS:
368  *
369  *  FUNCTION VALUE:
370  *
371  *  SIDE EFFECTS:
372  *
373  *--
374  */
375 
376 void
Urm__CW_AppendCBSVWidgetRef(IDBFile file_id,URMPointerListPtr * svlist,RGMCallbackDescPtr cbptr,MrmCode argtag,String argname)377 Urm__CW_AppendCBSVWidgetRef (IDBFile			file_id,
378 			     URMPointerListPtr		*svlist,
379 			     RGMCallbackDescPtr		cbptr,
380 			     MrmCode			argtag,
381 			     String			argname)
382 {
383   URMSetValuesDescPtr	svdesc ;	/* new descriptor */
384   RGMCallbackDescPtr	cbdesc;		/* Copy of descriptor */
385   MrmSize		descsize;	/* Size of descriptor to be copied */
386   Cardinal		uncmp_res;	/* function result */
387   char			errmsg[300];
388 
389 
390   /*
391    * Initialize the pointer list if required
392    */
393   if ( *svlist == NULL )
394     UrmPlistInit (10, svlist) ;
395 
396   /*
397    * Create and set the new descriptor. The argument tag must be uncompressed
398    * into its string now, when the compression code for it is available from the
399    * file. If the tag code is unknown, then the string must be copied into
400    * allocated memory.
401    */
402   svdesc = (URMSetValuesDescPtr) XtMalloc (sizeof(URMSetValuesDesc)) ;
403   svdesc->setw = NULL ;
404   svdesc->type = URMsvCallBackList ;
405   svdesc->tagcode = argtag ;
406   if ( argtag == UilMrmUnknownCode )
407     {
408       svdesc->tagname = (String) XtMalloc (strlen(argname)+1);
409       strcpy (svdesc->tagname, argname);
410     }
411   else
412     {
413       uncmp_res = Urm__UncompressCode (file_id, argtag, &svdesc->tagname);
414       if ( uncmp_res != MrmSUCCESS )
415 	{
416 	  sprintf (errmsg, _MrmMMsg_0108, argtag);
417 	  XtFree ((char *)svdesc);
418 	  Urm__UT_Error ("Urm__CW_AppendCBSVWidgetRef", errmsg,
419 			 NULL, NULL, MrmNOT_FOUND);
420 	  return;
421 	}
422     }
423   svdesc->done = FALSE ;
424   /* Copy callback descriptor */
425   descsize = sizeof(RGMCallbackDesc) + (cbptr->count)*sizeof(RGMCallbackItem);
426   cbdesc = (RGMCallbackDescPtr)XtMalloc(descsize);
427   memcpy(cbdesc, cbptr, descsize);
428   svdesc->sv.callbacks = cbdesc ;
429   UrmPlistAppendPointer (( URMPointerListPtr)*svlist, (XtPointer) svdesc) ;
430 }
431 
432 
433 
434 /*
435  *++
436  *
437  *  PROCEDURE DESCRIPTION:
438  *
439  *	This routine updates a SetValues list from a just-created widget.
440  *	Any entry whose modified widget field is NULL is has the modified
441  *	widget set to the given widget.
442  *
443  *  FORMAL PARAMETERS:
444  *
445  *	svlist		List of SetValues descriptors
446  *	cur_id		current widget to be entered in descriptors
447  *
448  *  IMPLICIT INPUTS:
449  *
450  *  IMPLICIT OUTPUTS:
451  *
452  *  FUNCTION VALUE:
453  *
454  *  SIDE EFFECTS:
455  *
456  *--
457  */
458 
459 void
Urm__CW_UpdateSVWidgetRef(URMPointerListPtr * svlist,Widget cur_id)460 Urm__CW_UpdateSVWidgetRef (URMPointerListPtr		*svlist,
461 			   Widget			cur_id)
462 {
463   /*
464    *  Local variables
465    */
466   int			ndx ;		/* loop index */
467   URMSetValuesDescPtr	svdesc ;	/* current SetValues descriptor */
468 
469   /*
470    * Loop over all descriptors. Enter the current widget as appropriate.
471    * Since each descriptor is used only once, immediately free any
472    * allocated tag string.
473    */
474   for ( ndx=0 ; ndx<UrmPlistNum(*svlist) ; ndx++ )
475     {
476       svdesc = (URMSetValuesDescPtr) UrmPlistPtrN(*svlist,ndx) ;
477       if ( svdesc->done ) continue ;
478       if ( svdesc->setw == NULL )
479 	svdesc->setw = cur_id ;
480     }
481 }
482 
483 /*
484  *++
485  *
486  *  PROCEDURE DESCRIPTION:
487  *
488  *	This routine updates a SetValues list from a just-created widget.
489  *	Any entry whose modified widget field is NULL is has the modified
490  *	widget set to the given widget. It also uses this widget to
491  *	immediately update any previously saved widget which can be
492  *	resolved with this new widget and to update widget references
493  *	in callback items.
494  *
495  *  FORMAL PARAMETERS:
496  *
497  *	svlist		List of SetValues descriptors
498  *	cur_name	current widget's name
499  *	cur_id		current widget to be entered in descriptors
500  *
501  *  IMPLICIT INPUTS:
502  *
503  *  IMPLICIT OUTPUTS:
504  *
505  *  FUNCTION VALUE:
506  *
507  *  SIDE EFFECTS:
508  *
509  *--
510  */
511 
512 void
Urm__CW_ResolveSVWidgetRef(URMPointerListPtr * svlist,String cur_name,Widget cur_id)513 Urm__CW_ResolveSVWidgetRef (URMPointerListPtr		*svlist,
514 			    String			cur_name,
515 			    Widget			cur_id)
516 {
517   /*
518    *  Local variables
519    */
520   int			ndx ;		/* loop index */
521   int			cbndx;		/* callback list index */
522   URMSetValuesDescPtr	svdesc ;	/* current SetValues descriptor */
523   Arg			args[1] ;	/* SetValues argument list */
524   RGMCallbackDescPtr	cbdesc;		/* Current callback descriptor */
525   RGMCallbackItemPtr	items;		/* Array of callback items */
526 
527   /*
528    * Loop over all descriptors. Enter the current widget as appropriate.
529    * Since each descriptor is used only once, immediately free any
530    * allocated tag string.
531    */
532   for ( ndx=0 ; ndx<UrmPlistNum(*svlist) ; ndx++ )
533     {
534       svdesc = (URMSetValuesDescPtr) UrmPlistPtrN(*svlist,ndx) ;
535       if ( svdesc->done ) continue ;
536       if ( svdesc->setw == NULL )
537 	{
538 	  svdesc->setw = cur_id ;
539 	  continue ;
540 	}
541       switch (svdesc->type)
542 	{
543 	case URMsvWidgetRef:
544 	  if ( strcmp(cur_name,svdesc->sv.wname) == 0 )
545 	    {
546 	      args[0].name = svdesc->tagname ;
547 	      args[0].value = (XtArgVal) cur_id ;
548 	      XtSetValues (svdesc->setw, args, 1) ;
549 	      svdesc->done = TRUE ;
550 	      if ( svdesc->tagcode == UilMrmUnknownCode )
551 		{
552 		  XtFree ((char *)svdesc->tagname);
553 		  svdesc->tagname = NULL;
554 		}
555 	      /* Does this really need to be freed here? */
556 	      XtFree(svdesc->sv.wname);
557 	      svdesc->sv.wname = NULL;
558 	    }
559 	  break;
560 
561 	case URMsvCallBackList:
562 	  cbdesc = (RGMCallbackDescPtr)svdesc->sv.callbacks;
563 	  items = cbdesc->item;
564 
565 	  /* Loop through callback items, resolving where possible */
566 	  for (cbndx = 0; cbndx < cbdesc->count; cbndx++)
567 	    {
568 	      if (items[cbndx].runtime.resolved) continue;
569 
570 	      if (strcmp(cur_name, items[cbndx].runtime.wname) == 0)
571 		/* Finish resolving the callback item. */
572 		{
573 		  items[cbndx].runtime.callback.closure = (XtPointer)cur_id;
574 		  items[cbndx].runtime.resolved = TRUE;
575 		  cbdesc->unres_ref_count--;
576 		  /* Free the widget name. */
577 		  XtFree(items[cbndx].runtime.wname);
578 		  items[cbndx].runtime.wname = NULL;
579 		}
580 	    }
581 
582 	  if (cbdesc->unres_ref_count == 0)
583 	    {
584 	      /* Move individual items so array functions as callback list */
585 	      XtCallbackRec *callbacks = (XtCallbackRec *)items;
586 
587 	      for (cbndx = 0; cbndx <= cbdesc->count; cbndx++)
588 		/* <= so that null item is copied. */
589 		{
590 		  callbacks[cbndx].callback = (XtCallbackProc)
591 		    items[cbndx].runtime.callback.callback;
592 		  callbacks[cbndx].closure = (XtPointer)
593 		    items[cbndx].runtime.callback.closure;
594 		}
595 
596 
597 	      args[0].name = svdesc->tagname;
598 	      args[0].value = (XtArgVal)items;
599 	      XtSetValues(svdesc->setw, args, 1);
600 	      svdesc->done = TRUE;
601 
602 	      /* Free memory. */
603 	      if ( svdesc->tagcode == UilMrmUnknownCode )
604 		{
605 		  XtFree ((char *)svdesc->tagname);
606 		  svdesc->tagname = NULL;
607 		}
608 
609 	      XtFree((char *)svdesc->sv.callbacks);
610 	      svdesc->sv.callbacks = NULL;
611 	    }
612 	  break;
613 
614 	default:
615 	  continue;
616 	}
617     }
618 }
619 
620 /*
621  *++
622  *
623  *  PROCEDURE DESCRIPTION:
624  *
625  *      This routine frees a SetValues descriptor.
626  *
627  *  FORMAL PARAMETERS:
628  *
629  *      svdesc          SetValues descriptor
630  *
631  *  IMPLICIT INPUTS:
632  *
633  *  IMPLICIT OUTPUTS:
634  *
635  *  FUNCTION VALUE:
636  *
637  *  SIDE EFFECTS:
638  *
639  *--
640  */
641 
642 void
Urm__CW_FreeSetValuesDesc(URMSetValuesDescPtr svdesc)643 Urm__CW_FreeSetValuesDesc (URMSetValuesDescPtr         svdesc)
644 {
645   if ( (svdesc->type == URMsvWidgetRef) && (svdesc->sv.wname != NULL) )
646     XtFree ((char *)svdesc->sv.wname);
647 
648   XtFree ((char *)svdesc);
649 }
650