X-Git-Url: http://git.draconx.ca/gitweb/rrace.git/blobdiff_plain/5a4a23e5e8032dfa1f7b73facb32f0c9ab200765..bbe659b000e2c281340953c5fc96bd7ac3b94eaa:/src/xcounter.h?ds=sidebyside diff --git a/src/xcounter.h b/src/xcounter.h index 6109b05..e08b8a8 100644 --- a/src/xcounter.h +++ b/src/xcounter.h @@ -16,90 +16,104 @@ * along with this program. If not, see . */ +#ifndef XCOUNTER_H_ +#define XCOUNTER_H_ + /* - * A set of functions to implement a simple counter display with better support - * for rapid updates than regular XmLabel (and other Motif text display widgets). + * A set of functions to implement a simple decimal counter display supporting + * rapid updates. This is intended to avoid two specific practical problems + * with the Motif text widgets: * - * This is intended to avoid two specific practical problems with these widgets: + * (1) Updating the text involves expensive(?) XmString operations, and + * (2) Updating the text causes the label to be cleared and redrawn. * - * (1) Any update to the text involves dynamic allocation of XmStrings - * (2) Updating the text causes the entire label to be redrawn. + * Point #2 in particular results in very annoying flicker. * - * Point #2 can lead to annoying flicker on static portions of the label when - * updates are occurring continuously. + * These functions are intended for dealing with strings that consist of + * "static" text interspersed with digits. For example, a string such as: * - * These functions are intended for displaying strings that consist of non- - * changing static text with digits interspersed. Specifically, strings such - * as "The time is 12:30:57." + * "The time is 12:30:57." * - * Passing this string as the template argument to xcounter_init will pre- - * allocate an XmString values for each of the four maximal nondigit - * substrings. These nondigit parts cannot be changed. + * On a call to xcounter_init, a string like this is provided as the template. + * The "static" elements are all the maximal nondigit substrings, which in this + * instance are "The time is ", ":" (twice) and ".". These static elements + * are pre-rendered to an X pixmap along with all possible decimal digits. * - * On a subsequent call to xcounter_update, a different string may be passed. - * The digits in this string are used to construct a sequence of XmString - * values that includes the precomputed static portions interspersed with - * digits. This new string is expected to be in the same format as the - * template although there are two possible exceptions: + * A subsequent call to xcounter_update will change the displayed string by + * combining the pre-rendered images in various ways. This takes a strings in + * the same format the original template to modify the digit sequences. * - * - The nondigit substrings do not need to match the template; they are - * used only to separate different groups of digits and otherwise have - * no effect on the output. + * This solves the practical problems by significantly simplifying the actual + * X drawing process (just a single operation to update any particular pixel). + * This avoids the flicker inherent to a clear+redraw, and a simple change + * tracking scheme is employed to avoid redundant drawing for a smoother + * update. * - * - If the new string may be a prefix of the template, only that portion - * will be output. However it is still not possible to alter the static - * portions: they are either present in their entirety or omitted. + * To simplify the implementation, some arbitrary limits are baked in: * - * The xcounter_redraw function can then be used to redraw only the portions of - * the string that have changed since the last redraw. + * - maximum number of static elements in a template: 10 + * - maximum number of digits plus static elements in an update: 23 + * + * Which should be more than enough to handle the RRace displays. */ -#ifndef XCOUNTER_H_ -#define XCOUNTER_H_ - /* - * Create xcounter based on template, which should be representative of - * the number of digits expected to preallocate a typical number of digits. + * Create xcounter based on template. * - * Note that the provided template string will be modified by this function, - * but restored to its original value before returning. + * The provided template must be writeable as it is internally modified by + * this function. However, it is restored to its original value upon return. */ struct xcounter *xcounter_init(Widget w, char *template); /* * Update xcounter segments according to str. * - * The nondigit sequences are assumed to match those from the original - * template. + * Generally, the string should be in the same format as the original + * template, with only the digits changing between calls. However, there + * are two allowed exceptions: + * + * - It does not matter what exact text is placed in the static portions + * between digits, provided they are nonempty. These are used only to + * separate groups of digits. The pre-rendered text from the original + * template is always used. + * + * - The updated string need not include all the elements of the original + * template. Omitted elements from the update string are not drawn. */ -void xcounter_update(Widget w, struct xcounter *xc, const char *str); +void xcounter_update(struct xcounter *xc, const char *str); /* * Redraw the counter in response to an expose event. */ -void xcounter_expose(Widget w, struct xcounter *xc, XExposeEvent *e); +void xcounter_expose(struct xcounter *xc, XExposeEvent *e); /* - * Resize and expose callbacks that can be registered on a drawing area widget. + * Resize and expose callbacks that can be registered on an XmDrawingArea. */ void xcounter_resize_cb(Widget w, void *data, void *cb_data); void xcounter_expose_cb(Widget w, void *data, void *cb_data); -static inline void xcounter_simple_setup(Widget w, char *template) +/* + * Clear the margins of the counter after resizing the widget. + * + * Since the pre-rendered text never changes, this is all that is needed: + * existing portions of the window do not need to be redrawn (except when + * shrinking the margins over previously-drawn text), and newly-revealed + * areas will get expose events to trigger redraw. + */ +static inline void xcounter_resize(struct xcounter *xc) +{ + xcounter_resize_cb(0, xc, 0); +} + +static inline struct xcounter *xcounter_simple_init(Widget w, char *template) { struct xcounter *xc = xcounter_init(w, template); - XtVaSetValues(w, XmNuserData, (void *)xc, (char *)NULL); XtAddCallback(w, XmNresizeCallback, xcounter_resize_cb, xc); XtAddCallback(w, XmNexposeCallback, xcounter_expose_cb, xc); -} - -static inline void xcounter_simple_update(Widget w, const char *str) -{ - void *xc; - XtVaGetValues(w, XmNuserData, &xc, (char *)NULL); - xcounter_update(w, xc, str); + return xc; } #endif