Transfer more gtk-xt code, and add some new
authorH.G. Muller <h.g.muller@hccnet.nl>
Mon, 15 Oct 2012 20:17:50 +0000 (22:17 +0200)
committerH.G. Muller <h.g.muller@hccnet.nl>
Tue, 6 Nov 2012 13:13:47 +0000 (14:13 +0100)
Add input-source handling
Graft color picker (<Enter> 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
xoptions.c

index 6ed7bfc..f1c5425 100644 (file)
--- 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 <X11/xpm.h>
-#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("<span size=\"xx-large\" weight=\"heavy\" background=\"%s\" foreground=\"%s\">%s:%s%s</span>",
+                                        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("<span size=\"xx-large\" weight=\"heavy\" background=\"%s\" foreground=\"%s\">%s  </span>",
+                                        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
index e15a9a4..d71d182 100644 (file)
@@ -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