X-Git-Url: https://git.distorted.org.uk/~mdw/sgt/puzzles/blobdiff_plain/98488ab92877f83b7727ed2571c6da991e1783c1..d5b1e2c1dbb25627c99db211476d4eb01c66f744:/gtk.c diff --git a/gtk.c b/gtk.c index 026bbe3..d551f47 100644 --- a/gtk.c +++ b/gtk.c @@ -499,6 +499,17 @@ void gtk_end_draw(void *handle) } } +#ifdef USE_PANGO +char *gtk_text_fallback(void *handle, const char *const *strings, int nstrings) +{ + /* + * We assume Pango can cope with any UTF-8 likely to be emitted + * by a puzzle. + */ + return dupstr(strings[0]); +} +#endif + const struct drawing_api gtk_drawing = { gtk_draw_text, gtk_draw_rect, @@ -516,7 +527,12 @@ const struct drawing_api gtk_drawing = { gtk_blitter_save, gtk_blitter_load, NULL, NULL, NULL, NULL, NULL, NULL, /* {begin,end}_{doc,page,puzzle} */ - NULL, /* line_width */ + NULL, NULL, /* line_width, line_dotted */ +#ifdef USE_PANGO + gtk_text_fallback, +#else + NULL, +#endif }; static void destroy(GtkWidget *widget, gpointer data) @@ -810,18 +826,18 @@ int message_box(GtkWidget *parent, char *title, char *msg, int centre, gtk_label_set_line_wrap(GTK_LABEL(text), TRUE); if (type == MB_OK) { - titles = "OK\0"; + titles = GTK_STOCK_OK "\0"; def = cancel = 0; } else { assert(type == MB_YESNO); - titles = "Yes\0No\0"; - def = 0; - cancel = 1; + titles = GTK_STOCK_NO "\0" GTK_STOCK_YES "\0"; + def = 1; + cancel = 0; } i = 0; while (*titles) { - button = gtk_button_new_with_label(titles); + button = gtk_button_new_from_stock(titles); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(window)->action_area), button, FALSE, FALSE, 0); gtk_widget_show(button); @@ -850,7 +866,7 @@ int message_box(GtkWidget *parent, char *title, char *msg, int centre, gtk_widget_show(window); i = -1; gtk_main(); - return (type == MB_YESNO ? i == 0 : TRUE); + return (type == MB_YESNO ? i == 1 : TRUE); } void error_box(GtkWidget *parent, char *msg) @@ -940,22 +956,22 @@ static int get_config(frontend *fe, int which) gtk_window_set_title(GTK_WINDOW(fe->cfgbox), title); sfree(title); - w = gtk_button_new_with_label("OK"); + w = gtk_button_new_from_stock(GTK_STOCK_CANCEL); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(fe->cfgbox)->action_area), w, FALSE, FALSE, 0); gtk_widget_show(w); - GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT); - gtk_window_set_default(GTK_WINDOW(fe->cfgbox), w); gtk_signal_connect(GTK_OBJECT(w), "clicked", - GTK_SIGNAL_FUNC(config_ok_button_clicked), fe); + GTK_SIGNAL_FUNC(config_cancel_button_clicked), fe); + cancel = w; - w = gtk_button_new_with_label("Cancel"); + w = gtk_button_new_from_stock(GTK_STOCK_OK); gtk_box_pack_end(GTK_BOX(GTK_DIALOG(fe->cfgbox)->action_area), w, FALSE, FALSE, 0); gtk_widget_show(w); + GTK_WIDGET_SET_FLAGS(w, GTK_CAN_DEFAULT); + gtk_window_set_default(GTK_WINDOW(fe->cfgbox), w); gtk_signal_connect(GTK_OBJECT(w), "clicked", - GTK_SIGNAL_FUNC(config_cancel_button_clicked), fe); - cancel = w; + GTK_SIGNAL_FUNC(config_ok_button_clicked), fe); table = gtk_table_new(1, 2, FALSE); y = 0; @@ -1208,77 +1224,40 @@ static void menu_preset_event(GtkMenuItem *menuitem, gpointer data) GdkAtom compound_text_atom, utf8_string_atom; int paste_initialised = FALSE; -void init_paste() +static void set_selection(frontend *fe, GdkAtom selection) { - unsigned char empty[] = { 0 }; - - if (paste_initialised) - return; - - if (!compound_text_atom) - compound_text_atom = gdk_atom_intern("COMPOUND_TEXT", FALSE); - if (!utf8_string_atom) - utf8_string_atom = gdk_atom_intern("UTF8_STRING", FALSE); + if (!paste_initialised) { + compound_text_atom = gdk_atom_intern("COMPOUND_TEXT", FALSE); + utf8_string_atom = gdk_atom_intern("UTF8_STRING", FALSE); + paste_initialised = TRUE; + } /* - * Ensure that all the cut buffers exist - according to the - * ICCCM, we must do this before we start using cut buffers. + * For this simple application we can safely assume that the + * data passed to this function is pure ASCII, which means we + * can return precisely the same stuff for types STRING, + * COMPOUND_TEXT or UTF8_STRING. */ - XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER0, XA_STRING, 8, PropModeAppend, empty, 0); - XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER1, XA_STRING, 8, PropModeAppend, empty, 0); - XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER2, XA_STRING, 8, PropModeAppend, empty, 0); - XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER3, XA_STRING, 8, PropModeAppend, empty, 0); - XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER4, XA_STRING, 8, PropModeAppend, empty, 0); - XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER5, XA_STRING, 8, PropModeAppend, empty, 0); - XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER6, XA_STRING, 8, PropModeAppend, empty, 0); - XChangeProperty(GDK_DISPLAY(), GDK_ROOT_WINDOW(), - XA_CUT_BUFFER7, XA_STRING, 8, PropModeAppend, empty, 0); -} - -/* Store data in a cut-buffer. */ -void store_cutbuffer(char *ptr, int len) -{ - /* ICCCM says we must rotate the buffers before storing to buffer 0. */ - XRotateBuffers(GDK_DISPLAY(), 1); - XStoreBytes(GDK_DISPLAY(), ptr, len); + + if (gtk_selection_owner_set(fe->area, selection, CurrentTime)) { + gtk_selection_clear_targets(fe->area, selection); + gtk_selection_add_target(fe->area, selection, + GDK_SELECTION_TYPE_STRING, 1); + gtk_selection_add_target(fe->area, selection, compound_text_atom, 1); + gtk_selection_add_target(fe->area, selection, utf8_string_atom, 1); + } } void write_clip(frontend *fe, char *data) { - init_paste(); - if (fe->paste_data) sfree(fe->paste_data); - /* - * For this simple application we can safely assume that the - * data passed to this function is pure ASCII, which means we - * can return precisely the same stuff for types STRING, - * COMPOUND_TEXT or UTF8_STRING. - */ - fe->paste_data = data; fe->paste_data_len = strlen(data); - store_cutbuffer(fe->paste_data, fe->paste_data_len); - - if (gtk_selection_owner_set(fe->area, GDK_SELECTION_PRIMARY, - CurrentTime)) { - gtk_selection_clear_targets(fe->area, GDK_SELECTION_PRIMARY); - gtk_selection_add_target(fe->area, GDK_SELECTION_PRIMARY, - GDK_SELECTION_TYPE_STRING, 1); - gtk_selection_add_target(fe->area, GDK_SELECTION_PRIMARY, - compound_text_atom, 1); - gtk_selection_add_target(fe->area, GDK_SELECTION_PRIMARY, - utf8_string_atom, 1); - } + set_selection(fe, GDK_SELECTION_PRIMARY); + set_selection(fe, GDK_SELECTION_CLIPBOARD); } void selection_get(GtkWidget *widget, GtkSelectionData *seldata, @@ -1579,7 +1558,7 @@ enum { ARG_EITHER, ARG_SAVE, ARG_ID }; /* for argtype */ static frontend *new_window(char *arg, int argtype, char **error) { frontend *fe; - GtkBox *vbox; + GtkBox *vbox, *hbox; GtkWidget *menubar, *menu, *menuitem; GdkPixmap *iconpm; GList *iconlist; @@ -1665,8 +1644,12 @@ static frontend *new_window(char *arg, int argtype, char **error) fe->accelgroup = gtk_accel_group_new(); gtk_window_add_accel_group(GTK_WINDOW(fe->window), fe->accelgroup); + hbox = GTK_BOX(gtk_hbox_new(FALSE, 0)); + gtk_box_pack_start(vbox, GTK_WIDGET(hbox), FALSE, FALSE, 0); + gtk_widget_show(GTK_WIDGET(hbox)); + menubar = gtk_menu_bar_new(); - gtk_box_pack_start(vbox, menubar, FALSE, FALSE, 0); + gtk_box_pack_start(hbox, menubar, TRUE, TRUE, 0); gtk_widget_show(menubar); menuitem = gtk_menu_item_new_with_mnemonic("_Game"); @@ -1760,9 +1743,11 @@ static frontend *new_window(char *arg, int argtype, char **error) gtk_signal_connect(GTK_OBJECT(menuitem), "activate", GTK_SIGNAL_FUNC(menu_save_event), fe); gtk_widget_show(menuitem); +#ifndef STYLUS_BASED 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", 'r'); +#endif if (thegame.can_format_as_text_ever) { add_menu_separator(GTK_CONTAINER(menu)); menuitem = gtk_menu_item_new_with_label("Copy"); @@ -1798,6 +1783,42 @@ static frontend *new_window(char *arg, int argtype, char **error) GTK_SIGNAL_FUNC(menu_about_event), fe); gtk_widget_show(menuitem); +#ifdef STYLUS_BASED + menuitem=gtk_button_new_with_mnemonic("_Redo"); + gtk_object_set_data(GTK_OBJECT(menuitem), "user-data", + GINT_TO_POINTER((int)('r'))); + gtk_signal_connect(GTK_OBJECT(menuitem), "clicked", + GTK_SIGNAL_FUNC(menu_key_event), fe); + gtk_box_pack_end(hbox, menuitem, FALSE, FALSE, 0); + gtk_widget_show(menuitem); + + menuitem=gtk_button_new_with_mnemonic("_Undo"); + gtk_object_set_data(GTK_OBJECT(menuitem), "user-data", + GINT_TO_POINTER((int)('u'))); + gtk_signal_connect(GTK_OBJECT(menuitem), "clicked", + GTK_SIGNAL_FUNC(menu_key_event), fe); + gtk_box_pack_end(hbox, menuitem, FALSE, FALSE, 0); + gtk_widget_show(menuitem); + + if (thegame.flags & REQUIRE_NUMPAD) { + hbox = GTK_BOX(gtk_hbox_new(FALSE, 0)); + gtk_box_pack_start(vbox, GTK_WIDGET(hbox), FALSE, FALSE, 0); + gtk_widget_show(GTK_WIDGET(hbox)); + + *((int*)errbuf)=0; + errbuf[1]='\0'; + for(errbuf[0]='0';errbuf[0]<='9';errbuf[0]++) { + menuitem=gtk_button_new_with_label(errbuf); + gtk_object_set_data(GTK_OBJECT(menuitem), "user-data", + GINT_TO_POINTER((int)(errbuf[0]))); + gtk_signal_connect(GTK_OBJECT(menuitem), "clicked", + GTK_SIGNAL_FUNC(menu_key_event), fe); + gtk_box_pack_start(hbox, menuitem, TRUE, TRUE, 0); + gtk_widget_show(menuitem); + } + } +#endif /* STYLUS_BASED */ + changed_preset(fe); { @@ -1851,6 +1872,9 @@ static frontend *new_window(char *arg, int argtype, char **error) fe->statusbar = NULL; fe->area = gtk_drawing_area_new(); +#if GTK_CHECK_VERSION(2,0,0) + GTK_WIDGET_UNSET_FLAGS(fe->area, GTK_DOUBLE_BUFFERED); +#endif get_size(fe, &x, &y); gtk_drawing_area_size(GTK_DRAWING_AREA(fe->area), x, y); fe->w = x;