diff --git a/devel.but b/devel.but index 4f589da..4a91349 100644 --- 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, diff --git a/drawing.c b/drawing.c index 63e27a4..4204c4c 100644 --- 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 #include +#include #include #include @@ -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 528300e..07f2535 100644 --- 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; diff --git a/midend.c b/midend.c index ab70489..47d9b2c 100644 --- 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 9dc03e8..a1f21d6 100644 --- 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; } diff --git a/puzzles.h b/puzzles.h index 2137a55..d9cb745 100644 --- 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); diff --git a/windows.c b/windows.c index 6b90023..f4cbfe4 100644 --- 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;