Home | History | Annotate | Line # | Download | only in src
      1 /*
      2 
      3 Copyright 1985, 1986, 1987, 1988, 1989, 1994, 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 */
     26 
     27 #ifdef HAVE_CONFIG_H
     28 #include <config.h>
     29 #endif
     30 #include "IntrinsicI.h"
     31 #include "VarargsI.h"
     32 #include "StringDefs.h"
     33 
     34 static String XtNxtConvertVarToArgList = "xtConvertVarToArgList";
     35 
     36 /*
     37  *    Given a nested list, _XtCountNestedList() returns counts of the
     38  *    total number of attribute-value pairs and the count of those
     39  *    attributes that are typed. The list is counted recursively.
     40  */
     41 static void
     42 _XtCountNestedList(XtTypedArgList avlist, int *total_count, int *typed_count)
     43 {
     44     for (; avlist->name != NULL; avlist++) {
     45         if (strcmp(avlist->name, XtVaNestedList) == 0) {
     46             _XtCountNestedList((XtTypedArgList) avlist->value, total_count,
     47                                typed_count);
     48         }
     49         else {
     50             if (avlist->type != NULL) {
     51                 ++(*typed_count);
     52             }
     53             ++(*total_count);
     54         }
     55     }
     56 }
     57 
     58 /*
     59  *    Given a variable length attribute-value list, _XtCountVaList()
     60  *    returns counts of the total number of attribute-value pairs,
     61  *    and the count of the number of those attributes that are typed.
     62  *    The list is counted recursively.
     63  */
     64 void
     65 _XtCountVaList(va_list var, int *total_count, int *typed_count)
     66 {
     67     String attr;
     68 
     69     *total_count = 0;
     70     *typed_count = 0;
     71 
     72     for (attr = va_arg(var, String); attr != NULL; attr = va_arg(var, String)) {
     73         if (strcmp(attr, XtVaTypedArg) == 0) {
     74             (void) va_arg(var, String);
     75             (void) va_arg(var, String);
     76             (void) va_arg(var, XtArgVal);
     77             (void) va_arg(var, int);
     78 
     79             ++(*total_count);
     80             ++(*typed_count);
     81         }
     82         else if (strcmp(attr, XtVaNestedList) == 0) {
     83             _XtCountNestedList(va_arg(var, XtTypedArgList), total_count,
     84                                typed_count);
     85         }
     86         else {
     87             (void) va_arg(var, XtArgVal);
     88             ++(*total_count);
     89         }
     90     }
     91 }
     92 
     93 /*
     94  *   Given a variable length attribute-value list, XtVaCreateArgsList()
     95  *   constructs an attribute-value list of type XtTypedArgList and
     96  *   returns the list.
     97  */
     98 XtVarArgsList
     99 XtVaCreateArgsList(XtPointer unused _X_UNUSED, ...)
    100 {
    101     va_list var;
    102     XtTypedArgList avlist;
    103     int count = 0;
    104     String attr;
    105 
    106     /*
    107      * Count the number of attribute-value pairs in the list.
    108      * Note: The count is required only to allocate enough space to store
    109      * the list. Therefore nested lists are not counted recursively.
    110      */
    111     va_start(var, unused);
    112     for (attr = va_arg(var, String); attr != NULL; attr = va_arg(var, String)) {
    113         ++count;
    114         if (strcmp(attr, XtVaTypedArg) == 0) {
    115             (void) va_arg(var, String);
    116             (void) va_arg(var, String);
    117             (void) va_arg(var, XtArgVal);
    118             (void) va_arg(var, int);
    119         }
    120         else {
    121             (void) va_arg(var, XtArgVal);
    122         }
    123     }
    124     va_end(var);
    125 
    126     va_start(var, unused);
    127     avlist = _XtVaCreateTypedArgList(var, count);
    128     va_end(var);
    129     return (XtVarArgsList) avlist;
    130 }
    131 
    132 XtTypedArgList
    133 _XtVaCreateTypedArgList(va_list var, register int count)
    134 {
    135     String attr;
    136     XtTypedArgList avlist;
    137 
    138     avlist = (XtTypedArgList)
    139         __XtCalloc((Cardinal) count + 1, (unsigned) sizeof(XtTypedArg));
    140 
    141     for (attr = va_arg(var, String), count = 0; attr != NULL;
    142          attr = va_arg(var, String)) {
    143         if (strcmp(attr, XtVaTypedArg) == 0) {
    144             avlist[count].name = va_arg(var, String);
    145             avlist[count].type = va_arg(var, String);
    146             avlist[count].value = va_arg(var, XtArgVal);
    147             avlist[count].size = va_arg(var, int);
    148         }
    149         else {
    150             avlist[count].name = attr;
    151             avlist[count].type = NULL;
    152             avlist[count].value = va_arg(var, XtArgVal);
    153         }
    154         ++count;
    155     }
    156     avlist[count].name = NULL;
    157 
    158     return avlist;
    159 }
    160 
    161 /*
    162  *    TypedArgToArg() invokes a resource converter to convert the
    163  *    passed typed arg into a name/value pair and stores the name/value
    164  *    pair in the passed Arg structure.  If memory is allocated for the
    165  *    converted value, the address is returned in the value field of
    166  *    memory_return; otherwise that field is NULL.  The function returns
    167  *    1 if the conversion succeeded and 0 if the conversion failed.
    168  */
    169 static int
    170 TypedArgToArg(Widget widget,
    171               XtTypedArgList typed_arg,
    172               ArgList arg_return,
    173               XtResourceList resources,
    174               Cardinal num_resources,
    175               ArgList memory_return)
    176 {
    177     String to_type = NULL;
    178     XrmValue from_val, to_val;
    179 
    180     if (widget == NULL) {
    181         XtAppWarningMsg(XtWidgetToApplicationContext(widget),
    182                         "nullWidget", XtNxtConvertVarToArgList,
    183                         XtCXtToolkitError,
    184                         "XtVaTypedArg conversion needs non-NULL widget handle",
    185                         NULL, NULL);
    186         return (0);
    187     }
    188 
    189     /* again we assume that the XtResourceList is un-compiled */
    190 
    191     for (; num_resources--; resources++)
    192         if (strcmp(typed_arg->name, resources->resource_name) == 0) {
    193             to_type = resources->resource_type;
    194             break;
    195         }
    196 
    197     if (to_type == NULL) {
    198         XtAppWarningMsg(XtWidgetToApplicationContext(widget),
    199                         "unknownType", XtNxtConvertVarToArgList,
    200                         XtCXtToolkitError,
    201                         "Unable to find type of resource for conversion", NULL,
    202                         NULL);
    203         return (0);
    204     }
    205 
    206     to_val.addr = NULL;
    207     from_val.size = (Cardinal) typed_arg->size;
    208     if ((strcmp(typed_arg->type, XtRString) == 0) ||
    209         ((unsigned) typed_arg->size > sizeof(XtArgVal))) {
    210         from_val.addr = (XPointer) typed_arg->value;
    211     }
    212     else {
    213         from_val.addr = (XPointer) &typed_arg->value;
    214     }
    215 
    216     LOCK_PROCESS;
    217     XtConvertAndStore(widget, typed_arg->type, &from_val, to_type, &to_val);
    218 
    219     if (to_val.addr == NULL) {
    220         UNLOCK_PROCESS;
    221         XtAppWarningMsg(XtWidgetToApplicationContext(widget),
    222                         "conversionFailed", XtNxtConvertVarToArgList,
    223                         XtCXtToolkitError, "Type conversion failed", NULL,
    224                         NULL);
    225         return (0);
    226     }
    227 
    228     arg_return->name = typed_arg->name;
    229     memory_return->value = (XtArgVal) NULL;
    230 
    231     if (strcmp(to_type, XtRString) == 0) {
    232         arg_return->value = (XtArgVal) to_val.addr;
    233     }
    234     else {
    235         if (to_val.size == sizeof(long))
    236             arg_return->value = (XtArgVal) * (long *) to_val.addr;
    237         else if (to_val.size == sizeof(int))
    238             arg_return->value = (XtArgVal) * (int *) to_val.addr;
    239         else if (to_val.size == sizeof(short))
    240             arg_return->value = (XtArgVal) * (short *) to_val.addr;
    241         else if (to_val.size == sizeof(char))
    242             arg_return->value = (XtArgVal) * (char *) to_val.addr;
    243         else if (to_val.size == sizeof(XtArgVal))
    244             arg_return->value = *(XtArgVal *) to_val.addr;
    245         else if (to_val.size > sizeof(XtArgVal)) {
    246             arg_return->value = (XtArgVal) (void *) __XtMalloc(to_val.size);
    247             if ((memory_return->value = arg_return->value) != 0)
    248                 memcpy((void *) arg_return->value, to_val.addr, to_val.size);
    249         }
    250     }
    251     UNLOCK_PROCESS;
    252 
    253     return (1);
    254 }
    255 
    256 /*
    257  *    NestedArgtoArg() converts the passed nested list into
    258  *    an ArgList/count.
    259  */
    260 static int
    261 NestedArgtoArg(Widget widget,
    262                XtTypedArgList avlist,
    263                ArgList args,
    264                XtResourceList resources,
    265                Cardinal num_resources,
    266                ArgList memory_return)
    267 {
    268     int count = 0;
    269 
    270     for (; avlist->name != NULL; avlist++) {
    271         if (avlist->type != NULL) {
    272             /* If widget is NULL, the typed arg is ignored */
    273             if (widget != NULL) {
    274                 /* this is a typed arg */
    275                 count += TypedArgToArg(widget, avlist, (args + count),
    276                                        resources, num_resources,
    277                                        (memory_return + count));
    278             }
    279         }
    280         else if (strcmp(avlist->name, XtVaNestedList) == 0) {
    281             count += NestedArgtoArg(widget, (XtTypedArgList) avlist->value,
    282                                     (args + count), resources, num_resources,
    283                                     (memory_return + count));
    284         }
    285         else {
    286             (args + count)->name = avlist->name;
    287             (args + count)->value = avlist->value;
    288             ++count;
    289         }
    290     }
    291 
    292     return (count);
    293 }
    294 
    295 /*
    296  * Free memory allocated through _XtVaToArgList.  The actual args array
    297  * size is expected to be total_count * 2, where total_count is the number
    298  * of elements needed for resource representations.  The lower half of the
    299  * array contains pairs of resource names and values as usual.  For each
    300  * element [n] in the lower half of the array, the value field of the
    301  * corresponding element [n + total_count] in the upper half of the array
    302  * has been pressed into service in order to note whether the resource value
    303  * is a pointer to memory that was allocated in TypedArgToArg.  In the
    304  * upper half, if the value field is not NULL, it contains the address of
    305  * memory which should now be freed.  That memory could have been allocated
    306  * only as a result of the conversion of typed arguments.  Therefore, if
    307  * there were no typed arguments in the original varargs, there is no need
    308  * to examine the upper half of the array.  In the choice of data structure
    309  * to make this representation, priority was given to the wish to retrofit
    310  * the release of memory around the existing signature of _XtVaToArgList.
    311  */
    312 void
    313 _XtFreeArgList(ArgList args,    /* as returned by _XtVaToArgList */
    314                int total_count, /* argument count returned by _XtCountVaList */
    315                int typed_count) /* typed arg count returned by _XtCountVaList */
    316 {
    317     if (args) {
    318         if (typed_count) {
    319             ArgList p;
    320 
    321             for (p = args + total_count; total_count--; ++p) {
    322                 XtFree((char *) p->value);
    323             }
    324         }
    325         XtFree((char *) args);
    326     }
    327 }
    328 
    329 static void GetResources(Widget widget, XtResourceList *res_list,
    330                          Cardinal *number);
    331 
    332 /*
    333  *    Given a variable argument list, _XtVaToArgList() returns the
    334  *    equivalent ArgList and count. _XtVaToArgList() handles nested
    335  *    lists and typed arguments.  If typed arguments are present, the
    336  *    ArgList should be freed with _XtFreeArgList.
    337  */
    338 void
    339 _XtVaToArgList(Widget widget,
    340                va_list var,
    341                int max_count,
    342                ArgList *args_return,
    343                Cardinal *num_args_return)
    344 {
    345     String		attr;
    346     int			count;
    347     ArgList		args = (ArgList)NULL;
    348     XtTypedArg		typed_arg;
    349     XtResourceList	resources = (XtResourceList)NULL;
    350     Cardinal		num_resources = 0;
    351     Boolean		fetched_resource_list = False;
    352 
    353     *num_args_return = 0;
    354     *args_return = (ArgList)NULL;
    355 
    356     if (max_count  == 0)
    357 	return;
    358 
    359     args = (ArgList)__XtCalloc((Cardinal)(max_count * 2),  sizeof(Arg));
    360     if (!args)
    361 	return;
    362 
    363     count = 0;
    364 
    365     for(attr = va_arg(var, String) ; attr != NULL;
    366 			    attr = va_arg(var, String)) {
    367 	    if (strcmp(attr, XtVaTypedArg) == 0) {
    368 		typed_arg.name = va_arg(var, String);
    369 		typed_arg.type = va_arg(var, String);
    370 		typed_arg.value = va_arg(var, XtArgVal);
    371 		typed_arg.size = va_arg(var, int);
    372 
    373 		/* if widget is NULL, typed args are ignored */
    374 		if (widget != NULL) {
    375 		    if (!fetched_resource_list) {
    376 			GetResources(widget, &resources, &num_resources);
    377 			fetched_resource_list = True;
    378 		    }
    379 		    count += TypedArgToArg(widget, &typed_arg, &args[count],
    380 					      resources, num_resources,
    381 					      &args[max_count + count]);
    382 		}
    383 	    } else if (strcmp(attr, XtVaNestedList) == 0) {
    384 		if (widget != NULL) {
    385 		    if (!fetched_resource_list) {
    386 			GetResources(widget, &resources, &num_resources);
    387 			fetched_resource_list = True;
    388 		    }
    389 		}
    390 
    391 		count += NestedArgtoArg(widget, va_arg(var, XtTypedArgList),
    392 					   &args[count], resources, num_resources,
    393 					   &args[max_count + count]);
    394 	    } else {
    395 		args[count].name = attr;
    396 		args[count].value = va_arg(var, XtArgVal);
    397 		count ++;
    398 	    }
    399     }
    400     XtFree((XtPointer) resources);
    401 
    402     *num_args_return = (Cardinal) count;
    403     *args_return = (ArgList) args;
    404 }
    405 
    406 /*      Function Name: GetResources
    407  *      Description: Retrieves the normal and constraint resources
    408  *                   for this widget.
    409  *      Arguments: widget - the widget.
    410  * RETURNED        res_list - the list of resource for this widget
    411  * RETURNED        number - the number of resources in the above list.
    412  *      Returns: none
    413  */
    414 
    415 static void
    416 GetResources(Widget widget, XtResourceList *res_list, Cardinal *number)
    417 {
    418     Widget parent = XtParent(widget);
    419 
    420     XtInitializeWidgetClass(XtClass(widget));
    421     XtGetResourceList(XtClass(widget), res_list, number);
    422 
    423     if (!XtIsShell(widget) && parent && XtIsConstraint(parent)) {
    424         XtResourceList res, constraint, cons_top;
    425         Cardinal num_constraint, temp;
    426 
    427         XtGetConstraintResourceList(XtClass(parent), &constraint,
    428                                     &num_constraint);
    429 
    430         cons_top = constraint;
    431         *res_list = XtReallocArray(*res_list, *number + num_constraint,
    432                                    (Cardinal) sizeof(XtResource));
    433 
    434         for (temp = num_constraint, res = *res_list + *number; temp != 0;
    435              temp--)
    436             *res++ = *constraint++;
    437 
    438         *number += num_constraint;
    439         XtFree((XtPointer) cons_top);
    440     }
    441 }
    442 
    443 static int
    444 NestedArgtoTypedArg(XtTypedArgList args, XtTypedArgList avlist)
    445 {
    446     int count = 0;
    447 
    448     for (; avlist->name != NULL; avlist++) {
    449         if (avlist->type != NULL) {
    450             (args + count)->name = avlist->name;
    451             (args + count)->type = avlist->type;
    452             (args + count)->size = avlist->size;
    453             (args + count)->value = avlist->value;
    454             ++count;
    455         }
    456         else if (strcmp(avlist->name, XtVaNestedList) == 0) {
    457             count += NestedArgtoTypedArg((args + count),
    458                                          (XtTypedArgList) avlist->value);
    459         }
    460         else {
    461             (args + count)->name = avlist->name;
    462             (args + count)->type = NULL;
    463             (args + count)->value = avlist->value;
    464             ++count;
    465         }
    466     }
    467     return (count);
    468 }
    469 
    470 /*
    471  *    Given a variable argument list, _XtVaToTypedArgList() returns
    472  *    the equivalent TypedArgList. _XtVaToTypedArgList() handles nested
    473  *    lists.
    474  *    Note: _XtVaToTypedArgList() does not do type conversions.
    475  */
    476 void
    477 _XtVaToTypedArgList(va_list var,
    478                     int max_count,
    479                     XtTypedArgList *args_return,
    480                     Cardinal *num_args_return)
    481 {
    482     XtTypedArgList args;
    483     String attr;
    484     int count;
    485 
    486     *args_return = NULL;
    487     *num_args_return = 0;
    488 
    489     if (max_count  == 0)
    490 	return;
    491 
    492     args = (XtTypedArgList)
    493         __XtCalloc((Cardinal) max_count , sizeof(XtTypedArg));
    494     if (!args)
    495     	return;
    496 
    497     count=0;
    498 
    499     for (attr = va_arg(var, String); attr != NULL;
    500          attr = va_arg(var, String)) {
    501         if (strcmp(attr, XtVaTypedArg) == 0) {
    502             args[count].name = va_arg(var, String);
    503             args[count].type = va_arg(var, String);
    504             args[count].value = va_arg(var, XtArgVal);
    505             args[count].size = va_arg(var, int);
    506 
    507             ++count;
    508         }
    509         else if (strcmp(attr, XtVaNestedList) == 0) {
    510             count += NestedArgtoTypedArg(&args[count],
    511                                          va_arg(var, XtTypedArgList));
    512         }
    513         else {
    514             args[count].name = attr;
    515             args[count].type = NULL;
    516             args[count].value = va_arg(var, XtArgVal);
    517             ++count;
    518         }
    519     }
    520 
    521     *args_return = args;
    522     *num_args_return = (Cardinal) count;
    523 }
    524