Search the FAQ Archives

3 - A - B - C - D - E - F - G - H - I - J - K - L - M
N - O - P - Q - R - S - T - U - V - W - X - Y - Z
faqs.org - Internet FAQ Archives

comp.windows.x.intrinsics Frequently Asked Questions (FAQ)
Section - 17. How do I write a resource converter?

( Single Page )
[ Usenet FAQs | Web FAQs | Documents | RFC Index | Forum ]


Top Document: comp.windows.x.intrinsics Frequently Asked Questions (FAQ)
Previous Document: 16. How do I pass a float value to XtSetValues?
Next Document: 18. How do I open multiple displays?
See reader questions & answers on this topic! - Help others by sharing your knowledge
----------------------------------------------------------------------

Courtesy of Rich Thomson (rthomson@dsd.es.com):

The following discussion of resource converters assumes R4 (or R5)
Intrinsics.  Resource converters changed between R3 and R4 to allow
for destructors and caching of converted values.

There are several main types of resource converters:

    string to data type
    data type to string
    data type to data type

i) string to data type
    Usually a string to data type converter has a fixed set of strings
    that will be converted to data type values.  This is most often
    used to map enumerated names to enumerated values:

	Name		Value
	"True"		1
	"False"		0

    In this case, the string to data type converter needs to compare
    the resource value to the list of fixed strings.  This is most
    readily accomplished by the use of the "quark" mechanism of the
    resource manager.  The resource value is turned into a quark,
    which is a unique representation of the string that fits into a
    single word.  Then the resource quark is compared against the
    quarks for the fixed strings representing the enumerated values.

    If there are many enumerated strings in the converter (or many
    converters, each with a small number of enumeration strings), then
    a global initialization routine might be used to turn all the
    resource strings into quarks.  That way, the first time one of
    these converters is used, the strings will be turned into quarks
    and held in static variables for use in the next invocation of one
    of the converters.

ii) data type to string
    This type of converter is slightly easier than the string to data
    type converters since the use of quarks isn't necessary.  Instead,
    the data type value is simply converted to a string value,
    probably by the use of sprintf.

    Data type to string converters are useful for applications that
    wish to convert an internal data type value into a string so that
    they can write out a valid resource specification to a file.  This
    mechanism can be used to provide a "snapshot" of application state
    into a file.  This snapshot can be used to restore the program to
    a known state via the usual X resource database mechanisms.

    If you are taking the trouble to write a string to data type
    converter, it isn't much extra effort to write the data type to
    string converter.  Writing both at the same time helps to ensure
    that they are consistent.

iii) data type to data type
    This type of converter is used to convert an existing data type
    value to another data type.  For instance, an X pixel value can be
    converted to an RGB data type that contains separate fields for
    red, green and blue.


The type signature for a resource converter is as follows:

typedef Boolean (*XtTypeConverter)(Display *, XrmValuePtr, Cardinal *,
	XrmValuePtr, XrmValuePtr, XtPointer *);
    Display *dpy;
    XrmValuePtr args;
    Cardinal *num_args;
    XrmValuePtr fromVal;
    XrmValuePtr toVal;
    XtPointer *converter_data;

When the converter is invoked, the "fromVal" argument points to the source
X resource manager value and the "toVal" argument points to the
destination X resource manager value.  The "converter_data" argument
is an opaque pointer to some converter-specific data that is specified
when the converter is registered.  The "args" and "num_args" arguments
allow extra information to be passed to the converter when it is
invoked.  For instance, the Pixel to RGB structure converter discussed
above would need colormap and visual arguments in which to lookup the
Pixel to obtain the RGB values corresponding to that pixel.

Care must be taken with the "toVal" argument.  An XrmValue has the
following type definition and specifies a size and location for a
converted value:

typedef struct {
    unsigned int    size;
    caddr_t         addr;
} XrmValue, *XrmValuePtr;

When the converter is invoked, the address may point to a location of
the given size for the converted value or the location can be NULL.
In the former case, the converter should ensure that the size of the
destination area is large enough to handle the converted value.  If
the destination area is not large enough, then the converter should
set the size to the amount of space needed and return False.  The
caller can then ensure that enough space is allocated and reinvoke the
converter.  If the size is large enough, then the converter can simply
copy the converted value into the space given and return True.

If the location is NULL, then the converter can assign the location to
the address of a static variable containing the converted value and
return True.

When writing a group of converters, this code is often repeated and it
becomes convenient to define a macro:

    #define DONE(var, type) \
      if (toVal->addr) \
	{ \
	  if (toVal->size < sizeof(type)) \
	    { \
	      toVal->size = sizeof(type); \
	      return False; \
	    } \
	  else \
	    *((type *) toVal->addr) = var; \
	} \
      else \
	toVal->addr = (caddr_t) &var; \
      toVal->size = sizeof(type); \
      return True;

    #define DONESTR(str) \
      if (toVal->addr && toVal->size < sizeof(String)) \
	{ \
	  toVal->size = sizeof(String); \
	  return False; \
	} \
      else \
	toVal->addr = (caddr_t) str; \
      toVal->size = sizeof(String); \
      return True;

Inside the converter, it is a good idea to perform a little safety
checking on the "num_args" and "args" arguments to ensure that your
converter is being called properly.

Once you have written your converter, you need to register it with the
Intrinsics.  The Intrinsics invokes resource converters when creating
widgets and fetching their resource values from the resource database.

To register a converter with a single application context, use
XtAppSetTypeConverter:

void XtAppSetTypeConverter(context, from, to, converter, args, num_args,
	cache, destructor)
    XtAppContext context;
    String from;
    String to;
    XtTypeConverter converter;
    XtConvertArgList args;
    Cardinal num_args;
    XtCacheType cache;
    XtDestructor destructor;

To register a converter with all application contexts, use
XtSetTypeConverter:

void XtSetTypeConverter(from, to, converter, args, num_args,
	cache, destructor)
    String from;
    String to;
    XtTypeConverter converter;
    XtConvertArgList args;
    Cardinal num_args;
    XtCacheType cache;
    XtDestructor destructor;

In the R3 Intrinsics, there were the routines XtAppAddConverter and
XtAddConverter; these have been superseded by XtAppSetTypeConverter
and XtSetTypeConverter.  Whenever possible, the newer routines should be
used.

When a converter is registered with the Intrinsics, a "cache" argument
specifies how converted resource values are to be cached:

    XtCacheNone		Don't cache any converted values
    XtCacheAll		Cache all converted values
    XtCacheByDisplay	Cache converted values on a per display basis

Caching converted values that require a round-trip to the server is a
good idea (for instance string to Pixel conversions).

The "destructor" argument is a routine that is invoked then the
resource is destroyed, either because its cached reference count has
been decremented to zero or because the widget owning the value is
being destroyed.  XtDestructor has the following type definition:

typedef void (*XtDestructor)(XtAppContext, XrmValuePtr, XtPointer,
	XrmValuePtr, Cardinal *);
    XtAppContext context;
    XrmValuePtr to;
    XtPointer converter_data;
    XrmValuePtr args;
    Cardinal *num_args;

The destructor is invoked to free any auxiliary storage associated
with the "to" argument, but does not actually free the storage pointed
to by the "to" argument itself (to->addr).  The destructor is passed
the extra arguments that were passed to the converter when the
conversion was performed (for instance, colormap and visual arguments
for the string to Pixel converter since the destructor would need to
free the allocated Pixel from the colormap) as well as the private
data passed in when the converter was registered.

Sample converter code can be found in the following files in the MIT
R5 distribution:

    mit/lib/Xt/Converters.c
    contrib/lib/PEXt/Converters.c
    contrib/lib/PEXt/Converters.h

User Contributions:

Comment about this article, ask questions, or add new information about this topic:




Top Document: comp.windows.x.intrinsics Frequently Asked Questions (FAQ)
Previous Document: 16. How do I pass a float value to XtSetValues?
Next Document: 18. How do I open multiple displays?

Single Page

[ Usenet FAQs | Web FAQs | Documents | RFC Index ]

Send corrections/additions to the FAQ Maintainer:
ware@cis.ohio-state.edu





Last Update March 27 2014 @ 02:11 PM