]> git.draconx.ca Git - rrace.git/blob - src/xcounter.h
6109b0594a9a9636db2510fb3c53f0f0f734f7a1
[rrace.git] / src / xcounter.h
1 /*
2  * Helpers for implementing a rapid-update counter display in Motif.
3  * Copyright © 2022 Nick Bowler
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
17  */
18
19 /*
20  * A set of functions to implement a simple counter display with better support
21  * for rapid updates than regular XmLabel (and other Motif text display widgets).
22  *
23  * This is intended to avoid two specific practical problems with these widgets:
24  *
25  *  (1) Any update to the text involves dynamic allocation of XmStrings
26  *  (2) Updating the text causes the entire label to be redrawn.
27  *
28  * Point #2 can lead to annoying flicker on static portions of the label when
29  * updates are occurring continuously.
30  *
31  * These functions are intended for displaying strings that consist of non-
32  * changing static text with digits interspersed.  Specifically, strings such
33  * as "The time is 12:30:57."
34  *
35  * Passing this string as the template argument to xcounter_init will pre-
36  * allocate an XmString values for each of the four maximal nondigit
37  * substrings.  These nondigit parts cannot be changed.
38  *
39  * On a subsequent call to xcounter_update, a different string may be passed.
40  * The digits in this string are used to construct a sequence of XmString
41  * values that includes the precomputed static portions interspersed with
42  * digits.  This new string is expected to be in the same format as the
43  * template although there are two possible exceptions:
44  *
45  *   - The nondigit substrings do not need to match the template; they are
46  *     used only to separate different groups of digits and otherwise have
47  *     no effect on the output.
48  *
49  *   - If the new string may be a prefix of the template, only that portion
50  *     will be output.  However it is still not possible to alter the static
51  *     portions: they are either present in their entirety or omitted.
52  *
53  * The xcounter_redraw function can then be used to redraw only the portions of
54  * the string that have changed since the last redraw.
55  */
56
57 #ifndef XCOUNTER_H_
58 #define XCOUNTER_H_
59
60 /*
61  * Create xcounter based on template, which should be representative of
62  * the number of digits expected to preallocate a typical number of digits.
63  *
64  * Note that the provided template string will be modified by this function,
65  * but restored to its original value before returning.
66  */
67 struct xcounter *xcounter_init(Widget w, char *template);
68
69 /*
70  * Update xcounter segments according to str.
71  *
72  * The nondigit sequences are assumed to match those from the original
73  * template.
74  */
75 void xcounter_update(Widget w, struct xcounter *xc, const char *str);
76
77 /*
78  * Redraw the counter in response to an expose event.
79  */
80 void xcounter_expose(Widget w, struct xcounter *xc, XExposeEvent *e);
81
82 /*
83  * Resize and expose callbacks that can be registered on a drawing area widget.
84  */
85 void xcounter_resize_cb(Widget w, void *data, void *cb_data);
86 void xcounter_expose_cb(Widget w, void *data, void *cb_data);
87
88 static inline void xcounter_simple_setup(Widget w, char *template)
89 {
90         struct xcounter *xc = xcounter_init(w, template);
91
92         XtVaSetValues(w, XmNuserData, (void *)xc, (char *)NULL);
93         XtAddCallback(w, XmNresizeCallback, xcounter_resize_cb, xc);
94         XtAddCallback(w, XmNexposeCallback, xcounter_expose_cb, xc);
95 }
96
97 static inline void xcounter_simple_update(Widget w, const char *str)
98 {
99         void *xc;
100
101         XtVaGetValues(w, XmNuserData, &xc, (char *)NULL);
102         xcounter_update(w, xc, str);
103 }
104
105 #endif