X-Git-Url: http://winboard.nl/cgi-bin?a=blobdiff_plain;f=gtk%2Fxoptions.c;h=a3a54eaad9951028bfab667d3b2133279ba97870;hb=960cb2c18e20efe428653f8832e488aac93a6603;hp=ccc7588951ad0ed4fbb7961140e5a00956a59b0f;hpb=7304138955ef81f821e739b772cdce89509f518d;p=xboard.git diff --git a/gtk/xoptions.c b/gtk/xoptions.c index ccc7588..a3a54ea 100644 --- a/gtk/xoptions.c +++ b/gtk/xoptions.c @@ -1,7 +1,7 @@ /* * xoptions.c -- Move list window, part of X front end for XBoard * - * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014 Free Software Foundation, Inc. + * Copyright 2000, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc. * ------------------------------------------------------------------------ * * GNU XBoard is free software: you can redistribute it and/or modify @@ -48,7 +48,6 @@ extern char *getenv(); #include #include -#include #include #include #ifdef OSXAPP @@ -244,6 +243,12 @@ SetWidgetLabel (Option *opt, char *buf) } void +SetComboChoice (Option *opt, int n) +{ + gtk_combo_box_set_active(opt->handle, n); +} + +void SetDialogTitle (DialogClass dlg, char *title) { gtk_window_set_title(GTK_WINDOW(shells[dlg]), title); @@ -365,6 +370,16 @@ SetIconName (DialogClass dlg, char *name) #endif } +static gboolean +HelpEvent(GtkWidget *widget, GdkEventButton *event, gpointer gdata) +{ // intercept button3 clicks to pop up help +// Option *opt = (Option *) gdata; + char *msg = (char *) gdata; + if(event->button != 3) return FALSE; + DisplayHelp(msg); + return TRUE; +} + void ComboSelect(GtkWidget *widget, gpointer addr) { Option *opt = dialogOptions[((intptr_t)addr)>>8]; // applicable option list @@ -438,16 +453,31 @@ CreateMenuPopup (Option *opt, int n, int def) } else entry = gtk_menu_item_new_with_label(msg); gtk_signal_connect_object (GTK_OBJECT (entry), "activate", GTK_SIGNAL_FUNC(MenuSelect), (gpointer) (intptr_t) ((n<<16)+i)); + g_signal_connect(entry, "button-release-event", G_CALLBACK (HelpEvent), (gpointer) mb[i].string ); if(mb[i].accel) { guint accelerator_key; GdkModifierType accelerator_mods; gtk_accelerator_parse(mb[i].accel, &accelerator_key, &accelerator_mods); #ifdef OSXAPP - if(accelerator_mods & GDK_CONTROL_MASK) { // in OSX use Meta where Linux uses Ctrl - accelerator_mods &= ~GDK_CONTROL_MASK; // clear Ctrl flag - accelerator_mods |= GDK_META_MASK; // set Meta flag - } + if(accelerator_mods & GDK_CONTROL_MASK && + accelerator_key != 'v' && // don't use Cmd+V as this is a OS text edit command + accelerator_key != 'c' && // and Cmd+C + accelerator_key != 'x' && // and CMD+X + accelerator_key != 'a' // and CMD+A + ) { // in OSX use Meta (Cmd) where Linux uses Ctrl + accelerator_mods &= ~GDK_CONTROL_MASK; // clear Ctrl flag + accelerator_mods |= GDK_META_MASK; // set Meta flag + } else if (accelerator_mods & GDK_CONTROL_MASK && + accelerator_key == 'v' || + accelerator_key == 'c' || + accelerator_key == 'x' || + accelerator_key == 'a' + ) { // For these conflicting commands, lets make them alt-cmd + accelerator_mods &= ~GDK_CONTROL_MASK; // clear Ctrl flag + accelerator_mods |= GDK_META_MASK; + accelerator_mods |= GDK_MOD1_MASK; + } #endif gtk_widget_add_accelerator (GTK_WIDGET(entry), "activate",GtkAccelerators, accelerator_key, accelerator_mods, GTK_ACCEL_VISIBLE); @@ -502,6 +532,8 @@ TypeInProc (GtkWidget *widget, GdkEventKey *event, gpointer gdata) shiftState = event->state & GDK_SHIFT_MASK; controlState = event->state & GDK_CONTROL_MASK; switch(event->keyval) { + case 'e': return (controlState && IcsHist( 5, opt, dlg)); + case 'h': return (controlState && IcsHist( 8, opt, dlg)); case 'n': return (controlState && IcsHist(14, opt, dlg)); case 'o': return (controlState && IcsHist(15, opt, dlg)); case GDK_Tab: IcsHist(10, opt, dlg); break; @@ -528,11 +560,11 @@ HighlightText (Option *opt, int from, int to, Boolean highlight) if(!(opt->min & INIT)) { opt->min |= INIT; // each memo its own init flag! gtk_text_buffer_create_tag(opt->handle, "highlight", "background", "yellow", NULL); - gtk_text_buffer_create_tag(opt->handle, "normal", "background", "white", NULL); } gtk_text_buffer_get_iter_at_offset(opt->handle, &start, from); gtk_text_buffer_get_iter_at_offset(opt->handle, &end, to); - gtk_text_buffer_apply_tag_by_name(opt->handle, highlight ? "highlight" : "normal", &start, &end); + if(highlight) gtk_text_buffer_apply_tag_by_name(opt->handle, "highlight", &start, &end); + else gtk_text_buffer_remove_tag_by_name(opt->handle, "highlight", &start, &end); } static char **names; @@ -662,10 +694,10 @@ MemoEvent(GtkWidget *widget, GdkEvent *event, gpointer gdata) } if(memo->value == 250 // kludge to recognize ICS Console and Chat panes && gtk_text_buffer_get_selection_bounds(memo->handle, NULL, NULL) ) { -printf("*** selected\n"); gtk_text_buffer_get_selection_bounds(memo->handle, &start, &end); // only return selected text - index = -1; // kludge to indicate omething was selected + index = -1; // kludge to indicate something was selected } else { + if(abs(button) == 3 && gtk_text_buffer_get_selection_bounds(memo->handle, NULL, NULL)) return FALSE; // normal context menu // GTK_TODO: is this really the most efficient way to get the character at the mouse cursor??? gtk_text_view_window_to_buffer_coords(GTK_TEXT_VIEW(widget), GTK_TEXT_WINDOW_WIDGET, w, h, &x, &y); gtk_text_view_get_iter_at_location(GTK_TEXT_VIEW(widget), &start, x, y); @@ -678,7 +710,7 @@ printf("*** selected\n"); } /* get text from textbuffer */ val = gtk_text_buffer_get_text (memo->handle, &start, &end, FALSE); - break; + if(strlen(val) != index) break; // if we clicked behind all text, fall through to do default action default: return FALSE; // should not happen } @@ -824,6 +856,16 @@ gboolean GenericPopDown(w, resptype, gdata) return TRUE; } +gboolean PopDownProxy(w, gdata) + GtkWidget *w; + gpointer gdata; +{ + GtkResponseType resp = GTK_RESPONSE_ACCEPT; + int dlg = (intptr_t) gdata; + if(dlg >= 3000) dlg -= 3000, resp = GTK_RESPONSE_REJECT; + return GenericPopDown(gtk_widget_get_toplevel(w), resp, (gpointer)(intptr_t)dlg); +} + int AppendText(Option *opt, char *s) { char *v; @@ -1291,7 +1333,7 @@ if(appData.debugMode) printf("n=%d, h=%d, w=%d\n",n,height,width); top = breakType = 0; expandable = FALSE; } if(!SameRow(&option[i])) { - if(SameRow(&option[i+1])) { + if(SameRow(&option[i+1]) || topLevel && option[i].type == Button && option[i+1].type == EndMark && option[i+1].min & SAME_ROW) { GtkAttachOptions x = GTK_FILL; // make sure hbox is always available when we have more options on same row hbox = gtk_hbox_new (option[i].type == Button && option[i].textValue || option[i].type == Graph, 0); @@ -1381,8 +1423,15 @@ if(appData.debugMode) printf("n=%d, h=%d, w=%d\n",n,height,width); gtk_entry_set_max_length (GTK_ENTRY (entry), w); // left, right, top, bottom - if (strcmp(option[i].name, "") != 0) + if (strcmp(option[i].name, "") != 0) { + button = gtk_event_box_new(); + gtk_container_add(GTK_CONTAINER(button), label); + label = button; + gtk_widget_add_events(GTK_WIDGET(label), GDK_BUTTON_PRESS_MASK); + g_signal_connect(label, "button-press-event", G_CALLBACK(HelpEvent), (gpointer) option[i].name); + gtk_widget_set_sensitive(label, TRUE); gtk_table_attach(GTK_TABLE(table), label, left, left+1, top, top+1, GTK_FILL, GTK_FILL, 2, 1); // leading names do not expand + } if (option[i].type == Spin) { spinner_adj = (GtkAdjustment *) gtk_adjustment_new (option[i].value, option[i].min, option[i].max, 1.0, 0.0, 0.0); @@ -1404,6 +1453,7 @@ if(appData.debugMode) printf("n=%d, h=%d, w=%d\n",n,height,width); break; case CheckBox: checkbutton = gtk_check_button_new_with_label(option[i].name); + g_signal_connect(checkbutton, "button-press-event", G_CALLBACK (HelpEvent), (gpointer) option[i].name ); if(!currentCps) option[i].value = *(Boolean*)option[i].target; gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(checkbutton), option[i].value); gtk_table_attach(GTK_TABLE(table), checkbutton, left, left+r, top, top+1, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 0); @@ -1433,7 +1483,7 @@ if(appData.debugMode) printf("n=%d, h=%d, w=%d\n",n,height,width); g_signal_connect(label, "button-press-event", G_CALLBACK(MemoEvent), (gpointer) &option[i]); gtk_widget_set_sensitive(label, TRUE); } - Pack(hbox, table, label, left, left+3, top, 0); + Pack(hbox, table, label, left, left+r, top, 0); break; case SaveButton: case Button: @@ -1449,10 +1499,12 @@ if(appData.debugMode) printf("n=%d, h=%d, w=%d\n",n,height,width); /* set button color on new variant dialog */ if(option[i].textValue) { static char *b = "Bold"; + char *v, *p = NULL, n = option[i].value; + if(n >= 0) v = VariantName(n), p = strstr(first.variants, v); gdk_color_parse( option[i].textValue, &color ); gtk_widget_modify_bg ( GTK_WIDGET(button), GTK_STATE_NORMAL, &color ); gtk_widget_set_sensitive(button, option[i].value >= 0 && (appData.noChessProgram - || strstr(first.variants, VariantName(option[i].value)))); + || p && (!*v || strlen(p) == strlen(v) || p[strlen(v)] == ','))); if(engineVariant[100] ? !strcmp(engineVariant+100, option[i].name) : gameInfo.variant ? option[i].value == gameInfo.variant : !strcmp(option[i].name, "Normal")) SetWidgetFont(gtk_bin_get_child(GTK_BIN(button)), &b); @@ -1460,6 +1512,7 @@ if(appData.debugMode) printf("n=%d, h=%d, w=%d\n",n,height,width); Pack(hbox, table, button, left, left+1, top, 0); g_signal_connect (button, "clicked", G_CALLBACK (GenericCallback), (gpointer)(intptr_t) i + (dlgNr<<16)); + g_signal_connect(button, "button-press-event", G_CALLBACK (HelpEvent), (gpointer) option[i].name ); option[i].handle = (void*)button; break; case ComboBox: @@ -1566,7 +1619,11 @@ if(appData.debugMode) printf("n=%d, h=%d, w=%d\n",n,height,width); top--; msg = _(option[i].name); // write name on the menu button #ifndef OSXAPP - if(tinyLayout) { strcpy(def, msg); def[tinyLayout] = NULLCHAR; msg = def; } // clip menu text to keep menu bar small + if(tinyLayout) { // clip menu text to keep menu bar small + int clip = tinyLayout + 1; + strcpy(def, msg + (msg[clip-1] == '_')); + def[clip] = NULLCHAR; msg = def; + } #endif // XtSetArg(args[j], XtNmenuName, XtNewString(option[i].name)); j++; // XtSetArg(args[j], XtNlabel, msg); j++; @@ -1629,6 +1686,21 @@ if(appData.debugMode) printf("n=%d, h=%d, w=%d\n",n,height,width); } } + if(topLevel && !(option[i].min & NO_OK)) { // buttons requested in top-level window + button = gtk_button_new_with_label (_("OK")); + g_signal_connect (button, "clicked", G_CALLBACK (PopDownProxy), (gpointer)(intptr_t) dlgNr); + if(!(option[i].min & NO_CANCEL)) { + GtkWidget *button2 = gtk_button_new_with_label (_("Cancel")); + g_signal_connect (button2, "clicked", G_CALLBACK (PopDownProxy), (gpointer)(intptr_t) dlgNr + 3000); + if(!hbox) { + hbox = gtk_hbox_new (False, 0); + gtk_table_attach(GTK_TABLE(table), hbox, left, left+r, top+1, top+2, GTK_FILL | GTK_EXPAND, GTK_FILL, 2, 1); + } + Pack(hbox, table, button, left, left+1, top+1, 0); + Pack(hbox, table, button2, left, left+1, top+1, 0); + } else Pack(hbox, table, button, left, left+1, ++top, 0); + } + gtk_table_resize(GTK_TABLE(table), top+1, r); if(dlgNr == BoardWindow && appData.fixedSize) { // inhibit sizing GtkWidget *h = gtk_hbox_new(FALSE, 0);