summaryrefslogtreecommitdiff
path: root/apps/plugins/puzzles/src/gtk.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/puzzles/src/gtk.c')
-rw-r--r--apps/plugins/puzzles/src/gtk.c142
1 files changed, 103 insertions, 39 deletions
diff --git a/apps/plugins/puzzles/src/gtk.c b/apps/plugins/puzzles/src/gtk.c
index c212522957..37ba8078e2 100644
--- a/apps/plugins/puzzles/src/gtk.c
+++ b/apps/plugins/puzzles/src/gtk.c
@@ -71,7 +71,7 @@
71#ifdef DEBUGGING 71#ifdef DEBUGGING
72static FILE *debug_fp = NULL; 72static FILE *debug_fp = NULL;
73 73
74void dputs(char *buf) 74void dputs(const char *buf)
75{ 75{
76 if (!debug_fp) { 76 if (!debug_fp) {
77 debug_fp = fopen("debug.log", "w"); 77 debug_fp = fopen("debug.log", "w");
@@ -85,7 +85,7 @@ void dputs(char *buf)
85 } 85 }
86} 86}
87 87
88void debug_printf(char *fmt, ...) 88void debug_printf(const char *fmt, ...)
89{ 89{
90 char buf[4096]; 90 char buf[4096];
91 va_list ap; 91 va_list ap;
@@ -101,7 +101,7 @@ void debug_printf(char *fmt, ...)
101 * Error reporting functions used elsewhere. 101 * Error reporting functions used elsewhere.
102 */ 102 */
103 103
104void fatal(char *fmt, ...) 104void fatal(const char *fmt, ...)
105{ 105{
106 va_list ap; 106 va_list ap;
107 107
@@ -189,6 +189,38 @@ struct frontend {
189 int drawing_area_shrink_pending; 189 int drawing_area_shrink_pending;
190 int menubar_is_local; 190 int menubar_is_local;
191#endif 191#endif
192#if GTK_CHECK_VERSION(3,0,0)
193 /*
194 * This is used to get round an annoying lack of GTK notification
195 * message. If we request a window resize with
196 * gtk_window_resize(), we normally get back a "configure" event
197 * on the window and on its drawing area, and we respond to the
198 * latter by doing an appropriate resize of the puzzle. If the
199 * window is maximised, so that gtk_window_resize() _doesn't_
200 * change its size, then that configure event never shows up. But
201 * if we requested the resize in response to a change of puzzle
202 * parameters (say, the user selected a differently-sized preset
203 * from the menu), then we would still like to be _notified_ that
204 * the window size was staying the same, so that we can respond by
205 * choosing an appropriate tile size for the new puzzle preset in
206 * the existing window size.
207 *
208 * Fortunately, in GTK 3, we may not get a "configure" event on
209 * the drawing area in this situation, but we still get a
210 * "size_allocate" event on the whole window (which, in other
211 * situations when we _do_ get a "configure" on the area, turns up
212 * second). So we treat _that_ event as indicating that if the
213 * "configure" event hasn't already shown up then it's not going
214 * to arrive.
215 *
216 * This flag is where we bookkeep this system. On
217 * gtk_window_resize we set this flag to true; the area's
218 * configure handler sets it back to false; then if that doesn't
219 * happen, the window's size_allocate handler does a fallback
220 * puzzle resize when it sees this flag still set to true.
221 */
222 int awaiting_resize_ack;
223#endif
192}; 224};
193 225
194struct blitter { 226struct blitter {
@@ -232,7 +264,7 @@ void frontend_default_colour(frontend *fe, float *output)
232#endif 264#endif
233} 265}
234 266
235void gtk_status_bar(void *handle, char *text) 267void gtk_status_bar(void *handle, const char *text)
236{ 268{
237 frontend *fe = (frontend *)handle; 269 frontend *fe = (frontend *)handle;
238 270
@@ -968,7 +1000,7 @@ void gtk_unclip(void *handle)
968} 1000}
969 1001
970void gtk_draw_text(void *handle, int x, int y, int fonttype, int fontsize, 1002void gtk_draw_text(void *handle, int x, int y, int fonttype, int fontsize,
971 int align, int colour, char *text) 1003 int align, int colour, const char *text)
972{ 1004{
973 frontend *fe = (frontend *)handle; 1005 frontend *fe = (frontend *)handle;
974 int i; 1006 int i;
@@ -1338,15 +1370,10 @@ static gint map_window(GtkWidget *widget, GdkEvent *event,
1338 return TRUE; 1370 return TRUE;
1339} 1371}
1340 1372
1341static gint configure_area(GtkWidget *widget, 1373static void resize_puzzle_to_area(frontend *fe, int x, int y)
1342 GdkEventConfigure *event, gpointer data)
1343{ 1374{
1344 frontend *fe = (frontend *)data;
1345 int x, y;
1346 int oldw = fe->w, oldpw = fe->pw, oldh = fe->h, oldph = fe->ph; 1375 int oldw = fe->w, oldpw = fe->pw, oldh = fe->h, oldph = fe->ph;
1347 1376
1348 x = event->width;
1349 y = event->height;
1350 fe->w = x; 1377 fe->w = x;
1351 fe->h = y; 1378 fe->h = y;
1352 midend_size(fe->me, &x, &y, TRUE); 1379 midend_size(fe->me, &x, &y, TRUE);
@@ -1363,10 +1390,31 @@ static gint configure_area(GtkWidget *widget,
1363 } 1390 }
1364 1391
1365 midend_force_redraw(fe->me); 1392 midend_force_redraw(fe->me);
1393}
1366 1394
1395static gint configure_area(GtkWidget *widget,
1396 GdkEventConfigure *event, gpointer data)
1397{
1398 frontend *fe = (frontend *)data;
1399 resize_puzzle_to_area(fe, event->width, event->height);
1400 fe->awaiting_resize_ack = FALSE;
1367 return TRUE; 1401 return TRUE;
1368} 1402}
1369 1403
1404#if GTK_CHECK_VERSION(3,0,0)
1405static void window_size_alloc(GtkWidget *widget, GtkAllocation *allocation,
1406 gpointer data)
1407{
1408 frontend *fe = (frontend *)data;
1409 if (fe->awaiting_resize_ack) {
1410 GtkAllocation a;
1411 gtk_widget_get_allocation(fe->area, &a);
1412 resize_puzzle_to_area(fe, a.width, a.height);
1413 fe->awaiting_resize_ack = FALSE;
1414 }
1415}
1416#endif
1417
1370static gint timer_func(gpointer data) 1418static gint timer_func(gpointer data)
1371{ 1419{
1372 frontend *fe = (frontend *)data; 1420 frontend *fe = (frontend *)data;
@@ -1444,8 +1492,8 @@ static void align_label(GtkLabel *label, double x, double y)
1444} 1492}
1445 1493
1446#if GTK_CHECK_VERSION(3,0,0) 1494#if GTK_CHECK_VERSION(3,0,0)
1447int message_box(GtkWidget *parent, char *title, char *msg, int centre, 1495int message_box(GtkWidget *parent, const char *title, const char *msg,
1448 int type) 1496 int centre, int type)
1449{ 1497{
1450 GtkWidget *window; 1498 GtkWidget *window;
1451 gint ret; 1499 gint ret;
@@ -1539,7 +1587,7 @@ int message_box(GtkWidget *parent, char *title, char *msg, int centre,
1539} 1587}
1540#endif /* GTK_CHECK_VERSION(3,0,0) */ 1588#endif /* GTK_CHECK_VERSION(3,0,0) */
1541 1589
1542void error_box(GtkWidget *parent, char *msg) 1590void error_box(GtkWidget *parent, const char *msg)
1543{ 1591{
1544 message_box(parent, "Error", msg, FALSE, MB_OK); 1592 message_box(parent, "Error", msg, FALSE, MB_OK);
1545} 1593}
@@ -1547,7 +1595,7 @@ void error_box(GtkWidget *parent, char *msg)
1547static void config_ok_button_clicked(GtkButton *button, gpointer data) 1595static void config_ok_button_clicked(GtkButton *button, gpointer data)
1548{ 1596{
1549 frontend *fe = (frontend *)data; 1597 frontend *fe = (frontend *)data;
1550 char *err; 1598 const char *err;
1551 1599
1552 err = midend_set_config(fe->me, fe->cfg_which, fe->cfg); 1600 err = midend_set_config(fe->me, fe->cfg_which, fe->cfg);
1553 1601
@@ -1593,22 +1641,25 @@ static void editbox_changed(GtkEditable *ed, gpointer data)
1593{ 1641{
1594 config_item *i = (config_item *)data; 1642 config_item *i = (config_item *)data;
1595 1643
1596 sfree(i->sval); 1644 assert(i->type == C_STRING);
1597 i->sval = dupstr(gtk_entry_get_text(GTK_ENTRY(ed))); 1645 sfree(i->u.string.sval);
1646 i->u.string.sval = dupstr(gtk_entry_get_text(GTK_ENTRY(ed)));
1598} 1647}
1599 1648
1600static void button_toggled(GtkToggleButton *tb, gpointer data) 1649static void button_toggled(GtkToggleButton *tb, gpointer data)
1601{ 1650{
1602 config_item *i = (config_item *)data; 1651 config_item *i = (config_item *)data;
1603 1652
1604 i->ival = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tb)); 1653 assert(i->type == C_BOOLEAN);
1654 i->u.boolean.bval = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tb));
1605} 1655}
1606 1656
1607static void droplist_sel(GtkComboBox *combo, gpointer data) 1657static void droplist_sel(GtkComboBox *combo, gpointer data)
1608{ 1658{
1609 config_item *i = (config_item *)data; 1659 config_item *i = (config_item *)data;
1610 1660
1611 i->ival = gtk_combo_box_get_active(combo); 1661 assert(i->type == C_CHOICES);
1662 i->u.choices.selected = gtk_combo_box_get_active(combo);
1612} 1663}
1613 1664
1614static int get_config(frontend *fe, int which) 1665static int get_config(frontend *fe, int which)
@@ -1703,7 +1754,7 @@ static int get_config(frontend *fe, int which)
1703 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 1754 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
1704 3, 3); 1755 3, 3);
1705#endif 1756#endif
1706 gtk_entry_set_text(GTK_ENTRY(w), i->sval); 1757 gtk_entry_set_text(GTK_ENTRY(w), i->u.string.sval);
1707 g_signal_connect(G_OBJECT(w), "changed", 1758 g_signal_connect(G_OBJECT(w), "changed",
1708 G_CALLBACK(editbox_changed), i); 1759 G_CALLBACK(editbox_changed), i);
1709 g_signal_connect(G_OBJECT(w), "key_press_event", 1760 g_signal_connect(G_OBJECT(w), "key_press_event",
@@ -1728,7 +1779,8 @@ static int get_config(frontend *fe, int which)
1728 GTK_EXPAND | GTK_SHRINK | GTK_FILL, 1779 GTK_EXPAND | GTK_SHRINK | GTK_FILL,
1729 3, 3); 1780 3, 3);
1730#endif 1781#endif
1731 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w), i->ival); 1782 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(w),
1783 i->u.boolean.bval);
1732 gtk_widget_show(w); 1784 gtk_widget_show(w);
1733 break; 1785 break;
1734 1786
@@ -1751,15 +1803,16 @@ static int get_config(frontend *fe, int which)
1751 1803
1752 { 1804 {
1753 int c; 1805 int c;
1754 char *p, *q, *name; 1806 const char *p, *q;
1807 char *name;
1755 GtkListStore *model; 1808 GtkListStore *model;
1756 GtkCellRenderer *cr; 1809 GtkCellRenderer *cr;
1757 GtkTreeIter iter; 1810 GtkTreeIter iter;
1758 1811
1759 model = gtk_list_store_new(1, G_TYPE_STRING); 1812 model = gtk_list_store_new(1, G_TYPE_STRING);
1760 1813
1761 c = *i->sval; 1814 c = *i->u.choices.choicenames;
1762 p = i->sval+1; 1815 p = i->u.choices.choicenames+1;
1763 1816
1764 while (*p) { 1817 while (*p) {
1765 q = p; 1818 q = p;
@@ -1780,7 +1833,8 @@ static int get_config(frontend *fe, int which)
1780 1833
1781 w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model)); 1834 w = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
1782 1835
1783 gtk_combo_box_set_active(GTK_COMBO_BOX(w), i->ival); 1836 gtk_combo_box_set_active(GTK_COMBO_BOX(w),
1837 i->u.choices.selected);
1784 1838
1785 cr = gtk_cell_renderer_text_new(); 1839 cr = gtk_cell_renderer_text_new();
1786 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), cr, TRUE); 1840 gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(w), cr, TRUE);
@@ -1881,8 +1935,7 @@ static void changed_preset(frontend *fe)
1881 struct preset_menu_entry *entry = 1935 struct preset_menu_entry *entry =
1882 (struct preset_menu_entry *)g_object_get_data( 1936 (struct preset_menu_entry *)g_object_get_data(
1883 G_OBJECT(gs->data), "user-data"); 1937 G_OBJECT(gs->data), "user-data");
1884 1938 if (!entry || entry->id != n)
1885 if (entry && entry->id != n)
1886 gtk_check_menu_item_set_active( 1939 gtk_check_menu_item_set_active(
1887 GTK_CHECK_MENU_ITEM(gs->data), FALSE); 1940 GTK_CHECK_MENU_ITEM(gs->data), FALSE);
1888 else 1941 else
@@ -1890,7 +1943,7 @@ static void changed_preset(frontend *fe)
1890 } 1943 }
1891 if (found) 1944 if (found)
1892 gtk_check_menu_item_set_active( 1945 gtk_check_menu_item_set_active(
1893 GTK_CHECK_MENU_ITEM(found->data), FALSE); 1946 GTK_CHECK_MENU_ITEM(found->data), TRUE);
1894 } 1947 }
1895 fe->preset_threaded = FALSE; 1948 fe->preset_threaded = FALSE;
1896 1949
@@ -1996,6 +2049,7 @@ static void resize_fe(frontend *fe)
1996 2049
1997#if GTK_CHECK_VERSION(3,0,0) 2050#if GTK_CHECK_VERSION(3,0,0)
1998 gtk_window_resize(GTK_WINDOW(fe->window), x, y + window_extra_height(fe)); 2051 gtk_window_resize(GTK_WINDOW(fe->window), x, y + window_extra_height(fe));
2052 fe->awaiting_resize_ack = TRUE;
1999#else 2053#else
2000 fe->drawing_area_shrink_pending = FALSE; 2054 fe->drawing_area_shrink_pending = FALSE;
2001 gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y); 2055 gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
@@ -2114,7 +2168,7 @@ static void filesel_ok(GtkButton *button, gpointer data)
2114 fe->filesel_name = dupstr(name); 2168 fe->filesel_name = dupstr(name);
2115} 2169}
2116 2170
2117static char *file_selector(frontend *fe, char *title, int save) 2171static char *file_selector(frontend *fe, const char *title, int save)
2118{ 2172{
2119 GtkWidget *filesel = 2173 GtkWidget *filesel =
2120 gtk_file_selection_new(title); 2174 gtk_file_selection_new(title);
@@ -2145,7 +2199,7 @@ static char *file_selector(frontend *fe, char *title, int save)
2145 2199
2146#else 2200#else
2147 2201
2148static char *file_selector(frontend *fe, char *title, int save) 2202static char *file_selector(frontend *fe, const char *title, int save)
2149{ 2203{
2150 char *filesel_name = NULL; 2204 char *filesel_name = NULL;
2151 2205
@@ -2177,7 +2231,7 @@ struct savefile_write_ctx {
2177 int error; 2231 int error;
2178}; 2232};
2179 2233
2180static void savefile_write(void *wctx, void *buf, int len) 2234static void savefile_write(void *wctx, const void *buf, int len)
2181{ 2235{
2182 struct savefile_write_ctx *ctx = (struct savefile_write_ctx *)wctx; 2236 struct savefile_write_ctx *ctx = (struct savefile_write_ctx *)wctx;
2183 if (fwrite(buf, 1, len, ctx->fp) < len) 2237 if (fwrite(buf, 1, len, ctx->fp) < len)
@@ -2244,7 +2298,8 @@ static void menu_save_event(GtkMenuItem *menuitem, gpointer data)
2244static void menu_load_event(GtkMenuItem *menuitem, gpointer data) 2298static void menu_load_event(GtkMenuItem *menuitem, gpointer data)
2245{ 2299{
2246 frontend *fe = (frontend *)data; 2300 frontend *fe = (frontend *)data;
2247 char *name, *err; 2301 char *name;
2302 const char *err;
2248 2303
2249 name = file_selector(fe, "Enter name of saved game file to load", FALSE); 2304 name = file_selector(fe, "Enter name of saved game file to load", FALSE);
2250 2305
@@ -2275,7 +2330,7 @@ static void menu_load_event(GtkMenuItem *menuitem, gpointer data)
2275static void menu_solve_event(GtkMenuItem *menuitem, gpointer data) 2330static void menu_solve_event(GtkMenuItem *menuitem, gpointer data)
2276{ 2331{
2277 frontend *fe = (frontend *)data; 2332 frontend *fe = (frontend *)data;
2278 char *msg; 2333 const char *msg;
2279 2334
2280 msg = midend_solve(fe->me); 2335 msg = midend_solve(fe->me);
2281 2336
@@ -2341,7 +2396,7 @@ static void menu_about_event(GtkMenuItem *menuitem, gpointer data)
2341} 2396}
2342 2397
2343static GtkWidget *add_menu_ui_item( 2398static GtkWidget *add_menu_ui_item(
2344 frontend *fe, GtkContainer *cont, char *text, int action, 2399 frontend *fe, GtkContainer *cont, const char *text, int action,
2345 int accel_key, int accel_keyqual) 2400 int accel_key, int accel_keyqual)
2346{ 2401{
2347 GtkWidget *menuitem = gtk_menu_item_new_with_label(text); 2402 GtkWidget *menuitem = gtk_menu_item_new_with_label(text);
@@ -2434,7 +2489,7 @@ static frontend *new_window(char *arg, int argtype, char **error)
2434 fe->me = midend_new(fe, &thegame, &gtk_drawing, fe); 2489 fe->me = midend_new(fe, &thegame, &gtk_drawing, fe);
2435 2490
2436 if (arg) { 2491 if (arg) {
2437 char *err; 2492 const char *err;
2438 FILE *fp; 2493 FILE *fp;
2439 2494
2440 errbuf[0] = '\0'; 2495 errbuf[0] = '\0';
@@ -2522,6 +2577,10 @@ static frontend *new_window(char *arg, int argtype, char **error)
2522 } 2577 }
2523#endif 2578#endif
2524 2579
2580#if GTK_CHECK_VERSION(3,0,0)
2581 fe->awaiting_resize_ack = FALSE;
2582#endif
2583
2525 fe->window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 2584 fe->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2526 gtk_window_set_title(GTK_WINDOW(fe->window), thegame.name); 2585 gtk_window_set_title(GTK_WINDOW(fe->window), thegame.name);
2527 2586
@@ -2786,6 +2845,10 @@ static frontend *new_window(char *arg, int argtype, char **error)
2786 G_CALLBACK(configure_area), fe); 2845 G_CALLBACK(configure_area), fe);
2787 g_signal_connect(G_OBJECT(fe->window), "configure_event", 2846 g_signal_connect(G_OBJECT(fe->window), "configure_event",
2788 G_CALLBACK(configure_window), fe); 2847 G_CALLBACK(configure_window), fe);
2848#if GTK_CHECK_VERSION(3,0,0)
2849 g_signal_connect(G_OBJECT(fe->window), "size_allocate",
2850 G_CALLBACK(window_size_alloc), fe);
2851#endif
2789 2852
2790 gtk_widget_add_events(GTK_WIDGET(fe->area), 2853 gtk_widget_add_events(GTK_WIDGET(fe->area),
2791 GDK_BUTTON_PRESS_MASK | 2854 GDK_BUTTON_PRESS_MASK |
@@ -2865,7 +2928,7 @@ int main(int argc, char **argv)
2865 int soln = FALSE, colour = FALSE; 2928 int soln = FALSE, colour = FALSE;
2866 float scale = 1.0F; 2929 float scale = 1.0F;
2867 float redo_proportion = 0.0F; 2930 float redo_proportion = 0.0F;
2868 char *savefile = NULL, *savesuffix = NULL; 2931 const char *savefile = NULL, *savesuffix = NULL;
2869 char *arg = NULL; 2932 char *arg = NULL;
2870 int argtype = ARG_EITHER; 2933 int argtype = ARG_EITHER;
2871 char *screenshot_file = NULL; 2934 char *screenshot_file = NULL;
@@ -3108,7 +3171,8 @@ int main(int argc, char **argv)
3108 * generated descriptive game IDs.) 3171 * generated descriptive game IDs.)
3109 */ 3172 */
3110 while (ngenerate == 0 || i < n) { 3173 while (ngenerate == 0 || i < n) {
3111 char *pstr, *err, *seed; 3174 char *pstr, *seed;
3175 const char *err;
3112 struct rusage before, after; 3176 struct rusage before, after;
3113 3177
3114 if (ngenerate == 0) { 3178 if (ngenerate == 0) {
@@ -3162,7 +3226,7 @@ int main(int argc, char **argv)
3162 * re-entering the same game id, and then try to solve 3226 * re-entering the same game id, and then try to solve
3163 * it. 3227 * it.
3164 */ 3228 */
3165 char *game_id, *err; 3229 char *game_id;
3166 3230
3167 game_id = midend_get_game_id(me); 3231 game_id = midend_get_game_id(me);
3168 err = midend_game_id(me, game_id); 3232 err = midend_game_id(me, game_id);
@@ -3207,7 +3271,7 @@ int main(int argc, char **argv)
3207 sprintf(realname, "%s%d%s", savefile, i, savesuffix); 3271 sprintf(realname, "%s%d%s", savefile, i, savesuffix);
3208 3272
3209 if (soln) { 3273 if (soln) {
3210 char *err = midend_solve(me); 3274 const char *err = midend_solve(me);
3211 if (err) { 3275 if (err) {
3212 fprintf(stderr, "%s: unable to show solution: %s\n", 3276 fprintf(stderr, "%s: unable to show solution: %s\n",
3213 realname, err); 3277 realname, err);