/* * Helpers for implementing a rapid-update counter display in Motif. * Copyright © 2022 Nick Bowler * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* * 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). * * This is intended to avoid two specific practical problems with these widgets: * * (1) Any update to the text involves dynamic allocation of XmStrings * (2) Updating the text causes the entire label to be redrawn. * * Point #2 can lead to annoying flicker on static portions of the label when * updates are occurring continuously. * * 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." * * 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 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: * * - 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. * * - 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. * * The xcounter_redraw function can then be used to redraw only the portions of * the string that have changed since the last redraw. */ #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. * * Note that the provided template string will be modified by this function, * but restored to its original value before returning. */ 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. */ void xcounter_update(Widget w, 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); /* * Resize and expose callbacks that can be registered on a drawing area widget. */ 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) { 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); } #endif