Version 2 of TextField widget design

Updated 2004-05-30 09:08:59

GPS: I've had a design floating in my brain for over a year for a text-like widget that is simple and robust. Parts of the design are incomplete and I would appreciate help.

Here are some ideas relating to that:

Each line will consist of a structure like this:

 typedef struct TextFieldLine_s {
  struct TextFieldLine_s *next;
  struct TextFieldLine_s *previous;
  unsigned int width;
  unsigned int height;
  unsigned char *b;
 } TextFieldLine;

Note: that next and previous implement our double-linked list. This should reduce the cost of inserting and deleting lines or contents of lines.

Now as for the data stored in *b we will define some markers so we would have something like:

MARKER0x01MARKERText

In the case above 0x01 is the id of our text context. 0x01 could be looked up as an offset into an array that stores a structure with the GC and various other information needed to draw the text or measure it. I like to call this structure a Text Context or TC.

A TC would be something like this:

 typedef struct {
  int width;
  int height;
  GC gc;
  /*other bits most likely needed*/
 } TC;

In the current design 0x00/NUL would be the marker.

For proper scrollbar operation we will need to measure each line for its width and height. We also need to take into account the entire width and height, so that the ratio is proper. As lines wrap we will need to calculate the amount of height that is added from the wrap. This presents a problem, because we can't treat each line as the same height and have it always appear proper. To further complicate the matter some TCs will only be images.

The text will be rendered and measured using a state machine. There would be two basic states for measuring. If the MARKER char is received then we enter a state of TC and use the next character as an offset into our lookup table for the TC. Once we have that structure from the offset we set it as our current TC (variable cur_tc). We then proceed until the end MARKER and we can then begin to process our Text. Once a \0 is found at the end of our cur_line->b array or another MARKER we would invoke a measure of the text via a Tk function, such as Tk_TextWidth(). The height will not be dynamic like the width, so we can rely on the cur_tc->height for our final calculations of the total height of the line (note wrapping introduces some extra complexity for this to work properly).

How can we efficiently handle the change of a TC that results in a tc->width or tc->height change without using our state machine to remeasure the entire contents? It seems that there is little to no way of handling this without remeasuring the entire contents or using a vast amount of pointers (perhaps a linked list with pointers to TextFieldLines in a TC). Do you know of a way?


Category Widget