mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 08:01:30 -07:00
Actually implemented the serialise/deserialise functions in
midend.c. Also I've added an experimental front end in gtk.c only: `Save' and `Load' options on the Game menu, which don't even show up unless you define the magic environment variable PUZZLES_EXPERIMENTAL_SAVE. Once I'm reasonably confident that the whole edifice is plausibly stable, I'll take that out and turn it into a supported feature (and also implement it in OS X and Windows and write documentation). [originally from svn r6030]
This commit is contained in:
132
gtk.c
132
gtk.c
@ -118,6 +118,7 @@ struct frontend {
|
||||
char *laststatus;
|
||||
int pw, ph; /* pixmap size (w, h are area size) */
|
||||
int ox, oy; /* offset of pixmap in drawing area */
|
||||
char *filesel_name;
|
||||
};
|
||||
|
||||
void get_random_seed(void **randseed, int *randseedsize)
|
||||
@ -450,6 +451,7 @@ static void destroy(GtkWidget *widget, gpointer data)
|
||||
{
|
||||
frontend *fe = (frontend *)data;
|
||||
deactivate_timer(fe);
|
||||
midend_free(fe->me);
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
@ -1114,6 +1116,123 @@ static void menu_copy_event(GtkMenuItem *menuitem, gpointer data)
|
||||
}
|
||||
}
|
||||
|
||||
static void filesel_ok(GtkButton *button, gpointer data)
|
||||
{
|
||||
frontend *fe = (frontend *)data;
|
||||
|
||||
gpointer filesel = gtk_object_get_data(GTK_OBJECT(button), "user-data");
|
||||
|
||||
const char *name =
|
||||
gtk_file_selection_get_filename(GTK_FILE_SELECTION(filesel));
|
||||
|
||||
fe->filesel_name = dupstr(name);
|
||||
}
|
||||
|
||||
static char *file_selector(frontend *fe, char *title, int save)
|
||||
{
|
||||
GtkWidget *filesel =
|
||||
gtk_file_selection_new(title);
|
||||
|
||||
fe->filesel_name = NULL;
|
||||
|
||||
gtk_window_set_modal(GTK_WINDOW(filesel), TRUE);
|
||||
gtk_object_set_data
|
||||
(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "user-data",
|
||||
(gpointer)filesel);
|
||||
gtk_signal_connect
|
||||
(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(filesel_ok), fe);
|
||||
gtk_signal_connect_object
|
||||
(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(gtk_widget_destroy), (gpointer)filesel);
|
||||
gtk_signal_connect_object
|
||||
(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->cancel_button), "clicked",
|
||||
GTK_SIGNAL_FUNC(gtk_widget_destroy), (gpointer)filesel);
|
||||
gtk_signal_connect(GTK_OBJECT(filesel), "destroy",
|
||||
GTK_SIGNAL_FUNC(window_destroy), NULL);
|
||||
gtk_widget_show(filesel);
|
||||
gtk_window_set_transient_for(GTK_WINDOW(filesel), GTK_WINDOW(fe->window));
|
||||
gtk_main();
|
||||
|
||||
return fe->filesel_name;
|
||||
}
|
||||
|
||||
static void savefile_write(void *wctx, void *buf, int len)
|
||||
{
|
||||
FILE *fp = (FILE *)wctx;
|
||||
fwrite(buf, 1, len, fp);
|
||||
}
|
||||
|
||||
static int savefile_read(void *wctx, void *buf, int len)
|
||||
{
|
||||
FILE *fp = (FILE *)wctx;
|
||||
int ret;
|
||||
|
||||
ret = fread(buf, 1, len, fp);
|
||||
return (ret == len);
|
||||
}
|
||||
|
||||
static void menu_save_event(GtkMenuItem *menuitem, gpointer data)
|
||||
{
|
||||
frontend *fe = (frontend *)data;
|
||||
char *name;
|
||||
|
||||
name = file_selector(fe, "Enter name of game file to save", TRUE);
|
||||
|
||||
if (name) {
|
||||
FILE *fp = fopen(name, "w");
|
||||
sfree(name);
|
||||
|
||||
if (!fp) {
|
||||
error_box(fe->window, "Unable to open save file");
|
||||
return;
|
||||
}
|
||||
|
||||
midend_serialise(fe->me, savefile_write, fp);
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_load_event(GtkMenuItem *menuitem, gpointer data)
|
||||
{
|
||||
frontend *fe = (frontend *)data;
|
||||
char *name, *err;
|
||||
int x, y;
|
||||
|
||||
name = file_selector(fe, "Enter name of saved game file to load", FALSE);
|
||||
|
||||
if (name) {
|
||||
FILE *fp = fopen(name, "r");
|
||||
sfree(name);
|
||||
|
||||
if (!fp) {
|
||||
error_box(fe->window, "Unable to open saved game file");
|
||||
return;
|
||||
}
|
||||
|
||||
err = midend_deserialise(fe->me, savefile_read, fp);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
if (err) {
|
||||
error_box(fe->window, err);
|
||||
return;
|
||||
}
|
||||
|
||||
get_size(fe, &x, &y);
|
||||
fe->w = x;
|
||||
fe->h = y;
|
||||
gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y);
|
||||
{
|
||||
GtkRequisition req;
|
||||
gtk_widget_size_request(GTK_WIDGET(fe->window), &req);
|
||||
gtk_window_resize(GTK_WINDOW(fe->window), req.width, req.height);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void menu_solve_event(GtkMenuItem *menuitem, gpointer data)
|
||||
{
|
||||
frontend *fe = (frontend *)data;
|
||||
@ -1295,6 +1414,19 @@ static frontend *new_window(char *game_id, char **error)
|
||||
}
|
||||
}
|
||||
|
||||
if (getenv("PUZZLES_EXPERIMENTAL_SAVE") != NULL) {
|
||||
add_menu_separator(GTK_CONTAINER(menu));
|
||||
menuitem = gtk_menu_item_new_with_label("Load");
|
||||
gtk_container_add(GTK_CONTAINER(menu), menuitem);
|
||||
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
|
||||
GTK_SIGNAL_FUNC(menu_load_event), fe);
|
||||
gtk_widget_show(menuitem);
|
||||
menuitem = gtk_menu_item_new_with_label("Save");
|
||||
gtk_container_add(GTK_CONTAINER(menu), menuitem);
|
||||
gtk_signal_connect(GTK_OBJECT(menuitem), "activate",
|
||||
GTK_SIGNAL_FUNC(menu_save_event), fe);
|
||||
gtk_widget_show(menuitem);
|
||||
}
|
||||
add_menu_separator(GTK_CONTAINER(menu));
|
||||
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Undo", 'u');
|
||||
add_menu_item_with_key(fe, GTK_CONTAINER(menu), "Redo", '\x12');
|
||||
|
Reference in New Issue
Block a user