Manipulating Resources in Application Code

This chapter describes how you can set and get the values of a widget's resources inside your application.

It includes:

Although you can set the initial values of a widget's resources in PhAB, you'll probably need to access them from your code. For example:

In addition, if you use PtCreateWidget() to instantiate a widget in your code, you can give an initial value to its resources.

The value for the resource is specified or retrieved using an argument list.


Note: There are two steps involved in specifying or retrieving more than one resource value:
  • Setting up the argument list, using the PtSetArg() macro.
  • Setting the value, using PtSetResources(), or retrieving the value, using PtGetResources().

If you're getting or setting one resource, it's easier to use PtGetResource() or PtSetResource() — you don't need to set up the argument list.


Argument lists

An argument list is an array of PtArg_t structures (see the Photon Library Reference). Each of these elements identifies a widget resource and a new value for the resource (or the address of a variable that will be set to the resource's current value).

You can use the PtSetArg() macro to initialize each element of the argument list:

PtSetArg( PtArg_t *arg,
          long type,
          long value,
          long len );

Note: If the values don't need to be calculated at runtime, you might be able to use Pt_ARG() instead to initialize the argument list. For more information, see the Photon Library Reference.

The first two arguments to PtSetArg() are the address of the argument list element, and the name of the resource. The third and fourth arguments vary, depending on the type of the resource, and on whether a set or a get operation is being applied. When setting a resource, the third argument is always used to hold a resource value or a pointer to a resource's value.

The fourth argument is used as either a size indicator or a mask, depending on the type of the value being specified. The possible resource types are given in the table below:

Type: Description:
Alloc An arbitrarily sized memory object
Array An array
Boolean A bit that's either on or off
Color A color
Complex A resource that's handled in a special way; see below.
Flag A value in which each bit has a different meaning
Function A pointer to a function
Image A pointer to a PhImage_t structure
Link A linked list
Pointer A pointer to an address that you specify
Scalar A value that can be represented within a single long
String A null-terminated string
Struct A fixed-size data type, usually a structure, float, or double

For information about the resources defined for each widget, see the Photon Widget Reference.


Note: Complex resources are special; see their descriptions in the Widget Reference for instructions for setting and getting them. Widgets that have complex resources usually have convenience functions to make it easier to work with them.

Setting resources

Remember that there are two steps involved in setting more than one resource value:

If you're setting one resource, it's easier to use PtSetResource() — you don't need to set up the argument list. See Setting one resource,” below.

Argument lists for setting resources

Many of the sections that follow demonstrate setting some resources for a PtComboBox widget. Note that you can set more than one resource at a time. To do so, define an argument list of the appropriate length:

PtArg_t  args[5];

After initializing the argument list, you'll actually set the resources.

Scalar and color resources

When setting a scalar value, you should specify the value as the third argument to PtSetArg(). The fourth argument isn't used and should be set to 0.

For example, to set the bevel width of the combo box, pass the new value as the third argument:

PtSetArg(&args[0], Pt_ARG_BEVEL_WIDTH, 5, 0);

When you call PtSetResources(), the widget copies the scalar value into its own internal data structure.

String resources

Setting a string value is similar to setting a scalar value; you specify the string as the third argument to the PtSetArg() macro. The fourth argument is the number of bytes to copy; if it's 0, strlen() is used to determine the length of the string.

For example, to set the default text for the combo box, you could specify a value for the Pt_ARG_TEXT_STRING resource in one element of the argument list:

PtSetArg(&args[1], Pt_ARG_TEXT_STRING,
         "Rectangle", 0);

When you call PtSetResources(), the widget copies the string into its own internal data structure.

If you need to use international (non-ASCII) characters in a string, do one of the following:

For more information on Unicode and UTF-8, see the appendix on Unicode Multilingual Support.

Alloc resources

Some resources are designed to store an allocated block of memory. For example, every widget includes a Pt_ARG_USER_DATA resource that you can use to store any data you want in the widget's internal memory. To set this resource, pass a pointer to the data as the third argument to PtSetArg(). The fourth argument is the size of the block of memory, in bytes:

my_struct user_data;

/* Initialize the data */

PtSetArg(&args[2], Pt_ARG_USER_DATA, &user_data,
         sizeof (user_data));

The widget copies the number of bytes given into its internal memory when you call PtSetResources().

Image resources

Image resources are designed to store a PhImage_t structure. For example, a PtLabel has a Pt_ARG_LABEL_IMAGE resource that you can use to store an image. To set this resource, create and initialize the PhImage_t structure, and pass a pointer to it as the third argument to PtSetArg(). The fourth argument is 0:

PhImage_t *my_image;

/* Create and initialize the image. */

PtSetArg(&args[2], Pt_ARG_LABEL_IMAGE, my_image, 0);

The widget copies the image structure (but not any memory pointed to by the PhImage_t members) into its internal memory when you call PtSetResources().

Array resources

When setting an array value, the third argument to PtSetArg() is the address of the array. The fourth argument is the number of elements in the array.

For example, the following entry in the argument list can be used to set up Pt_ARG_ITEMS, the list of choices for the combo box:

char *cbox_items[3] = {"Circle", "Rectangle", "Polygon"};

PtSetArg(&args[3], Pt_ARG_ITEMS, cbox_items, 3);

The widget copies the contents of the array into its own internal data structure when you call PtSetResources().

Flag resources

When setting a flag, the third argument to PtSetArg() is a bit field specifying the value of the bits to be set. The fourth argument is a bit mask indicating which elements of the bit field should be used.


Note: For the value, use Pt_TRUE, Pt_FALSE, or a combination of specific bits and their complements. Don't use a value of 1, since it contains just one bit that's on; that bit might not correspond to the bit you're trying to set.

For example, the following argument list specification turns on the combo box widget's Pt_COMBOBOX_STATIC flag (so that the combo box always displays the list of items):

PtSetArg(&args[4], Pt_ARG_CBOX_FLAGS,
         Pt_TRUE, Pt_COMBOBOX_STATIC);

When you call PtSetResources(), the widget uses the bit mask to determine which bits of its internal flag resource representation to alter. It takes the bit values from the value specified.

Function resources

When setting a function resource, pass a pointer to the function as the third argument to PtSetArg(). The fourth argument is ignored; set it to 0.

For example, to specify a drawing function for a PtRaw widget, set the Pt_ARG_RAW_DRAW_F resource as follows:

PtSetArg( &args[0], Pt_ARG_RAW_DRAW_F,
          &my_raw_draw_fn, 0);

When you call PtSetResources(), the widget copies the pointer into the resource.

Pointer resources

When setting a pointer resource, the pointer must be given as the third argument to PtSetArg(). The fourth argument is ignored and should be set to 0.

When you call PtSetResources(), the widget simply does a shallow copy of the pointer into the resource.


Note: The widget doesn't make a copy of the memory referenced by the pointer; don't free the memory while the widget is still referencing it.

For example, every widget includes a Pt_ARG_POINTER resource that you can use to store in the widget's internal memory a pointer to arbitrary data. The widget never refers to this data; it's just for you to use. To set this resource, allocate the desired memory, and pass a pointer to it as the third argument to PtSetArg(). The fourth argument is set to 0:

my_struct *user_data;

/* Allocate and initialize the data */

PtSetArg( &args[0], Pt_ARG_POINTER, user_data, 0 );

The widget copies the value of the pointer into its internal memory when you call PtSetResources().

Link resources

When setting a Link, pass the address of an array of data as the third argument to PtSetArg(). The fourth argument has some special meanings:

num
append num items (if num is 0, one item is appended)
Pt_LINK_INSERT
insert the first array element at the beginning of the linked list
Pt_LINK_DELETE
remove the first list element that matches the first array element

The widget copies the data into its internal memory when you call PtSetResources().

Struct resources

When setting a struct resource, pass the address of the data as the third argument to PtSetArg(). The fourth argument isn't used and should be set to 0.

The widget copies the data into its internal memory when you call PtSetResources().

Boolean resources

When setting a Boolean value, you should specify the value as the third argument to PtSetArg(), using 0 for false, and a nonzero value for true. The fourth argument isn't used, and should be set to 0.

For example, to set the protocol for a PtTerminal to ANSI, pass a nonzero value as the third argument:

PtSetArg(&args[1], Pt_ARG_TERM_ANSI_PROTOCOL, 1, 0);

When you call PtSetResources(), the widget clears or sets one bit in its own internal data structure depending on whether or not the value is zero.

Calling PtSetResources()

Once you've set up the argument list, you're ready to set the resources. Remember that PtSetArg() doesn't set the resources; it just sets up the argument list.

You can use PtSetResources() to set the new values for resources:

int PtSetResources( PtWidget_t *widget,
                    int n_args,
                    PtArg_t *args );

The arguments to this function are a pointer to the widget, the number of entries in the argument list, and the argument list itself.

You can also set resources by passing an argument list to PtCreateWidget(). The rules for specifying values in argument list elements are the same. For more information, see Creating widgets in the Managing Widgets in Application Code chapter.

For example, you could set the resources of a combo box, using the argument list created above. Call PtSetResources() as follows:

PtSetResources (ABW_shapes_cbox, 5, args);

In response to a change to its resources, a widget may have to redisplay itself. The PtSetResources() call triggers this change. Any changes to the appearance of the widget, however, don't take effect until control is restored to the Photon event-handling loop. Therefore, if PtSetResources() is called from within a callback function or an event-handling function, the change to the widget won't be visible until all the callbacks in the callback list and all event handlers have been executed.

Setting one resource

If you're setting one resource, it's easier to use PtSetResource() than PtSetResources(). With PtSetResource(), you don't need to set up the argument list.

The arguments to PtSetResource() are a combination of those for PtSetArg() and PtSetResources():

int PtSetResource( PtWidget_t *widget,
                   long type,
                   long value,
                   long len );

The widget is a pointer to the widget whose resource you're setting. The other arguments are set just as they are for PtSetArg() when setting more than one resource. See Argument lists for setting resources,” above.

For example, setting one resource with PtSetResources() requires code like this:

PtArg_t args[1];

PtSetArg(&args[0], Pt_ARG_BEVEL_WIDTH, 5, 0);
PtSetResources (ABW_shapes_cbox, 1, args);

Setting the same resource with PtSetResource() is like this:

PtSetResource (ABW_shapes_cbox,
               Pt_ARG_BEVEL_WIDTH, 5, 0);

It takes just one function call, and there's no need for an args array.

Getting resources

There are two steps involved in retrieving more than one resource value:

If you're getting one resource, it's easier to use PtGetResource() — you don't need to set up the argument list. See Getting one resource,” below.

There are two methods of getting resources: one that involves pointers, and one that doesn't. The nonpointer method is usually easier and safer:

The pointer method may be less confusing if you're getting the values of several resources at once; you'll have named pointers to the values instead of having to remember which element in the argument list corresponds to which resource.

Not using pointers

If you set the value and len arguments to PtSetArg() to zero, PtGetResources() returns the resource's value (converted to long) as follows:

Resource type value len
Flags (any C type) Value of the resource N/A
Scalar (any C type) Value of the resource N/A
Pointer (any C type) Value of the resource N/A
String Address of the string N/A
Struct Address of the data N/A
Array Address of the first array item Number of items in the array
Alloc Address of where the resource is stored N/A
Boolean 0 (false) or 1 (true) N/A

Scalar and flag resources (nonpointer method)

To get a scalar or flag resource (of any C type) with the nonpointer method:

unsigned long getscalar( PtWidget_t *widget, long type ) {
    /* Get any kind of scalar */
    PtArg_t arg;
    PtSetArg( &arg, type, 0, 0 );
    PtGetResources( widget, 1, &arg );
    return arg.value;
    }

String resources (nonpointer method)

Here's how to use the nonpointer method to get the value of a string resource:

const char *getstr2( PtWidget_t *widget, long type ) {
    PtArg_t arg;

    PtSetArg( &arg, type, 0, 0 );
    PtGetResources( widget, 1, &arg );
    return (char*) arg.value;
    }

Boolean resources (nonpointer method)

In the nonpointer method to get a boolean, the value (0 or 1) is returned in value argument to PtSetArg():

int getbool( PtWidget_t *widget, long type ) {
    PtArg_t arg;

    PtSetArg( &arg, type, 0, 0 );
    PtGetResources( widget, 1, &arg );
    return arg.value;
    }

Using pointers

When using the pointer method to get a scalar, array, or flag resource, the widget always gives a pointer to an internal widget data structure. In the argument list element you set up using PtSetArg(), you must provide the address of a variable to which the internal data pointer can be assigned.

The fourth argument isn't used for most types of resources. For arrays, it's the address of a pointer that on return from PtGetResources() points to the number of entries.

For example, to obtain the contents of the Pt_ARG_FLAGS resource (which is a long) for a widget, you must pass the address of a pointer to a long:

const long *flags;
PtArg_t arg[1];

PtSetArg(&arg[0], Pt_ARG_FLAGS, &flags, 0);
PtGetResources(ABW_label, 1, arg);

Caution: PtGetResources() returns pointers directly into the widget's internal memory. Don't attempt to modify the resources directly using these pointers. Such a modification won't have the desired effect and will likely corrupt the widget's behavior. Never free these pointers either — this will certainly result in a memory violation or some other fault.

Using const pointers will help avoid these problems.

Changes to the widget's state may invalidate these pointers; use them promptly.


If you wish to retrieve the value of a given resource and then modify that value:

  1. Get the resource.
  2. Copy the resource to a temporary variable.
  3. Modify the temporary variable.
  4. Using the modified copy, set the resource.

You can use the value obtained to set the value of another resource of this or any other widget, as long as you don't change the original value.

For example, you can use the following code to obtain Pt_ARG_TEXT_STRING, the text string displayed in the label widget named label:

char *str;
PtArg_t args[1];

PtSetArg(&args[0], Pt_ARG_TEXT_STRING, &str, 0);
PtGetResources(ABW_label, 1, args);

You can then assign this text string to another label named label2:

PtSetArg(&args[0], Pt_ARG_TEXT_STRING, str, 0);
PtSetResources(ABW_label2, 1, args);

Scalar and flag resources (pointer method)

If you're getting scalar or flag resources using the pointer method:

When PtGetResources() is called, the pointer is set to point to the widget's internal storage for that resource.

Here are some functions that get a scalar or flag resource, using the pointer method:

unsigned long getlong( PtWidget_t *widget, long type ) {
    /* Get a long or long flags */
    PtArg_t arg; unsigned long const *result;

    PtSetArg( &arg, type, &result, 0 );
    PtGetResources( widget, 1, &arg );
    return *result;
    }

unsigned getshort( PtWidget_t *widget, long type ) {
    /* Get a short or short flags */
    PtArg_t arg; unsigned short const *result;

    PtSetArg( &arg, type, &result, 0 );
    PtGetResources( widget, 1, &arg );
    return *result;
    }

unsigned getbyte( PtWidget_t *widget, long type ) {
    /* Get a char or char flags */
    PtArg_t arg; unsigned char const *result;

    PtSetArg( &arg, type, &result, 0 );
    PtGetResources( widget, 1, &arg );
    return *result;
    }

String resources (pointer method)

If you're getting string resources using the pointer method:

When PtGetResources() is called, the pointer specified is set to point to the widget's internal storage for the string resource. For example:

const char *getstr1( PtWidget_t *widget, long type ) {
    PtArg_t arg; const char *str;

    PtSetArg( &arg, type, &str, 0 );
    PtGetResources( widget, 1, &arg );
    return str;
    }

Alloc resources (pointer method)

If you're getting alloc resources using the pointer method:

When PtGetResources() is called, the pointer specified is set to point to the widget's internal data.

Image resources (pointer method)

If you're getting Image resources using the pointer method:

When PtGetResources() is called, the pointer specified is set to point to the widget's internal data.

Array resources (pointer method)

If you're getting array resources using the pointer method:

When PtGetResources() is called:

Pointer resources (pointer method)

If you're getting pointer resources using the pointer method:

When PtGetResources() is called, the pointer specified is set to point to the same data as the widget's internal pointer. The data is external to the widget; you might be able to modify it, depending on the resource.

Link resources (pointer method)

If you're getting link resources using the pointer method:

When PtGetResources() is called, The pointer given by value is set to point to the first node of the widget's internal linked list.


Note: If you get a callback resource, the value argument to PtSetArg() is the address of a pointer to a PtCallbackList_t structure. For more information, see Examining callbacks in the Managing Widgets in Application Code chapter.

Struct resources (pointer method)

If you're getting struct resources using the pointer method:

When PtGetResources() is called, the pointer specified is set to point to the widget's internal storage for the struct resource.

Boolean resources (pointer method)

If you're getting boolean resources using the pointer method:

When PtGetResources() is called, the int is set to 1 if the Boolean is true, or 0 if it's false.

For example, to get the value of the Pt_ARG_CURSOR_OVERRIDE resource of a PtContainer:

PtArg_t arg;
int     bool_value;

PtSetArg( &arg[0], Pt_ARG_CURSOR_OVERRIDE, &bool_value, 0 );
PtGetResources (ABW_container, 1, arg);

if ( bool_value ) {
  /* The container's cursor overrides that of its children. */
}

Calling PtGetResources()

Use PtGetResources() to obtain the values of each of the resources identified in an argument list:

int PtGetResources( PtWidget_t *widget,
                    int n_args,
                    PtArg_t *args );

The arguments to this function are the identifier for the widget, the number of entries in the argument list, and the argument list itself.

PtGetResources() returns 0 on success, or -1 if an error occurs. A return code of -1 might indicate that you've tried to get the value of a resource that isn't defined for the widget.

Getting one resource

If you're getting the value of one resource, it's easier to use PtGetResource() than PtGetResources(). With PtGetResource(), you don't need to set up the argument list. The arguments to PtGetResource() are:

int PtGetResource( PtWidget_t *widget,
                   long type,
                   long value,
                   long len );

The widget is a pointer to the widget whose resource you're getting. The other arguments are set just as they are for PtSetArg() when getting more than one resource using the pointer method.

Here's an example of getting one resource with PtGetResources() and the pointer method:

unsigned short *width;
PtArg_t arg;

PtSetArg( &arg, Pt_ARG_BEVEL_WIDTH, &width, 0 );
PtGetResources( widget, 1, &arg );

With PtGetResource(), the code is like this:

unsigned short *width;

PtGetResource( widget, Pt_ARG_BEVEL_WIDTH, &width, 0 );

Caution: PtGetResource() returns a pointer directly into the widget's internal memory. Don't attempt to modify the resource directly using this pointer. Such a modification won't have the desired effect and will likely corrupt the widget's behavior. Never free the pointer either — this will certainly result in a memory violation or some other fault.

Using a const pointer will help avoid these problems.

Changes to the widget's state may invalidate the pointer; use it promptly.


Application-level resources

Applications have callback resources that you can set and get, just like widgets, except the resources apply to the application as a whole instead of individual widget instances. These resources apply to applications:


Note: At this time, application-level resources are all callback resources. There may be other resource types in a future version of the Photon library.

To manipulate application-level resources, you can use these functions:

The application-level resource functions are similar to their widget counterparts, except you don't specify a widget.

Setting resources

You can set application-level resources using these functions:

If you are adding a single callback to an application's callback list, PtAppAddCallback() is the easiest method. For example, here is an application exit callback function that prints a message to the standard output when the application exits:

int exit_cb(void *data,
            PtCallbackInfo_t *cbinfo)
{
  printf( "I\'m exiting\n" );
  return( Pt_CONTINUE );
};

To add this callback to the application's Pt_CB_APP_EXIT callback list using PtAppAddCallback(), you would put this in the application's initialization code:

PtAppAddCallback(Pt_CB_APP_EXIT, exit_cb, NULL);

You can also set a single callback using PtAppSetResource(), but instead of passing it a pointer to the callback, you need to pass it the address of a PtAppCallback_t:

PtAppCallback_t exit_callback = {exit_cb, NULL};
PtAppSetResource(Pt_CB_APP_EXIT, &exit_callback, 0);

To use the PtAppSetResources() function, you'll need to create an argument list using PtSetArg(). For example:

PtAppCallback_t exit_callbacks[] = {{exit_cb, NULL}};
PtArg_t args[1];

PtSetArg( &args[0], Pt_CB_APP_EXIT, exit_callbacks,
          sizeof(exit_callbacks)/sizeof(exit_callbacks[0]));
PtAppSetResources( 1, args );

Removing callbacks

You can remove a callback using PtAppRemoveCallback(). It takes the same arguments as PtAppAddCallback(). For example, to remove the callback added in the examples above:

PtAppRemoveCallback( Pt_CB_APP_EXIT, exit_cb, NULL );

Getting callbacks

You can retrieve a pointer to an application callback to examine it. You can use PtAppGetResource() to get a single callback, or PtAppGetResources() to get one or more.

For example, to retrieve a pointer to the application exit callback added in the previous example, you would use:

PtAppCallback_t *my_exit_callback;

PtAppGetResource(Pt_CB_APP_EXIT, &my_exit_callback, 0 );

See the section on Getting Resources for more information.