chiark / gitweb /
Cleanup: relieve frontends of the duty to call
authorSimon Tatham <anakin@pobox.com>
Sat, 22 Oct 2005 17:23:55 +0000 (17:23 +0000)
committerSimon Tatham <anakin@pobox.com>
Sat, 22 Oct 2005 17:23:55 +0000 (17:23 +0000)
midend_rewrite_statusbar() and check the result against the last
string returned. This is now done centrally in drawing.c, and the
front end status bar function need only do what it says on the tin.

While I'm modifying the prototype of drawing_init(), I've also
renamed it drawing_new() for the same reason as random_new() (it
_allocates_ a drawing object, rather than just initialising one
passed in).

[originally from svn r6420]

devel.but
drawing.c
gtk.c
midend.c
ps.c
puzzles.h
windows.c

index 4f589dab2016706eaa09779b25a4f79259d2b34c..4a91349e0fb3653f415d1121a22c0b639e5bee84 100644 (file)
--- a/devel.but
+++ b/devel.but
@@ -1863,6 +1863,11 @@ with the drawing API the property that it may only be called from
 within the back end redraw function, so this is as good a place as
 any to document it.)
 
+The supplied text is filtered through the mid-end for optional
+rewriting before being passed on to the front end; the mid-end will
+prepend the current game time if the game is timed (and may in
+future perform other rewriting if it seems like a good idea).
+
 This function is for drawing only; it must never be called during
 printing.
 
@@ -2068,7 +2073,7 @@ structure called \c{drawing_api}. Each of the functions takes a
 a more useful type. Thus, a drawing \e{object} (\c{drawing *)}
 suitable for passing to the back end redraw or printing functions
 is constructed by passing a \c{drawing_api} and a \cq{void *} to the
-function \cw{drawing_init()} (see \k{drawing-init}).
+function \cw{drawing_new()} (see \k{drawing-new}).
 
 \S{drawingapi-draw-text} \cw{draw_text()}
 
@@ -2167,19 +2172,9 @@ called unless drawing is attempted.
 This function behaves exactly like the back end \cw{status_bar()}
 function; see \k{drawing-status-bar}.
 
-Front ends implementing this function should not use the provided
-text directly; they should call \cw{midend_rewrite_statusbar()}
-(\k{midend-rewrite-statusbar}) to process it first.
-
-In a game which has a timer, this function is likely to be called
-every time the timer goes off, i.e. many times a second. It is
-therefore likely to be common that this function is called with
-precisely the same text as the last time it was called. Front ends
-may well wish to detect this common case and avoid bothering to do
-anything. If they do, however, they \e{must} perform this check on
-the value \e{returned} from \cw{midend_rewrite_statusbar()}, rather
-than the value passed in to it (because the mid-end will frequently
-update the status-bar timer without the back end's intervention).
+Front ends implementing this function need not worry about it being
+called repeatedly with the same text; the middleware code in
+\cw{status_bar()} will take care of this.
 
 Implementations of this API which do not provide drawing services
 may define this function pointer to be \cw{NULL}; it will never be
@@ -2351,15 +2346,23 @@ There are a small number of functions provided in \cw{drawing.c}
 which the front end needs to \e{call}, rather than helping to
 implement. They are described in this section.
 
-\S{drawing-init} \cw{drawing_init()}
+\S{drawing-new} \cw{drawing_new()}
 
-\c drawing *drawing_init(const drawing_api *api, void *handle);
+\c drawing *drawing_new(const drawing_api *api, midend *me,
+\c                      void *handle);
 
 This function creates a drawing object. It is passed a
 \c{drawing_api}, which is a structure containing nothing but
 function pointers; and also a \cq{void *} handle. The handle is
 passed back to each function pointer when it is called.
 
+The \c{midend} parameter is used for rewriting the status bar
+contents: \cw{status_bar()} (see \k{drawing-status-bar}) has to call
+a function in the mid-end which might rewrite the status bar text.
+If the drawing object is to be used only for printing, or if the
+game is known not to call \cw{status_bar()}, this parameter may be
+\cw{NULL}.
+
 \S{drawing-free} \cw{drawing_free()}
 
 \c void drawing_free(drawing *dr);
@@ -2412,7 +2415,7 @@ calling back to functions such as \cw{activate_timer()}
 function \cw{colours()} (\k{backend-colours}).
 
 The parameters \c{drapi} and \c{drhandle} are passed to
-\cw{drawing_init()} (\k{drawing-init}) to construct a drawing object
+\cw{drawing_new()} (\k{drawing-new}) to construct a drawing object
 which will be passed to the back end function \cw{redraw()}
 (\k{backend-redraw}). Hence, all drawing-related function pointers
 defined in \c{drapi} can expect to be called with \c{drhandle} as
@@ -2798,32 +2801,6 @@ The front end can expect its drawing API and/or
 \cw{activate_timer()} to be called from within a call to this
 function.
 
-\H{midend-rewrite-statusbar} \cw{midend_rewrite_statusbar()}
-
-\c char *midend_rewrite_statusbar(midend *me, char *text);
-
-The front end should call this function from within
-\cw{status_bar()} (\k{drawing-status-bar}). It should be passed the
-string that was passed by the back end to \cw{status_bar()}; it will
-return a dynamically allocated string adjusted by the mid-end.
-(Specifically, adjusted to include the timer if the game is a timed
-one.) The returned value should be placed in the actual status bar
-in place of the input value.
-
-(This is a nasty piece of architecture; I apologise for it. It would
-seem a lot more pleasant to have the back end pass its status bar
-text to the mid-end, which in turn would rewrite it and pass it on
-to the front end, so that each front end needed to do nothing
-strange. The main reason why I haven't done this is because it means
-the back end redraw function would need to be passed a mid-end
-pointer \e{as well} as a front end pointer, which seemed like an
-excessive proliferation of opaque handles. The only way to avoid
-that proliferation would be to have all the drawing API functions
-also gatewayed through the mid-end, and that seemed like an
-excessive proliferation of wrapper functions. The current setup
-isn't nice, but it has minimal impact and I'm unconvinced that any
-of the other options are an improvement.)
-
 \H{midend-serialise} \cw{midend_serialise()}
 
 \c void midend_serialise(midend *me,
index 63e27a4f04d0410dd47c7a39d4159f39248b2b77..4204c4cf00196ef0ff7a65d5c13da1d0ffe080e8 100644 (file)
--- a/drawing.c
+++ b/drawing.c
@@ -7,15 +7,25 @@
  * unchanged. However, on the printing side it tracks print colours
  * so the front end API doesn't have to.
  * 
- * FIXME: could we also sort out rewrite_statusbar in here? Also
- * I'd _like_ to do automatic draw_updates, but it's a pain for
- * draw_text in particular - I could invent a front end API which
- * retrieved the text bounds and then do the alignment myself as
- * well, except that that doesn't work for PS. As usual.
+ * FIXME:
+ * 
+ *  - I'd _like_ to do automatic draw_updates, but it's a pain for
+ *    draw_text in particular. I'd have to invent a front end API
+ *    which retrieved the text bounds.
+ *     + that might allow me to do the alignment centrally as well?
+ *       * perhaps not, because PS can't return this information,
+ *         so there would have to be a special case for it.
+ *     + however, that at least doesn't stand in the way of using
+ *      the text bounds for draw_update, because PS doesn't need
+ *      draw_update since it's printing-only. Any _interactive_
+ *      drawing API couldn't get away with refusing to tell you
+ *      what parts of the screen a text draw had covered, because
+ *      you would inevitably need to erase it later on.
  */
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <string.h>
 #include <assert.h>
 #include <math.h>
 
@@ -32,9 +42,13 @@ struct drawing {
     struct print_colour *colours;
     int ncolours, coloursize;
     float scale;
+    /* `me' is only used in status_bar(), so print-oriented instances of
+     * this may set it to NULL. */
+    midend *me;
+    char *laststatus;
 };
 
-drawing *drawing_init(const drawing_api *api, void *handle)
+drawing *drawing_new(const drawing_api *api, midend *me, void *handle)
 {
     drawing *dr = snew(drawing);
     dr->api = api;
@@ -42,11 +56,14 @@ drawing *drawing_init(const drawing_api *api, void *handle)
     dr->colours = NULL;
     dr->ncolours = dr->coloursize = 0;
     dr->scale = 1.0F;
+    dr->me = me;
+    dr->laststatus = NULL;
     return dr;
 }
 
 void drawing_free(drawing *dr)
 {
+    sfree(dr->laststatus);
     sfree(dr->colours);
     sfree(dr);
 }
@@ -110,8 +127,21 @@ void end_draw(drawing *dr)
 
 void status_bar(drawing *dr, char *text)
 {
-    if (dr->api->status_bar)
-       dr->api->status_bar(dr->handle, text);
+    char *rewritten;
+
+    if (!dr->api->status_bar)
+       return;
+
+    assert(dr->me);
+
+    rewritten = midend_rewrite_statusbar(dr->me, text);
+    if (!dr->laststatus || strcmp(rewritten, dr->laststatus)) {
+       dr->api->status_bar(dr->handle, rewritten);
+       sfree(dr->laststatus);
+       dr->laststatus = rewritten;
+    } else {
+       sfree(rewritten);
+    }
 }
 
 blitter *blitter_new(drawing *dr, int w, int h)
diff --git a/gtk.c b/gtk.c
index 528300e6c6edc94238edabed2fbfdc7155075f2b..07f2535eb22f26d9244a31a388f4b0558a5ecb2a 100644 (file)
--- a/gtk.c
+++ b/gtk.c
@@ -116,7 +116,6 @@ struct frontend {
     GtkWidget *cfgbox;
     void *paste_data;
     int paste_data_len;
-    char *laststatus;
     int pw, ph;                        /* pixmap size (w, h are area size) */
     int ox, oy;                        /* offset of pixmap in drawing area */
     char *filesel_name;
@@ -141,19 +140,11 @@ void frontend_default_colour(frontend *fe, float *output)
 void gtk_status_bar(void *handle, char *text)
 {
     frontend *fe = (frontend *)handle;
-    char *rewritten;
 
     assert(fe->statusbar);
 
-    rewritten = midend_rewrite_statusbar(fe->me, text);
-    if (!fe->laststatus || strcmp(rewritten, fe->laststatus)) {
-       gtk_statusbar_pop(GTK_STATUSBAR(fe->statusbar), fe->statusctx);
-       gtk_statusbar_push(GTK_STATUSBAR(fe->statusbar), fe->statusctx, rewritten);
-       sfree(fe->laststatus);
-       fe->laststatus = rewritten;
-    } else {
-       sfree(rewritten);
-    }
+    gtk_statusbar_pop(GTK_STATUSBAR(fe->statusbar), fe->statusctx);
+    gtk_statusbar_push(GTK_STATUSBAR(fe->statusbar), fe->statusctx, text);
 }
 
 void gtk_start_draw(void *handle)
@@ -1670,8 +1661,6 @@ static frontend *new_window(char *arg, char **error)
     fe->fonts = NULL;
     fe->nfonts = fe->fontsize = 0;
 
-    fe->laststatus = NULL;
-
     fe->paste_data = NULL;
     fe->paste_data_len = 0;
 
index ab7048992750e0174f76cc52cd9f442b5535ccbb..47d9b2ca5e7a0fdf11a1a5f4a59325240b9f7092 100644 (file)
--- a/midend.c
+++ b/midend.c
@@ -126,7 +126,7 @@ midend *midend_new(frontend *fe, const game *ourgame,
     me->elapsed = 0.0F;
     me->tilesize = me->winwidth = me->winheight = 0;
     if (drapi)
-       me->drawing = drawing_init(drapi, drhandle);
+       me->drawing = drawing_new(drapi, me, drhandle);
     else
        me->drawing = NULL;
 
diff --git a/ps.c b/ps.c
index 9dc03e802dceb0c5553cdc0fbbed827223d39142..a1f21d6e92877896a0da350e73f0caf18ce7b8ca 100644 (file)
--- a/ps.c
+++ b/ps.c
@@ -334,7 +334,7 @@ psdata *ps_init(FILE *outfile, int colour)
     ps->ytop = 0;
     ps->clipped = FALSE;
     ps->hatchthick = ps->hatchspace = ps->gamewidth = ps->gameheight = 0;
-    ps->drawing = drawing_init(&ps_drawing, ps);
+    ps->drawing = drawing_new(&ps_drawing, NULL, ps);
 
     return ps;
 }
index 2137a55fe412650b967350f777d04f2c384df810..d9cb745d6c2555434e3222d9c8c9dd2fecc494a2 100644 (file)
--- a/puzzles.h
+++ b/puzzles.h
@@ -159,7 +159,7 @@ void get_random_seed(void **randseed, int *randseedsize);
 /*
  * drawing.c
  */
-drawing *drawing_init(const drawing_api *api, void *handle);
+drawing *drawing_new(const drawing_api *api, midend *me, void *handle);
 void drawing_free(drawing *dr);
 void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
                int align, int colour, char *text);
index 6b900231b627046659322bb27799e8275b1873c3..f4cbfe4dce07c4b768729d877a99b9ff9180be76 100644 (file)
--- a/windows.c
+++ b/windows.c
@@ -121,7 +121,6 @@ struct frontend {
     HPEN oldpen;
     char *help_path;
     int help_has_contents;
-    char *laststatus;
     enum { DRAWING, PRINTING, NOTHING } drawstatus;
     DOCINFO di;
     int printcount, printw, printh, printsolns, printcurr, printcolour;
@@ -180,16 +179,8 @@ void get_random_seed(void **randseed, int *randseedsize)
 static void win_status_bar(void *handle, char *text)
 {
     frontend *fe = (frontend *)handle;
-    char *rewritten;
 
-    rewritten = midend_rewrite_statusbar(fe->me, text);
-    if (!fe->laststatus || strcmp(rewritten, fe->laststatus)) {
-       SetWindowText(fe->statusbar, rewritten);
-       sfree(fe->laststatus);
-       fe->laststatus = rewritten;
-    } else {
-       sfree(rewritten);
-    }
+    SetWindowText(fe->statusbar, text);
 }
 
 static blitter *win_blitter_new(void *handle, int w, int h)
@@ -913,7 +904,7 @@ void print(frontend *fe)
     fe->drawstatus = PRINTING;
     fe->hdc = pd.hDC;
 
-    fe->dr = drawing_init(&win_drawing, fe);
+    fe->dr = drawing_new(&win_drawing, NULL, fe);
     document_print(doc, fe->dr);
     drawing_free(fe->dr);
     fe->dr = NULL;
@@ -1122,8 +1113,6 @@ static frontend *new_window(HINSTANCE inst, char *game_id, char **error)
     fe->fonts = NULL;
     fe->nfonts = fe->fontsize = 0;
 
-    fe->laststatus = NULL;
-
     {
        int i, ncolours;
         float *colours;