From 81fccf197070389b0f540cfdaccc2660764f2a1f Mon Sep 17 00:00:00 2001 From: H.G. Muller Date: Mon, 15 Oct 2012 22:17:50 +0200 Subject: [PATCH] Transfer more gtk-xt code, and add some new Add input-source handling Graft color picker ( callbeack in the text field is still missing!) Handle contents of label widgets (store handles in Option for access) Add printing of clocks Add printing of window title Pay attention to BORDER attribute of Label Options (pack in frame) Delete ReadBitmap code (also remove #including of bitmap files for icons) Fix layout of textviews (adapt to newer Option format, incl. wrap, scroll) Support vertical stacking in Break Option (no table widening when !SAME_ROW) Make default horizontal scroll policy automatic (for engine-output window) Fix disabling of unused spinners in TC dialog --- xboard.c | 191 ++++++++++++++++++++++++++++-------------------------------- xoptions.c | 94 ++++++++++++++--------------- 2 files changed, 136 insertions(+), 149 deletions(-) diff --git a/xboard.c b/xboard.c index 6ed7bfc..f1c5425 100644 --- a/xboard.c +++ b/xboard.c @@ -184,17 +184,6 @@ extern char *getenv(); // [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are. #include "common.h" -#if HAVE_LIBXPM -#include -#define IMAGE_EXT "xpm" -#else -#define IMAGE_EXT "xim" -#endif - -#include "bitmaps/icon_white.bm" -#include "bitmaps/icon_black.bm" -#include "bitmaps/checkmark.bm" - #include "frontend.h" #include "backend.h" #include "backendz.h" @@ -239,8 +228,6 @@ XFontSet CreateFontSet P((char *base_fnt_lst)); #else char *FindFont P((char *pattern, int targetPxlSize)); #endif -void ReadBitmap P((Pixmap *pm, String name, unsigned char bits[], - u_int wreq, u_int hreq)); void EventProc P((Widget widget, caddr_t unused, XEvent *event)); void DelayedDrag P((void)); static void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event)); @@ -328,20 +315,6 @@ WindowPlacement wpEngineOutput; WindowPlacement wpGameList; WindowPlacement wpTags; -#define INPUT_SOURCE_BUF_SIZE 8192 - -typedef struct { - CPKind kind; - int fd; - int lineByLine; - char *unused; - InputCallback func; - XtInputId xid; - char buf[INPUT_SOURCE_BUF_SIZE]; - VOIDSTAR closure; -} InputSource; - - /* This magic number is the number of intermediate frames used in each half of the animation. For short moves it's reduced by 1. The total number of frames will be factor * 2 + 1. */ @@ -1341,8 +1314,8 @@ main (int argc, char **argv) menuBarWidget = optList[W_MENU].handle; dropMenu = optList[W_DROP].handle; titleWidget = optList[optList[W_TITLE].type != -1 ? W_TITLE : W_SMALL].handle; - formWidget = XtParent(boardWidget); #ifdef TODO_GTK + formWidget = XtParent(boardWidget); XtSetArg(args[0], XtNbackground, &timerBackgroundPixel); XtSetArg(args[1], XtNforeground, &timerForegroundPixel); XtGetValues(optList[W_WHITE].handle, args, 2); @@ -1361,13 +1334,6 @@ main (int argc, char **argv) // [HGM] it seems the layout code ends here, but perhaps the color stuff is size independent and would // not need to go into InitDrawingSizes(). - /* - * Create X checkmark bitmap and initialize option menu checks. - */ -#ifdef TODO_GTK - ReadBitmap(&xMarkPixmap, "checkmark.bm", - checkmark_bits, checkmark_width, checkmark_height); -#endif InitMenuMarkers(); /* @@ -1477,7 +1443,10 @@ main (int argc, char **argv) #endif /* check for GTK events and process them */ - gtk_main(); +// gtk_main(); +while(1) { +gtk_main_iteration(); +} if (appData.debugMode) fclose(debugFP); // [DM] debug return 0; @@ -1679,17 +1648,6 @@ FindFont (char *pattern, int targetPxlSize) #endif void -ReadBitmap (Pixmap *pm, String name, unsigned char bits[], u_int wreq, u_int hreq) -{ - if (bits != NULL) { -#ifdef TODO_GTK - *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits, - wreq, hreq); -#endif - } -} - -void EnableNamedMenuItem (char *menuRef, int state) { MenuItem *item = MenuNameToItem(menuRef); @@ -1967,7 +1925,7 @@ FreezeUI () { if (frozen) return; /* Grab by a widget that doesn't accept input */ - XtAddGrab(optList[W_MESSG].handle, TRUE, FALSE); + gtk_grab_add(optList[W_MESSG].handle); frozen = 1; } @@ -1976,9 +1934,7 @@ void ThawUI () { if (!frozen) return; -#ifdef TODO_GTK - XtRemoveGrab(optList[W_MESSG].handle); -#endif + gtk_grab_remove(optList[W_MESSG].handle); frozen = 0; } @@ -2332,6 +2288,10 @@ SetWindowTitle (char *text, char *title, char *icon) XtSetValues(shellWidget, args, i); XSync(xDisplay, False); #endif + if (appData.titleInWindow) { + SetWidgetLabel(titleWidget, text); + } + gtk_window_set_title (GTK_WINDOW(shells[BoardWindow]), title); } @@ -2376,38 +2336,33 @@ DisplayIcsInteractionTitle (String message) void DisplayTimerLabel (Option *opt, char *color, long timer, int highlight) { -#ifdef TODO_GTK - char buf[MSG_SIZ]; - Arg args[16]; - Widget w = (Widget) opt->handle; - - /* check for low time warning */ - Pixel foregroundOrWarningColor = timerForegroundPixel; + GtkWidget *w = (GtkWidget *) opt->handle; + char *markup; + char bgcolor[10]; + char fgcolor[10]; + if (highlight) { + strcpy(bgcolor, "black"); + strcpy(fgcolor, "white"); + } else { + strcpy(bgcolor, "white"); + strcpy(fgcolor, "black"); + } if (timer > 0 && appData.lowTimeWarning && - (timer / 1000) < appData.icsAlarmTime) - foregroundOrWarningColor = lowTimeWarningColor; - - if (appData.clockMode) { - snprintf(buf, MSG_SIZ, "%s:%s%s", color, appData.logoSize && !partnerUp ? "\n" : " ", TimeString(timer)); - XtSetArg(args[0], XtNlabel, buf); - } else { - snprintf(buf, MSG_SIZ, "%s ", color); - XtSetArg(args[0], XtNlabel, buf); + (timer / 1000) < appData.icsAlarmTime) { + strcpy(fgcolor, appData.lowTimeWarningColor); } - if (highlight) { - - XtSetArg(args[1], XtNbackground, foregroundOrWarningColor); - XtSetArg(args[2], XtNforeground, timerBackgroundPixel); + if (appData.clockMode) { + markup = g_markup_printf_escaped("%s:%s%s", + bgcolor, fgcolor, color, appData.logoSize && !partnerUp ? "\n" : " ", TimeString(timer)); } else { - XtSetArg(args[1], XtNbackground, timerBackgroundPixel); - XtSetArg(args[2], XtNforeground, foregroundOrWarningColor); + markup = g_markup_printf_escaped("%s ", + bgcolor, fgcolor, color); } - - XtSetValues(w, args, 3); -#endif + gtk_label_set_markup(GTK_LABEL(w), markup); + g_free(markup); } #ifdef TODO_GTK @@ -2428,24 +2383,50 @@ SetClockIcon (int color) #endif } -#ifdef TODO_GTK -void -DoInputCallback (caddr_t closure, int *source, XtInputId *xid) +#define INPUT_SOURCE_BUF_SIZE 8192 + +typedef struct { + CPKind kind; + int fd; + int lineByLine; + char *unused; + InputCallback func; + guint sid; + char buf[INPUT_SOURCE_BUF_SIZE]; + VOIDSTAR closure; +} InputSource; + +gboolean +DoInputCallback(io, cond, data) + GIOChannel *io; + GIOCondition cond; + gpointer *data; { - InputSource *is = (InputSource *) closure; + /* read input from one of the input source (for example a chess program, ICS, etc). + * and call a function that will handle the input + */ + int count; int error; char *p, *q; + /* All information (callback function, file descriptor, etc) is + * saved in an InputSource structure + */ + InputSource *is = (InputSource *) data; + if (is->lineByLine) { count = read(is->fd, is->unused, INPUT_SOURCE_BUF_SIZE - (is->unused - is->buf)); if (count <= 0) { (is->func)(is, is->closure, is->buf, count, count ? errno : 0); - return; + return True; } is->unused += count; p = is->buf; + /* break input into lines and call the callback function on each + * line + */ while (p < is->unused) { q = memchr(p, '\n', is->unused - p); if (q == NULL) break; @@ -2453,12 +2434,16 @@ DoInputCallback (caddr_t closure, int *source, XtInputId *xid) (is->func)(is, is->closure, p, q - p, 0); p = q; } + /* remember not yet used part of the buffer */ q = is->buf; while (p < is->unused) { *q++ = *p++; } is->unused = q; } else { + /* read maximum length of input buffer and send the whole buffer + * to the callback function + */ count = read(is->fd, is->buf, INPUT_SOURCE_BUF_SIZE); if (count == -1) error = errno; @@ -2466,14 +2451,17 @@ DoInputCallback (caddr_t closure, int *source, XtInputId *xid) error = 0; (is->func)(is, is->closure, is->buf, count, error); } + return True; // Must return true or the watch will be removed } -#endif -InputSourceRef -AddInputSource (ProcRef pr, int lineByLine, InputCallback func, VOIDSTAR closure) +InputSourceRef AddInputSource(pr, lineByLine, func, closure) + ProcRef pr; + int lineByLine; + InputCallback func; + VOIDSTAR closure; { -#ifdef TODO_GTK InputSource *is; + GIOChannel *channel; ChildProc *cp = (ChildProc *) pr; is = (InputSource *) calloc(1, sizeof(InputSource)); @@ -2486,31 +2474,32 @@ AddInputSource (ProcRef pr, int lineByLine, InputCallback func, VOIDSTAR closure is->kind = cp->kind; is->fd = cp->fdFrom; } - if (lineByLine) { - is->unused = is->buf; - } + if (lineByLine) + is->unused = is->buf; + else + is->unused = NULL; + + /* GTK-TODO: will this work on windows?*/ + + channel = g_io_channel_unix_new(is->fd); + g_io_channel_set_close_on_unref (channel, TRUE); + is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is); - is->xid = XtAppAddInput(appContext, is->fd, - (XtPointer) (XtInputReadMask), - (XtInputCallbackProc) DoInputCallback, - (XtPointer) is); is->closure = closure; return (InputSourceRef) is; -#else - return (InputSourceRef) 0; -#endif } + void -RemoveInputSource (InputSourceRef isr) +RemoveInputSource(isr) + InputSourceRef isr; { -#ifdef TODO_GTK InputSource *is = (InputSource *) isr; - if (is->xid == 0) return; - XtRemoveInput(is->xid); - is->xid = 0; -#endif + if (is->sid == 0) return; + g_source_remove(is->sid); + is->sid = 0; + return; } #ifndef HAVE_USLEEP diff --git a/xoptions.c b/xoptions.c index e15a9a4..d71d182 100644 --- a/xoptions.c +++ b/xoptions.c @@ -149,6 +149,9 @@ void GetWidgetTextGTK(GtkWidget *w, char **buf) GtkTextIter start; GtkTextIter end; + if (GTK_IS_ENTRY(w)) { + *buf = gtk_entry_get_text(GTK_ENTRY (w)); + } else if (GTK_IS_TEXT_BUFFER(w)) { gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(w), &start); gtk_text_buffer_get_end_iter(GTK_TEXT_BUFFER(w), &end); @@ -180,16 +183,16 @@ GetWidgetText (Option *opt, char **buf) } } -void SetSpinValue(Option *opt, int val, int n) +void SetSpinValue(Option *opt, char *val, int n) { if (opt->type == Spin) { - if (val == -1) + if (!strcmp(val, _("Unused"))) gtk_widget_set_sensitive(opt->handle, FALSE); else { gtk_widget_set_sensitive(opt->handle, TRUE); - gtk_spin_button_set_value(opt->handle, val); + gtk_spin_button_set_value(opt->handle, atoi(val)); } } else @@ -198,11 +201,13 @@ void SetSpinValue(Option *opt, int val, int n) void SetWidgetTextGTK(GtkWidget *w, char *text) { - if (!GTK_IS_TEXT_BUFFER(w)) { - printf("error: SetWidgetTextGTK arg is not a GtkTextBuffer\n"); - return; - } - gtk_text_buffer_set_text(GTK_TEXT_BUFFER(w), text, -1); + if (GTK_IS_ENTRY(w)) { + gtk_entry_set_text (GTK_ENTRY (w), text); + } else + if (GTK_IS_TEXT_BUFFER(w)) { + gtk_text_buffer_set_text(GTK_TEXT_BUFFER(w), text, -1); + } else + printf("error: SetWidgetTextGTK arg is neitherGtkEntry nor GtkTextBuffer\n"); } void @@ -213,7 +218,7 @@ SetWidgetText (Option *opt, char *buf, int n) case FileName: case PathName: case TextBox: SetWidgetTextGTK((GtkWidget *) opt->handle, buf); break; - case Spin: SetSpinValue(opt, atoi(buf), n); break; + case Spin: SetSpinValue(opt, buf, n); break; default: printf("unexpected case (%d) in GetWidgetText\n", opt->type); } @@ -246,21 +251,13 @@ SetWidgetState (Option *opt, int state) void SetWidgetLabel (Option *opt, char *buf) { -#ifdef TODO_GTK - Arg arg; - XtSetArg(arg, XtNlabel, (XtArgVal) buf); - XtSetValues(opt->handle, &arg, 1); -#endif + gtk_label_set_text(opt->handle, buf); } void SetDialogTitle (DialogClass dlg, char *title) { -#ifdef TODO_GTK - Arg args[16]; - XtSetArg(args[0], XtNtitle, title); - XtSetValues(shells[dlg], args, 1); -#endif + gtk_window_set_title(GTK_WINDOW(shells[dlg]), title); } void @@ -647,7 +644,7 @@ gboolean GenericPopDown(w, event, gdata) // I guess BrowserDlg will be abandoned, as GTK has a better browser of its own if(shellUp[BrowserDlg] && dlg != BrowserDlg || dialogError) return; // prevent closing dialog when it has an open file-browse daughter #else - if(browserUp || dialogError) return True; // prevent closing dialog when it has an open file-browse daughter + if(browserUp || dialogError && dlg != FatalDlg) return True; // prevent closing dialog when it has an open file-browse daughter #endif GtkWidget *sh = shells[dlg]; printf("popdown %d\n", dlg); @@ -676,23 +673,11 @@ int AppendText(Option *opt, char *s) void SetColor (char *colorName, Option *box) { // sets the color of a widget -#ifdef TODO_GTK - Arg args[5]; - Pixel buttonColor; - XrmValue vFrom, vTo; - if (!appData.monoMode) { - vFrom.addr = (caddr_t) colorName; - vFrom.size = strlen(colorName); - XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo); - if (vTo.addr == NULL) { - buttonColor = (Pixel) -1; - } else { - buttonColor = *(Pixel *) vTo.addr; - } - } else buttonColor = timerBackgroundPixel; - XtSetArg(args[0], XtNbackground, buttonColor);; - XtSetValues(box->handle, args, 1); -#endif + GdkColor color; + + /* set the colour of the colour button to the colour that will be used */ + gdk_color_parse( colorName, &color ); + gtk_widget_modify_bg ( GTK_WIDGET(box->handle), GTK_STATE_NORMAL, &color ); } #ifdef TODO_GTK @@ -1078,9 +1063,8 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent currentOption[n].type = EndMark; currentOption[n].target = NULL; // delimit list by callback-less end mark } + parents[dlgNr] = parent; #ifdef TODO_GTK - i = 0; - XtSetArg(args[i], XtNresizable, True); i++; shells[BoardWindow] = shellWidget; parents[dlgNr] = parent; if(dlgNr == BoardWindow) dialog = shellWidget; else @@ -1089,7 +1073,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent shells[parent], args, i); #endif dialog = gtk_dialog_new_with_buttons( title, - NULL, + GTK_WINDOW(shells[parent]), GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR | (modal ? GTK_DIALOG_MODAL : 0), GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, @@ -1138,12 +1122,18 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent w = option[i].type == Spin || option[i].type == Fractional ? 70 : option[i].max ? option[i].max : 205; if(option[i].type == FileName || option[i].type == PathName) w -= 55; - if (option[i].type==TextBox && option[i].min > 80){ + if (option[i].type==TextBox && option[i].value > 80){ textview = gtk_text_view_new(); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), GTK_WRAP_WORD); + gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), option[i].min & T_WRAP ? GTK_WRAP_WORD : GTK_WRAP_NONE); +#ifdef TODO_GTK + if(option[i].min & T_FILL) { XtSetArg(args[j], XtNautoFill, True); j++; } + if(option[i].min & T_TOP) { XtSetArg(args[j], XtNtop, XtChainTop); j++; +#endif /* add textview to scrolled window so we have vertical scroll bar */ sw = gtk_scrolled_window_new(NULL, NULL); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); + gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), + option[i].min & T_HSCRL ? GTK_POLICY_ALWAYS : GTK_POLICY_AUTOMATIC, + option[i].min & T_VSCRL ? GTK_POLICY_ALWAYS : GTK_POLICY_NEVER); gtk_container_add(GTK_CONTAINER(sw), textview); gtk_widget_set_size_request(GTK_WIDGET(sw), w, -1); @@ -1214,9 +1204,14 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent option[i].handle = (void *)checkbutton; break; case Label: - label = gtk_label_new(option[i].name); + option[i].handle = (void *) (label = gtk_label_new(option[i].name)); /* Left Justify */ gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); + if(option[i].min & BORDER) { + GtkWidget *frame = gtk_frame_new(NULL); + gtk_container_add(GTK_CONTAINER(frame), label); + label = frame; + } gtk_table_attach_defaults(GTK_TABLE(table), label, left, left+3, top, top+1); break; case SaveButton: @@ -1262,14 +1257,14 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent for(j=0;;j++) { if ( ((char **) option[i].textValue)[j] == NULL) break; - gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), ((char **) option[i].textValue)[j]); + gtk_combo_box_append_text(GTK_COMBO_BOX(combobox), ((char **) option[i].choice)[j]); } if(currentCps) option[i].choice = (char**) option[i].textValue; - else { + else { for(j=0; option[i].choice[j]; j++) { - if(*(char**)option[i].target && !strcmp(*(char**)option[i].target, option[i].choice[j])) break; + if(*(char**)option[i].target && !strcmp(*(char**)option[i].target, ((char**)(option[i].textValue))[j])) break; } /* If choice is NULL set to first */ if (option[i].choice[j] == NULL) @@ -1389,7 +1384,7 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent if(option[i].target) ((ButtonCallback*)option[i].target)(boxStart); // callback that can make sizing decisions break; case Break: - top = height; // force next option to start in a new column + if(option[i].min & SAME_ROW) top = height; // force next option to start in a new column break; default: printf("GenericPopUp: unexpected case in switch. i=%d type=%d name=%s.\n", i, option[i].type, option[i].name); @@ -1415,6 +1410,9 @@ GenericPopUp (Option *option, char *title, DialogClass dlgNr, DialogClass parent g_signal_connect (dialog, "delete-event", G_CALLBACK (GenericPopDown), (gpointer)(intptr_t) dlgNr); + g_signal_connect (dialog, "destroy-event", + G_CALLBACK (GenericPopDown), + (gpointer)(intptr_t) dlgNr); shellUp[dlgNr]++; #ifdef TODO_GTK -- 1.7.0.4