
A Handle widget for undocking and reattaching widgets.

A new format handling scheme

The current scheme uses a fixed number of bits for each property
of a format. The result is something which is simple to implement
and use, but difficult to extend.

I want to replace this with something like this:

 - Backwards compatible
 - No fixed allocation of bits for properties
 - Easy to use
 - Easy to extend, even dynamically
 - Device independent

The final point, device independence, is so that different versions of the
programs, using different graphics libraries or even running on different
platforms, will be able to use the same high-level code.

Here is a suggestion where the old long integer is used as an integer into
an array of already allocated formats. This array is preloaded with all
the formats in use today (Courier, Times et al in all colour
combinations and so on). That takes care of the backwards compatibility.

We need a new data structure, containing all the properties broken up
into bold, italic, fg, bg, font and so on. To operate on this, we also
need two functions, one which maps from the filled in structure to an
index and one which maps from index to filled structure.

The first function takes an additional argument, a bit pattern telling
which properties are interesting. That way, already loaded formats can
be reused if they differ only in parts that are not interesting.

So, how do we go about registering fonts and colours? I propose the
following two functions.

(register-x-font name x-name italic)
	name is the name as used by the user, e.g. Times
	x-name is the name as used by X
	italic is i or o, depending on if it is called italic or oblique

(register-ps-font name ps-name italic)
	name is the name as used by the user
	ps-name is the name as used by Postscript
	italic is Oblique or Italic

This can be extended with more functions if more font name spaces are needed.

One effect is that there can be as mismatch between X and PS, so that a
font is available for X cannot be printed. This is clearly not
acceptable, so only those fonts that are available in both name spaces
will be offered to the user.


Colours are handled in a way similar to the fonts, but here there is
less need to adapt to different devices. I can simply say that this
is the official way to register a colour:

(register-color name red green blue)
	name is the name used by the user
	red, green and blue are integers in the range 0-65535

How this is mapped into real world, device-dependent colours is left
as an exercise for the programmer writing the device-dependent code.


The font size is a little different. I want the user to be able to use
any font size, including sizes like 12.3. There is no way to enumerate
all such sizes and it makes no sense to register them. Instead each new
size must be registered on the fly the first time it is used, or simply
used directly in the format structure without any registering at all.


Siag has additional properties that apply to a whole cell, not
individual characters. These include borders, horizontal and
vertical adjustment, display style. PW also has additional properties;
however, these are not stored lumped together with the character
formats. The additional properties for PW are horizontal adjustment
and display style.

It does no harm to have fields in the format structure for the Siag
properties. It makes porting easier and PW can simply leave them empty.


typedef struct {
	int font;	/* index into font table */
	int fg;		/* index into color table */
	int bg;		/* index into color table */
	long siag;	/* siag additional properties */
} siag_format;

typedef struct {
	char *name;	/* color name */
	unsigned short red, green, blue;
} color_table;

typedef struct {
	char *name;
	char *

When a user selects a font, it must be encoded into a form that can
be handed to X or PS. This is done through the function encode_font.

void encode_font(int attr, char *name, double size, int bold, int italic,
		char *x_name, char *ps_name)

Example:

char *name = "Helvetica";
double size = 12.0;
char x_name[1000];
char ps_name[1000];
encode_font(name, 12, FALSE, TRUE, x_name, ps_name);
if (x_name == NULL || ps_name == NULL) {
	fprintf(stderr, "Couldn't encode %s\n", name);
} else {
	printf("X name: %s\n", x_name);
	printf("PS name: %s\n", ps_name);
}

This should print:

X name: -*-courier-medium-i-*--*-12-75-75-*-*-*-*
PS name: Helvetica-Oblique

But this, although fairly nifty, isn't what I want to do. I would
rather have something that does this:

int index = lookup_font(name, 12, FALSE, TRUE);
if (index >= 0) {
	printf("X name: %s\n", font_table[index].x_name);
	printf("PS name: %s\n", font_table[index].ps_name);
}

and for colours:

int index = lookup_color("white");
if (index >= 0) {
	printf("RGB=(%u,%u,%u)\n",
		(unsigned)color_table[index].red,
		(unsigned)color_table[index].green,
		(unsigned)color_table[index].blue);
}

and finally, for formats:

int lookup_format(int font, int fgcolor, int bgcolor, int uline, int siagfmt);

int index = lookup_format(lookup_font("Helvetica", 12, FALSE, TRUE),
			lookup_color("black"), lookup_color("white"),
			FALSE, 0);

printf("X font: %s\n", font_table[format_table[index].font].x_name);

The lookup_* functions can be as simple as a linear search. I don't think
that anybody intends to use more than a few hundred fonts, and putting
the most frequently used ones at the top will reduce the search to perhaps
a dozen comparisons on average.


Compatibility

There are three issues with compatibility:
 - We want to be able to open old documents
 - We want old versions of Siag to be able to open new documents
 - We want to make minimal changes to the source code

Old documents will likely not be much of a problem. We will have to
extend the file format to include format descriptions. If no such
description is present, the document is an old version. Such documents
can be handled by translating old style format codes to the new style,
looking up fonts, colours et al as necessary in the new tables. The
procedure can be simplified by functions that do the translating.

New documents on the other hand are impossible to load in old programs
that don't have the necessary fonts or colours. To avoid forcing all
users to upgrade immediately, it would be nice if the documents could
be opened in a standard format, let's say left adjusted, Helvetica,
12 points, normal style. This would however require completely new bits
to be used for the new formats, and there are only 8 left. One of those
is the sign bit, and I don't trust that I have used unsigned long everywhere.

There is no good solution to this problem. I can make an option to save
using old-style formats, losing some formatting, but that's about it.
At least it will allow some communication between old and new versions.

Old versions *will* be able to open the new files, but the formats
may be unusable.

One advantage of not making the new format entirely compatible is that
it can be much simpler.


The changes to the source code will most likely be pretty extensive,
no matter what I do about it. There is much bitshifting and masking
going on, and none of that will work at all. The best thing is to make
a clean break with the past and remove old references to the old stuff.


