1680
static gboolean not_size_allocated_yet(GtkWidget *w)
1683
* This function tests whether a widget has not yet taken up space
1684
* on the screen which it will occupy in future. (Therefore, it
1685
* returns true only if the widget does exist but does not have a
1686
* size allocation. A null widget is already taking up all the
1687
* space it ever will.)
1690
return FALSE; /* nonexistent widgets aren't a problem */
1692
#if GTK_CHECK_VERSION(2,18,0) /* skip if no gtk_widget_get_allocation */
1695
gtk_widget_get_allocation(w, &a);
1696
if (a.height == 0 || a.width == 0)
1697
return TRUE; /* widget exists but has no size yet */
1704
static void try_shrink_drawing_area(frontend *fe)
1706
if (fe->drawing_area_shrink_pending &&
1707
!not_size_allocated_yet(fe->menubar) &&
1708
!not_size_allocated_yet(fe->statusbar)) {
1710
* In order to permit the user to resize the window smaller as
1711
* well as bigger, we call this function after the window size
1712
* has ended up where we want it. This shouldn't shrink the
1713
* window immediately; it just arranges that the next time the
1714
* user tries to shrink it, they can.
1716
* However, at puzzle creation time, we defer the first of
1717
* these operations until after the menu bar and status bar
1718
* are actually visible. On Ubuntu 12.04 I've found that these
1719
* can take a while to be displayed, and that it's a mistake
1720
* to reduce the drawing area's size allocation before they've
1721
* turned up or else the drawing area makes room for them by
1722
* shrinking to less than the size we intended.
1724
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), 1, 1);
1725
fe->drawing_area_shrink_pending = FALSE;
1729
static gint configure_window(GtkWidget *widget,
1730
GdkEventConfigure *event, gpointer data)
1732
frontend *fe = (frontend *)data;
1734
* When the main puzzle window changes size, it might be because
1735
* the menu bar or status bar has turned up after starting off
1736
* absent, in which case we should have another go at enacting a
1737
* pending shrink of the drawing area.
1739
try_shrink_drawing_area(fe);
1677
1743
static void resize_fe(frontend *fe)
1681
1747
get_size(fe, &x, &y);
1750
fe->drawing_area_shrink_pending = FALSE;
1684
1751
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
1686
1753
GtkRequisition req;
1687
1754
gtk_widget_size_request(GTK_WIDGET(fe->window), &req);
1688
1755
gtk_window_resize(GTK_WINDOW(fe->window), req.width, req.height);
1691
* Now that we've established the preferred size of the window,
1692
* reduce the drawing area's size request so the user can shrink
1695
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), 1, 1);
1757
fe->drawing_area_shrink_pending = TRUE;
1758
try_shrink_drawing_area(fe);
1698
1761
static void menu_preset_event(GtkMenuItem *menuitem, gpointer data)
2219
2282
gtk_box_pack_start(vbox, GTK_WIDGET(hbox), FALSE, FALSE, 0);
2220
2283
gtk_widget_show(GTK_WIDGET(hbox));
2222
menubar = gtk_menu_bar_new();
2223
gtk_box_pack_start(hbox, menubar, TRUE, TRUE, 0);
2224
gtk_widget_show(menubar);
2285
fe->menubar = gtk_menu_bar_new();
2286
gtk_box_pack_start(hbox, fe->menubar, TRUE, TRUE, 0);
2287
gtk_widget_show(fe->menubar);
2226
2289
menuitem = gtk_menu_item_new_with_mnemonic("_Game");
2227
gtk_container_add(GTK_CONTAINER(menubar), menuitem);
2290
gtk_container_add(GTK_CONTAINER(fe->menubar), menuitem);
2228
2291
gtk_widget_show(menuitem);
2230
2293
menu = gtk_menu_new();
2265
2328
menuitem = gtk_menu_item_new_with_mnemonic("_Type");
2266
gtk_container_add(GTK_CONTAINER(menubar), menuitem);
2329
gtk_container_add(GTK_CONTAINER(fe->menubar), menuitem);
2267
2330
gtk_widget_show(menuitem);
2269
2332
submenu = gtk_menu_new();
2342
2405
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Exit", 'q');
2344
2407
menuitem = gtk_menu_item_new_with_mnemonic("_Help");
2345
gtk_container_add(GTK_CONTAINER(menubar), menuitem);
2408
gtk_container_add(GTK_CONTAINER(fe->menubar), menuitem);
2346
2409
gtk_widget_show(menuitem);
2348
2411
menu = gtk_menu_new();
2474
2538
GTK_SIGNAL_FUNC(map_window), fe);
2475
2539
gtk_signal_connect(GTK_OBJECT(fe->area), "configure_event",
2476
2540
GTK_SIGNAL_FUNC(configure_area), fe);
2541
gtk_signal_connect(GTK_OBJECT(fe->window), "configure_event",
2542
GTK_SIGNAL_FUNC(configure_window), fe);
2478
2544
gtk_widget_add_events(GTK_WIDGET(fe->area),
2479
2545
GDK_BUTTON_PRESS_MASK |
2499
2565
gtk_widget_show(fe->area);
2500
2566
gtk_widget_show(fe->window);
2503
* Now that we've established the preferred size of the window,
2504
* reduce the drawing area's size request so the user can shrink
2507
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), 1, 1);
2568
fe->drawing_area_shrink_pending = TRUE;
2569
try_shrink_drawing_area(fe);
2508
2570
set_window_background(fe, 0);
2537
2599
int ngenerate = 0, print = FALSE, px = 1, py = 1;
2600
int time_generation = FALSE, test_solve = FALSE, list_presets = FALSE;
2538
2601
int soln = FALSE, colour = FALSE;
2539
2602
float scale = 1.0F;
2540
2603
float redo_proportion = 0.0F;
2675
} else if (doing_opts && !strcmp(p, "--time-generation")) {
2676
time_generation = TRUE;
2677
} else if (doing_opts && !strcmp(p, "--test-solve")) {
2679
} else if (doing_opts && !strcmp(p, "--list-presets")) {
2680
list_presets = TRUE;
2610
2681
} else if (doing_opts && !strcmp(p, "--save")) {
2611
2682
if (--ac > 0) {
2612
2683
savefile = *++av;
2761
2827
document *doc = NULL;
2830
* If we're in this branch, we should display any pending
2831
* error message from the command line, since GTK isn't going
2832
* to take another crack at making sense of it.
2835
fputs(errbuf, stderr);
2765
2841
me = midend_new(NULL, &thegame, NULL, NULL);
2897
if (time_generation)
2898
getrusage(RUSAGE_SELF, &before);
2900
midend_new_game(me);
2902
seed = midend_get_random_seed(me);
2904
if (time_generation) {
2907
getrusage(RUSAGE_SELF, &after);
2909
elapsed = (after.ru_utime.tv_sec -
2910
before.ru_utime.tv_sec);
2911
elapsed += (after.ru_utime.tv_usec -
2912
before.ru_utime.tv_usec) / 1000000.0;
2914
printf("%s %s: %.6f\n", thegame.name, seed, elapsed);
2917
if (test_solve && thegame.can_solve) {
2919
* Now destroy the aux_info in the midend, by means of
2920
* re-entering the same game id, and then try to solve
2923
char *game_id, *err;
2925
game_id = midend_get_game_id(me);
2926
err = midend_game_id(me, game_id);
2928
fprintf(stderr, "%s %s: game id re-entry error: %s\n",
2929
thegame.name, seed, err);
2932
midend_new_game(me);
2935
err = midend_solve(me);
2937
* If the solve operation returned the error "Solution
2938
* not known for this puzzle", that's OK, because that
2939
* just means it's a puzzle for which we don't have an
2940
* algorithmic solver and hence can't solve it without
2941
* the aux_info, e.g. Netslide. Any other error is a
2944
if (err && strcmp(err, "Solution not known for this puzzle")) {
2945
fprintf(stderr, "%s %s: solve error: %s\n",
2946
thegame.name, seed, err);
2821
midend_new_game(me);
2824
2955
err = midend_print_puzzle(me, doc, soln);
2881
3012
midend_free(me);
3015
} else if (list_presets) {
3017
* Another specialist mode which causes the puzzle to list the
3018
* game_params strings for all its preset configurations.
3023
me = midend_new(NULL, &thegame, NULL, NULL);
3024
npresets = midend_num_presets(me);
3026
for (i = 0; i < npresets; i++) {
3027
game_params *params;
3028
char *name, *paramstr;
3030
midend_fetch_preset(me, i, &name, ¶ms);
3031
paramstr = thegame.encode_params(params, TRUE);
3033
printf("%s %s\n", paramstr, name);