User's Guide - Preferences

# Request Preferences

The introductory chapter introduced converters and how they can be set up. Converters are a part or a family of preferences in the Library that can be configured by applications and this chapter explains in more detail how to use these features. The family of preferences includes the following members:

- Format converters
- Natural languages
- Content encodings
- Character sets

As mentioned in the previous chapter, when the Library is first initialized, it knows nothing about these preferences. By specifying preferences, the application can tailor the Library to fit the features supported by the application and by the end user. In the following section we will describe how the application can set up the various preferences. All preferences described in this chapter use lists to group the sets together. As we will see later in this chapter, the reason for this is that lists are an easy way of assigning specific preferences to various requests.

## Format Converters

We have already seen an example on how a converter can be set up. Let's take a step back and look at the declaration of the function that adds a converter, `HTConversion_add(...)`:

    extern void HTConversion_add   (HTList *	conversions,
    				CONST char * 	rep_in,
    				CONST char * 	rep_out,
    				HTConverter *	converter,
    				double		quality,
    				double		secs,
    				double		secs_per_byte);

The first argument is a list object. List objects are one of the several container objects in the Library and they are explained in more details in the W3C Library Internals. All we have to know at this point is to create a list object:

    extern HTList *	HTList_new (void);

The two next arguments describes the input format and the output format of the data that is entering and leaving the converter respectively. The syntax for these formats follow the syntax defined by the HTTP Protocol and the MIME specification which has a type string and a subtype string separated by a slash "/"

    	<type> "/" <subtype>

Some of the most common examples are

    	text/plain
    	text/html
    	image/gif
    	audio/basic
    	*/*

In addition to these "official" MIME types, the Library has a small set of internal representations that uniquely exist within the Library. They are used to describe data formats that are not really formats but an intermediate state of the document. The two most used formats of this type are

    	www/present
    	www/unknown

The internal formats are characterized by having the type www which doesn't exist anywhere but in the Library. The first of the two subtypes shown represent the rendered document as presented to the user and the second subtype represents an unknown data format.

The `converter` argument is a pointer to the function that is to be called in order to create a converter object capable of handling the conversion from the input type to the output type. By registering a pointer pointing to the converter, the converter can be set up dynamically. This allows the Library to evaluate the set of registered converters each time a conversion is requested and then chose the best suitable converter on the fly.

The next argument is the quality factor which we will describe in a separate paragraph later in this chapter. The last two arguments are not currently used but are reserved for future use. For now, using a value of 0 is perfectly valid.

Converters are intended to be used when we have our own module to handle the data coming from the remote server. The module can either be one provided by the Library or one made by the application. However, in some cases we would rather hand off the data to an external application for presenting the data. Often external applications are viewers of some sort, for example a postscript viewer or a mpeg viewer. The Library lets us register external applications as presenters very much like converters. This will become obvious if we take a look at how we register presenters:

    extern void HTPresentation_add (HTList *	conversions,
    				CONST char * 	representation,
    				CONST char * 	command,
    				CONST char * 	test_command,
    				double		quality,
    				double		secs,
    				double		secs_per_byte);

As was the case with converters, the first argument is a list which we create in exactly the same way as shown before. Presenters only need a input format as we hand off the data to the external application and never sees it again. A special thing about presenters and converters is that as they are very similar they are also treated very much alike internally in the Library. Therefore a list object can contain both converters and presenters at the same time. This makes often the management easier for the application instead of having to deal with two separate lists.

The next field is reserved to be used in connection with mail cap parsers as the test field of a mail cap file. The Library does not yet directly support Mail Cap files but the registration of presenters is foreseen to be able to work with mail cap files. The Arena browser is an example of an application having its own Mail Cap file parser while using the Library. The description of the test field in RFC 1524 is included below:

The "test" field may be used to test some external condition (e.g., the machine architecture, or the window system in use) to determine whether or not the mail cap line applies. It specifies a program to be run to test some condition. The semantics of execution and of the value returned by the test program are operating system dependent, with UNIX semantics specified in Appendix A. If the test fails, a subsequent mail cap entry should be sought. Multiple test fields are not permitted -- since a test can call a program, it can already be arbitrarily complex.

The last three arguments are exactly identical to the conversion registration so there is no need to describe them any more here. Again, the quality factor will be described in details later in this chapter.

## Natural Languages

The preferred natural language or languages is in almost all situations dependent on the individual user and an application should therefore give the user the opportunity to change the setup. When specifying a natural language preference, the Library will send this preference along with all HTTP requests. The remote server will then (it if supports this feature) look for a version in the language or languages mentioned. If it finds a matching document then it returns this one, otherwise it uses the best alternative. If no language is specified the remote server may whatever version it finds. You can add an element to the list of natural languages by using the following function:

    extern void HTLanguage_add (HTList *		list,
    			    CONST char *	lang,
    			    double		quality);

The list object containing the set of natural languages is similar to the list elements containing the converters and the presenters. However, in contrast to the former two which actually can be one list, the list of natural languages must be a list on its own.

The semantics of the language argument follows closely the Language tag of the HTTP protocol which in terms is based on the RFC 1766. Some example tags are

    	en
    	en-US
    	en-cockney
    	i-cherokee
    	x-pig-latin

where any two-letter primary tag is n ISO 639 language abbreviation and any two-letter initial subtag in an ISO 3166 country code.

## Content Encodings

Some documents are not send in their original data obejct but is encoded in some way. On the Web this is mostly some kind of compression but other encodings for example base 64 can be encountered when talking to NNTP servers etc. Just as for the other preferences, an application can register a supported encoders or decodes as a list. Encoders and decoders are registered in the same way with no differentiation whether it is a encoder or a decoder:

    extern void HTEncoding_add (HTList * 		list,
    			    CONST char *	encoding,
    			    double		quality);

The list argument is the now well-known way of handling these preferences and we will see this many more times throughout the guide. The "encoding" argument is a constant string just like the data format descriptions in the registration of converters and presenters. The values are also inspired strongly by the HTTP Protocol and the MIME specification and some of the most common examples are:

    	base64
    	compress
    	gzip

As the list of natural languages, the list of encoders and decoder must be a separate list.

## Character Sets

As the Web reaches all parts of the Internet there are more and more documents written in languages which contains characters not included in the ISO-8859-1 character set. A consequence of this the set of characters sets is often tightly connected with the natural language. The Library does not directly support other character sets but in case an application is capable of handling alternative sets it can register these as preferred character sets along with a quality factor just as all the other preferences in this section.

    extern void HTCharset_add (HTList *		list,
    			   CONST char *		charset,
    			   double		quality);

Also the charset argument is inspired by the HTTP Protocol and the MIME specification. Some of the most common examples of the charset parameter is:

    	US-ASCII
    	ISO-8859-1
    	UNICODE-1-1

Again, the list of preferred character sets must be a separate list.

## The Quality Factor

Characteristic for all the preferences above is that there is a quality factor associated with each member. The quality factor is a real number between 0 and 1 with 0 meaning "very bad" and 1 means "perfect". By registering a natural language or any or other preference in this group together with a quality factor you can specify "how well the preference is handled" either by the application or by the user. In the case of the user the quality factor of a natural language is how well the user understands the language. In my case, the quality factors for, for example Greek would be close to zero and 1 for Danish (nothing bad said about Greek!).

It is a bit different for converters where it is often the application's ability of handling the data format rather than the user's perception. As an example it is often faster to use a converter than a presenter as it takes time to launch the external application and the Library can not use progressive display mechanisms which is often the case for converters. Therefore, as an example, if we capable of handling an image in png format inline but rely on an external viewer for presenting postscript, we might set up the following list:

    HTConversion_add (converters, "image/gif", "www/present", GifPresenter, 1.0, 0.0, 0.0);

    HTPresentation_add (presenters, "application/postscript", "ghostview %s", NULL, 0.5, 0.0, 0.0);

where the gif converter is registered with a quality factor of 1.0 and the postscript presenter with a quality factor of 0.5.

## Enabling Preferences

All we have done until now is to show how we can register sets of preferences. However, we still need to define where and when to actually let the Library use the preferences. This can be done in two ways: Globally or locally. When assigning a set of preferences, for example the set of natural languages, it can either be assigned to all future requests (globally) or to a specific request (locally). The preferences can also partly be assigned globally and partly locally so that the most common preferences are registered globally and only some preferences specific to a single request is then added by registering the sets locally.

Here we will only show how to enable the preferences globally. Later when we have discussed how to create a request object we will see how to enable the preferences locally and also if they are to be added to the global list or completely override the global list for a particular request.

### Converters and Presenters

    extern void HTFormat_setConversion	(HTList *list);
    extern HTList * HTFormat_conversion	(void);

### Content Encodings

    extern void HTFormat_setEncoding	(HTList *list);
    extern HTList * HTFormat_encoding	(void);

### Content Encodings

    extern void HTFormat_setLanguage	(HTList *list);
    extern HTList * HTFormat_language	(void);

### Character Sets

    extern void HTFormat_setCharset		(HTList *list);
    extern HTList * HTFormat_charset	(void);

## Cleaning up Preferences

As the application is responsible for setting up the sets of preferences, it is also responsible for deleting them once they are not needed anymore, for example when the application i s closing down, or the user has changed them. The Library provides two mechanisms for cleaning up old lists: It can either be done by invoking separate methods on each set of preferences, or it can be done in a batch of all globally registered preferences or all locally registered preferences relative to a single request. In this context, a batch is the total set of registered converters, encoder, charsets, and languages. Here we will only show how to cleanup preferences set-wise and as a globally batch of preferences. We leave the local cleanup until we have described the request object later in this guide.

Common for the cleanup methods is that when they have been called you can nor more use the lists as they are not pointing to valid places in the memory. The first mechanism for cleaning up lists is by calling the cleanup method of each preference as indicated below:

### Converters

    extern void HTConversion_deleteAll	(HTList * list);

### Presenters

    extern void HTPresentation_deleteAll	(HTList * list);

### Content Encodings

    extern void HTEncoding_deleteAll	(HTList * list);

### Content Languages

    extern void HTLanguage_deleteAll	(HTList * list);

### Character Sets

    extern void HTCharset_deleteAll		(HTList * list);

The second mechanism which at once cleans up all globally registered preferences can often be used in order to simplify the management done by the application. Note, however, that all globally lists become inaccessible for future reference. In you want to define new sets of preferences then you need to start all over again and create a new list object.

    extern void HTFormat_deleteAll		(void);

## Getting Help on Initialization Converters and Presenters

The Library has a special module called HTInit which helps the application doing the initialization of all the converters and other preferences supported internally by the Library. This module is not called directly from the Library and must explicitly be invoked by the application. HTInit is a part of the WWWApp.h include file described in the previous section, so if you include this in your application then you have direct access to the following functions: The following function initializes all the converters supported natively by modules in the Library distribution file:

    extern void HTConverterInit	(HTList * conversions);

There is a similar function for registering a common set of presenters that can be found on many (especially Unix) platforms:

    extern void HTPresenterInit	(HTList * conversions);

In order to show the similarity between how converters and presenters are handled in the Library, there is also a single function that does the work of the two previous functions at once:

    extern void HTFormatInit	(HTList * conversions);

## Summary

We have now seen how to enable multiple sets of preferences using a very similar naming scheme and registration process. As mentioned in the beginning, lists are easy to handle when the preferences are likely to be changed often as the application is executed. In the next section, we will take a look at a slightly different registration mechanism which is more suited for topics that only rarely are registered multiple times during the execution of an application.