Connect CommentClick handler
[xboard.git] / xboard.c
index 719585c..4a4cdad 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -61,6 +61,9 @@
 #include <sys/stat.h>
 #include <pwd.h>
 #include <math.h>
+#include <cairo/cairo.h>
+#include <cairo/cairo-xlib.h>
+#include <gtk/gtk.h>
 
 #if !OMIT_SOCKETS
 # if HAVE_SYS_SOCKET_H
@@ -146,69 +149,25 @@ extern char *getenv();
 #include <locale.h>
 #endif
 
-#include <X11/Intrinsic.h>
-#include <X11/StringDefs.h>
-#include <X11/Shell.h>
-#include <X11/cursorfont.h>
-#include <X11/Xatom.h>
-#include <X11/Xmu/Atoms.h>
-#if USE_XAW3D
-#include <X11/Xaw3d/Dialog.h>
-#include <X11/Xaw3d/Form.h>
-#include <X11/Xaw3d/List.h>
-#include <X11/Xaw3d/Label.h>
-#include <X11/Xaw3d/SimpleMenu.h>
-#include <X11/Xaw3d/SmeBSB.h>
-#include <X11/Xaw3d/SmeLine.h>
-#include <X11/Xaw3d/Box.h>
-#include <X11/Xaw3d/MenuButton.h>
-#include <X11/Xaw3d/Text.h>
-#include <X11/Xaw3d/AsciiText.h>
-#else
-#include <X11/Xaw/Dialog.h>
-#include <X11/Xaw/Form.h>
-#include <X11/Xaw/List.h>
-#include <X11/Xaw/Label.h>
-#include <X11/Xaw/SimpleMenu.h>
-#include <X11/Xaw/SmeBSB.h>
-#include <X11/Xaw/SmeLine.h>
-#include <X11/Xaw/Box.h>
-#include <X11/Xaw/MenuButton.h>
-#include <X11/Xaw/Text.h>
-#include <X11/Xaw/AsciiText.h>
-#endif
-
 // [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>
-#include "pixmaps/pixmaps.h"
-#define IMAGE_EXT "xpm"
-#else
-#define IMAGE_EXT "xim"
-#include "bitmaps/bitmaps.h"
-#endif
-
-#include "bitmaps/icon_white.bm"
-#include "bitmaps/icon_black.bm"
-#include "bitmaps/checkmark.bm"
-
 #include "frontend.h"
 #include "backend.h"
 #include "backendz.h"
 #include "moves.h"
 #include "xboard.h"
+#include "xboard2.h"
 #include "childio.h"
 #include "xgamelist.h"
 #include "xhistory.h"
-#include "xedittags.h"
 #include "menus.h"
 #include "board.h"
 #include "dialogs.h"
 #include "engineoutput.h"
 #include "usystem.h"
 #include "gettext.h"
+#include "draw.h"
 
 
 #ifdef __EMX__
@@ -230,24 +189,15 @@ int main P((int argc, char **argv));
 RETSIGTYPE CmailSigHandler P((int sig));
 RETSIGTYPE IntSigHandler P((int sig));
 RETSIGTYPE TermSizeSigHandler P((int sig));
-static void CreateGCs P((int redo));
-static void CreateAnyPieces P((void));
-void CreateXIMPieces P((void));
-void CreateXPMPieces P((void));
-void CreateXPMBoard P((char *s, int n));
-void CreatePieces P((void));
-Widget CreateMenuBar P((Menu *mb, int boardWidth));
 #if ENABLE_NLS
 char *InsertPxlSize P((char *pattern, int targetPxlSize));
 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 CreateGrid P((void));
-void EventProc P((Widget widget, caddr_t unused, XEvent *event));
 void DelayedDrag P((void));
+void ICSInputBoxPopUp P((void));
+#ifdef TODO_GTK
 static void MoveTypeInProc P((Widget widget, caddr_t unused, XEvent *event));
 void HandlePV P((Widget w, XEvent * event,
                     String * params, Cardinal * nParams));
@@ -255,9 +205,6 @@ void DrawPositionProc P((Widget w, XEvent *event,
                     String *prms, Cardinal *nprms));
 void CommentClick P((Widget w, XEvent * event,
                   String * params, Cardinal * nParams));
-void ICSInputBoxPopUp P((void));
-void FileNamePopUp P((char *label, char *def, char *filter,
-                     FileProc proc, char *openMode));
 void SelectCommand P((Widget w, XtPointer client_data, XtPointer call_data));
 void KeyBindingProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void QuitWrapper P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
@@ -266,16 +213,16 @@ static void UpKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms)
 static void DownKeyProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void TempBackwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void TempForwardProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
-Boolean TempBackwardActive = False;
 void ManInner P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
+void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams));
+#endif
+Boolean TempBackwardActive = False;
 void DisplayMove P((int moveNumber));
 void ICSInitScript P((void));
-void SelectMove P((Widget w, XEvent * event, String * params, Cardinal * nParams));
 void update_ics_width P(());
-int get_term_width P(());
 int CopyMemoProc P(());
-void SetupDropMenu P((void));
 
+#ifdef TODO_GTK
 /*
 * XBoard depends on Xt R4 or higher
 */
@@ -284,16 +231,9 @@ int xtVersion = XtSpecificationRelease;
 int xScreen;
 Display *xDisplay;
 Window xBoardWindow;
-Pixel lightSquareColor, darkSquareColor, whitePieceColor, blackPieceColor,
-  highlightSquareColor, premoveHighlightColor, dialogColor, buttonColor;
-Pixel lowTimeWarningColor;
-GC lightSquareGC, darkSquareGC, lineGC, wdPieceGC, wlPieceGC,
-  bdPieceGC, blPieceGC, wbPieceGC, bwPieceGC, coordGC, highlineGC,
-  prelineGC, countGC;
+Pixel lowTimeWarningColor, dialogColor, buttonColor; // used in widgets
 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
 Widget shellWidget, formWidget, boardWidget, titleWidget, dropMenu, menuBarWidget;
-Option *optList; // contains all widgets of main window
-XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
 #if ENABLE_NLS
 XFontSet fontSet, clockFontSet;
 #else
@@ -303,14 +243,16 @@ XFontStruct *clockFontStruct;
 Font coordFontID, countFontID;
 XFontStruct *coordFontStruct, *countFontStruct;
 XtAppContext appContext;
+#else
+void *shellWidget, *formWidget, *boardWidget, *titleWidget, *dropMenu, *menuBarWidget;
+void *appContext;
+GtkWidget       *mainwindow;
+#endif
+Option *optList; // contains all widgets of main window
 char *layoutName;
 
-FileProc fileProc;
-char *fileOpenMode;
 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
 
-Position commentX = -1, commentY = -1;
-Dimension commentW, commentH;
 typedef unsigned int BoardSize;
 BoardSize boardSize;
 Boolean chessProgram;
@@ -320,9 +262,11 @@ int smallLayout = 0, tinyLayout = 0,
   marginW, marginH, // [HGM] for run-time resizing
   fromX = -1, fromY = -1, toX, toY, commentUp = False,
   errorExitStatus = -1, defaultLineGap;
+#ifdef TODO_GTK
 Dimension textHeight;
 Pixel timerForegroundPixel, timerBackgroundPixel;
 Pixel buttonForegroundPixel, buttonBackgroundPixel;
+#endif
 char *chessDir, *programName, *programVersion;
 Boolean alwaysOnTop = False;
 char *icsTextMenuString;
@@ -339,31 +283,6 @@ WindowPlacement wpEngineOutput;
 WindowPlacement wpGameList;
 WindowPlacement wpTags;
 
-
-#define SOLID 0
-#define OUTLINE 1
-Pixmap pieceBitmap[2][(int)BlackPawn];
-Pixmap pieceBitmap2[2][(int)BlackPawn+4];       /* [HGM] pieces */
-Pixmap xpmPieceBitmap[4][(int)BlackPawn];      /* LL, LD, DL, DD actually used*/
-Pixmap xpmPieceBitmap2[4][(int)BlackPawn+4];   /* LL, LD, DL, DD set to select from */
-Pixmap xpmLightSquare, xpmDarkSquare, xpmJailSquare;
-Pixmap xpmBoardBitmap[2];
-int useImages, useImageSqs, useTexture, textureW[2], textureH[2];
-XImage *ximPieceBitmap[4][(int)BlackPawn+4];   /* LL, LD, DL, DD */
-Pixmap ximMaskPm[(int)BlackPawn];               /* clipmasks, used for XIM pieces */
-Pixmap ximMaskPm2[(int)BlackPawn+4];            /* clipmasks, used for XIM pieces */
-XImage *ximLightSquare, *ximDarkSquare;
-XImage *xim_Cross;
-
-#define pieceToSolid(piece) &pieceBitmap[SOLID][(piece) % (int)BlackPawn]
-#define pieceToOutline(piece) &pieceBitmap[OUTLINE][(piece) % (int)BlackPawn]
-
-#define White(piece) ((int)(piece) < (int)BlackPawn)
-
-/* Bitmaps for use as masks when drawing XPM pieces.
-   Need one for each black and white piece.            */
-static Pixmap xpmMask[BlackKing + 1];
-
 /* 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.  */
@@ -384,6 +303,7 @@ DropMenuEnables dmEnables[] = {
     { 'Q', "Queen" }
 };
 
+#ifdef TODO_GTK
 Arg shellArgs[] = {
     { XtNwidth, 0 },
     { XtNheight, 0 },
@@ -429,6 +349,7 @@ XtActionsRec boardActions[] = {
     { "WheelProc", WheelProc },
     { "TabProc", TabProc },
 };
+#endif
 
 char globalTranslations[] =
   ":<Key>F9: MenuItem(Actions.Resign) \n \
@@ -509,11 +430,12 @@ char ICSInputTranslations[] =
 //             as the widget is destroyed before the up-click can call extend-end
 char commentTranslations[] = "<Btn3Down>: extend-end() select-start() CommentClick() \n";
 
+#ifdef TODO_GTK
 String xboardResources[] = {
     "*Error*translations: #override\\n <Key>Return: ErrorPopDown()",
     NULL
   };
-
+#endif
 
 /* Max possible square size */
 #define MAXSQSIZE 256
@@ -640,6 +562,7 @@ Warning: No DIR structure found on this system --\n\
 #endif /* HAVE_DIR_STRUCT */
 
 
+#ifdef TODO_GTK
 /* Arrange to catch delete-window events */
 Atom wm_delete_window;
 void
@@ -650,15 +573,12 @@ CatchDeleteWindow (Widget w, String procname)
   snprintf(buf, sizeof(buf), "<Message>WM_PROTOCOLS: %s() \n", procname);
   XtAugmentTranslations(w, XtParseTranslationTable(buf));
 }
+#endif
 
 void
 BoardToTop ()
 {
-  Arg args[16];
-  XtSetArg(args[0], XtNiconic, False);
-  XtSetValues(shellWidget, args, 1);
-
-  XtPopup(shellWidget, XtGrabNone); /* Raise if lowered  */
+  gtk_window_present(GTK_WINDOW(mainwindow));
 }
 
 //---------------------------------------------------------------------------------------------------------
@@ -836,6 +756,7 @@ ParseCommPortSettings (char *s)
 
 int frameX, frameY;
 
+#ifdef TODO_GTK
 void
 GetActualPlacement (Widget wg, WindowPlacement *wp)
 {
@@ -854,11 +775,13 @@ GetActualPlacement (Widget wg, WindowPlacement *wp)
   wp->width = winAt.width;
   frameX = winAt.x; frameY = winAt.y; // remember to decide if windows touch
 }
+#endif
 
 void
 GetWindowCoords ()
 { // wrapper to shield use of window handles from back-end (make addressible by number?)
   // In XBoard this will have to wait until awareness of window parameters is implemented
+#ifdef TODO_GTK
   GetActualPlacement(shellWidget, &wpMain);
   if(shellUp[EngOutDlg]) GetActualPlacement(shells[EngOutDlg], &wpEngineOutput);
   if(shellUp[HistoryDlg]) GetActualPlacement(shells[HistoryDlg], &wpMoveHistory);
@@ -866,6 +789,7 @@ GetWindowCoords ()
   if(shellUp[GameListDlg]) GetActualPlacement(shells[GameListDlg], &wpGameList);
   if(shellUp[CommentDlg]) GetActualPlacement(shells[CommentDlg], &wpComment);
   if(shellUp[TagsDlg]) GetActualPlacement(shells[TagsDlg], &wpTags);
+#endif
 }
 
 void
@@ -882,17 +806,11 @@ EnsureOnScreen (int *x, int *y, int minX, int minY)
 int
 MainWindowUp ()
 { // [HGM] args: allows testing if main window is realized from back-end
+#ifdef TODO_GTK
   return xBoardWindow != 0;
-}
-
-void SwitchWindow()
-{
-    extern Option dualOptions[];
-    static Window dual;
-    Window tmp = xBoardWindow;
-    if(!dual) dual = XtWindow(dualOptions[3].handle); // must be first call
-    xBoardWindow = dual; // swap them
-    dual = tmp;
+#else
+  return 0;
+#endif
 }
 
 void
@@ -923,124 +841,23 @@ ConvertToLine (int argc, char **argv)
 
 //--------------------------------------------------------------------------------------------
 
-#define BoardSize int
 void
-InitDrawingSizes (BoardSize boardSize, int flags)
-{   // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
-    Dimension boardWidth, boardHeight, w, h;
-    int i;
-    static Dimension oldWidth, oldHeight;
-    static VariantClass oldVariant;
-    static int oldMono = -1, oldTwoBoards = 0;
-
-    if(!formWidget) return;
-
-    if(oldTwoBoards && !twoBoards) PopDown(DummyDlg);
-    oldTwoBoards = twoBoards;
-
-    if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
-    boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
-    boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
-
-  if(boardWidth != oldWidth || boardHeight != oldHeight) { // do resizing stuff only if size actually changed
-
-    oldWidth = boardWidth; oldHeight = boardHeight;
-    CreateGrid();
-
-    /*
-     * Inhibit shell resizing.
-     */
-    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW ;
-    shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
+ResizeBoardWindow (int w, int h, int inhibit)
+{
+#ifdef TODO_GTK
+    w += marginW + 1; // [HGM] not sure why the +1 is (sometimes) needed...
+    h += marginH;
+    shellArgs[0].value = w;
+    shellArgs[1].value = h;
     shellArgs[4].value = shellArgs[2].value = w;
     shellArgs[5].value = shellArgs[3].value = h;
-    XtSetValues(shellWidget, &shellArgs[0], 6);
+    XtSetValues(shellWidget, &shellArgs[0], inhibit ? 6 : 2);
 
     XSync(xDisplay, False);
-    DelayedDrag();
-  }
-
-    // [HGM] pieces: tailor piece bitmaps to needs of specific variant
-    // (only for xpm)
-
-  if(gameInfo.variant != oldVariant) { // and only if variant changed
-
-    if(useImages) {
-      for(i=0; i<4; i++) {
-       int p;
-       for(p=0; p<=(int)WhiteKing; p++)
-          xpmPieceBitmap[i][p] = xpmPieceBitmap2[i][p]; // defaults
-       if(gameInfo.variant == VariantShogi) {
-          xpmPieceBitmap[i][(int)WhiteCannon] = xpmPieceBitmap2[i][(int)WhiteKing+1];
-          xpmPieceBitmap[i][(int)WhiteNightrider] = xpmPieceBitmap2[i][(int)WhiteKing+2];
-          xpmPieceBitmap[i][(int)WhiteSilver] = xpmPieceBitmap2[i][(int)WhiteKing+3];
-          xpmPieceBitmap[i][(int)WhiteGrasshopper] = xpmPieceBitmap2[i][(int)WhiteKing+4];
-          xpmPieceBitmap[i][(int)WhiteQueen] = xpmPieceBitmap2[i][(int)WhiteLance];
-       }
-#ifdef GOTHIC
-       if(gameInfo.variant == VariantGothic) {
-          xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteSilver];
-       }
-#endif
-       if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
-          xpmPieceBitmap[i][(int)WhiteAngel]    = xpmPieceBitmap2[i][(int)WhiteFalcon];
-          xpmPieceBitmap[i][(int)WhiteMarshall] = xpmPieceBitmap2[i][(int)WhiteAlfil];
-       }
-#if !HAVE_LIBXPM
-       // [HGM] why are thee ximMasks used at all? the ximPieceBitmaps seem to be never used!
-       for(p=0; p<=(int)WhiteKing; p++)
-          ximMaskPm[p] = ximMaskPm2[p]; // defaults
-       if(gameInfo.variant == VariantShogi) {
-          ximMaskPm[(int)WhiteCannon] = ximMaskPm2[(int)WhiteKing+1];
-          ximMaskPm[(int)WhiteNightrider] = ximMaskPm2[(int)WhiteKing+2];
-          ximMaskPm[(int)WhiteSilver] = ximMaskPm2[(int)WhiteKing+3];
-          ximMaskPm[(int)WhiteGrasshopper] = ximMaskPm2[(int)WhiteKing+4];
-          ximMaskPm[(int)WhiteQueen] = ximMaskPm2[(int)WhiteLance];
-       }
-#ifdef GOTHIC
-       if(gameInfo.variant == VariantGothic) {
-           ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteSilver];
-       }
 #endif
-       if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
-           ximMaskPm[(int)WhiteAngel]    = ximMaskPm2[(int)WhiteFalcon];
-           ximMaskPm[(int)WhiteMarshall] = ximMaskPm2[(int)WhiteAlfil];
-       }
-#endif
-      }
-    } else {
-      for(i=0; i<2; i++) {
-       int p;
-       for(p=0; p<=(int)WhiteKing; p++)
-          pieceBitmap[i][p] = pieceBitmap2[i][p]; // defaults
-       if(gameInfo.variant == VariantShogi) {
-          pieceBitmap[i][(int)WhiteCannon] = pieceBitmap2[i][(int)WhiteKing+1];
-          pieceBitmap[i][(int)WhiteNightrider] = pieceBitmap2[i][(int)WhiteKing+2];
-          pieceBitmap[i][(int)WhiteSilver] = pieceBitmap2[i][(int)WhiteKing+3];
-          pieceBitmap[i][(int)WhiteGrasshopper] = pieceBitmap2[i][(int)WhiteKing+4];
-          pieceBitmap[i][(int)WhiteQueen] = pieceBitmap2[i][(int)WhiteLance];
-       }
-#ifdef GOTHIC
-       if(gameInfo.variant == VariantGothic) {
-          pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteSilver];
-       }
-#endif
-       if(gameInfo.variant == VariantSChess && (squareSize == 49 || squareSize == 72)) {
-          pieceBitmap[i][(int)WhiteAngel]    = pieceBitmap2[i][(int)WhiteFalcon];
-          pieceBitmap[i][(int)WhiteMarshall] = pieceBitmap2[i][(int)WhiteAlfil];
-       }
-      }
-    }
-    oldMono = -10; // kludge to force recreation of animation masks
-    oldVariant = gameInfo.variant;
-  }
-#if HAVE_LIBXPM
-  if(appData.monoMode != oldMono)
-    CreateAnimVars();
-#endif
-  oldMono = appData.monoMode;
 }
 
+#ifdef TODO_GTK
 static int
 MakeOneColor (char *name, Pixel *color)
 {
@@ -1058,58 +875,27 @@ MakeOneColor (char *name, Pixel *color)
     }
     return False;
 }
+#endif
 
-static int
+int
 MakeColors ()
 {   // [HGM] taken out of main(), so it can be called from BoardOptions dialog
     int forceMono = False;
 
-    forceMono |= MakeOneColor(appData.lightSquareColor, &lightSquareColor);
-    forceMono |= MakeOneColor(appData.darkSquareColor, &darkSquareColor);
-    forceMono |= MakeOneColor(appData.whitePieceColor, &whitePieceColor);
-    forceMono |= MakeOneColor(appData.blackPieceColor, &blackPieceColor);
-    forceMono |= MakeOneColor(appData.highlightSquareColor, &highlightSquareColor);
-    forceMono |= MakeOneColor(appData.premoveHighlightColor, &premoveHighlightColor);
+#ifdef TODO_GTK
     if (appData.lowTimeWarning)
        forceMono |= MakeOneColor(appData.lowTimeWarningColor, &lowTimeWarningColor);
     if(appData.dialogColor[0]) MakeOneColor(appData.dialogColor, &dialogColor);
     if(appData.buttonColor[0]) MakeOneColor(appData.buttonColor, &buttonColor);
-
-    return forceMono;
-}
-
-static void
-CreateAnyPieces ()
-{   // [HGM] taken out of main
-#if HAVE_LIBXPM
-    if (appData.monoMode && // [HGM] no sense to go on to certain doom
-       (appData.bitmapDirectory == NULL || appData.bitmapDirectory[0] == NULLCHAR))
-           appData.bitmapDirectory = strdup(DEF_BITMAP_DIR);
-
-    if (appData.bitmapDirectory[0] != NULLCHAR) {
-      CreatePieces();
-    } else {
-      CreateXPMPieces();
-      CreateXPMBoard(appData.liteBackTextureFile, 1);
-      CreateXPMBoard(appData.darkBackTextureFile, 0);
-    }
-#else
-    CreateXIMPieces();
-    /* Create regular pieces */
-    if (!useImages) CreatePieces();
 #endif
-}
 
-void
-InitDrawingParams ()
-{
-    MakeColors(); CreateGCs(True);
-    CreateAnyPieces();
+    return forceMono;
 }
 
 void
 InitializeFonts (int clockFontPxlSize, int coordFontPxlSize, int fontPxlSize)
 {   // detervtomine what fonts to use, and create them
+#ifdef TODO_GTK
     XrmValue vTo;
     XrmDatabase xdb;
 
@@ -1160,17 +946,80 @@ InitializeFonts (int clockFontPxlSize, int coordFontPxlSize, int fontPxlSize)
 #else
     XrmPutStringResource(&xdb, "*font", appData.font);
 #endif
+#endif
+}
+
+char *
+PrintArg (ArgType t)
+{
+  char *p="";
+  switch(t) {
+    case ArgZ:
+    case ArgInt:      p = " N"; break;
+    case ArgString:   p = " STR"; break;
+    case ArgBoolean:  p = " TF"; break;
+    case ArgSettingsFilename:
+    case ArgFilename: p = " FILE"; break;
+    case ArgX:        p = " Nx"; break;
+    case ArgY:        p = " Ny"; break;
+    case ArgAttribs:  p = " TEXTCOL"; break;
+    case ArgColor:    p = " COL"; break;
+    case ArgFont:     p = " FONT"; break;
+    case ArgBoardSize: p = " SIZE"; break;
+    case ArgFloat: p = " FLOAT"; break;
+    case ArgTrue:
+    case ArgFalse:
+    case ArgTwo:
+    case ArgNone:
+    case ArgCommSettings:
+      break;
+  }
+  return p;
+}
+
+void
+PrintOptions ()
+{
+  char buf[MSG_SIZ];
+  int len=0;
+  ArgDescriptor *q, *p = argDescriptors+5;
+  printf("\nXBoard accepts the following options:\n"
+         "(N = integer, TF = true or false, STR = text string, FILE = filename,\n"
+         " Nx, Ny = relative coordinates, COL = color, FONT = X-font spec,\n"
+         " SIZE = board-size spec(s)\n"
+         " Within parentheses are short forms, or options to set to true or false.\n"
+         " Persistent options (saved in the settings file) are marked with *)\n\n");
+  while(p->argName) {
+    if(p->argType == ArgCommSettings) { p++; continue; } // XBoard has no comm port
+    snprintf(buf+len, MSG_SIZ, "-%s%s", p->argName, PrintArg(p->argType));
+    if(p->save) strcat(buf+len, "*");
+    for(q=p+1; q->argLoc == p->argLoc; q++) {
+      if(q->argName[0] == '-') continue;
+      strcat(buf+len, q == p+1 ? " (" : " ");
+      sprintf(buf+strlen(buf), "-%s%s", q->argName, PrintArg(q->argType));
+    }
+    if(q != p+1) strcat(buf+len, ")");
+    len = strlen(buf);
+    if(len > 39) len = 0, printf("%s\n", buf); else while(len < 39) buf[len++] = ' ';
+    p = q;
+  }
+  if(len) buf[len] = NULLCHAR, printf("%s\n", buf);
 }
 
 int
 main (int argc, char **argv)
 {
     int i, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
+#ifdef TODO_GTK
     XSetWindowAttributes window_attributes;
     Arg args[16];
     Dimension boardWidth, boardHeight, w, h;
+#else
+#endif
+    int boardWidth, boardHeight, w, h;
     char *p;
     int forceMono = False;
+    GError *gtkerror=NULL;
 
     srandom(time(0)); // [HGM] book: make random truly random
 
@@ -1183,6 +1032,14 @@ main (int argc, char **argv)
        exit(0);
     }
 
+    if(argc > 1 && !strcmp(argv[1], "--help" )) {
+       PrintOptions();
+       exit(0);
+    }
+
+    /* set up GTK */
+    gtk_init (&argc, &argv);
+
     programName = strrchr(argv[0], '/');
     if (programName == NULL)
       programName = argv[0];
@@ -1190,10 +1047,9 @@ main (int argc, char **argv)
       programName++;
 
 #ifdef ENABLE_NLS
-    XtSetLanguageProc(NULL, NULL, NULL);
-    if (appData.debugMode) {
-      fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
-    }
+//    if (appData.debugMode) {
+//      fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
+//    }
 
     bindtextdomain(PACKAGE, LOCALEDIR);
     textdomain(PACKAGE);
@@ -1240,6 +1096,12 @@ main (int argc, char **argv)
         setbuf(debugFP, NULL);
     }
 
+#if ENABLE_NLS
+    if (appData.debugMode) {
+      fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
+    }
+#endif
+
     /* [HGM,HR] make sure board size is acceptable */
     if(appData.NrFiles > BOARD_FILES ||
        appData.NrRanks > BOARD_RANKS   )
@@ -1254,6 +1116,17 @@ main (int argc, char **argv)
        gameInfo.variant = StringToVariant(appData.variant);
        InitPosition(FALSE);
 
+#ifdef TODO_GTK
+    /* GTK */
+    builder = gtk_builder_new();
+    filename = get_glade_filename ("mainboard.glade");
+    if(! gtk_builder_add_from_file (builder, filename, &gtkerror) )
+      {
+      if(gtkerror)
+        printf ("Error: %d %s\n",gtkerror->code,gtkerror->message);
+      }
+    mainwindow = GTK_WIDGET(gtk_builder_get_object (builder, "mainwindow"));
+
     shellWidget =
       XtAppInitialize(&appContext, "XBoard", shellOptions,
                      XtNumber(shellOptions),
@@ -1266,6 +1139,7 @@ main (int argc, char **argv)
     xDisplay = XtDisplay(shellWidget);
     xScreen = DefaultScreen(xDisplay);
     wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
+#endif
 
     /*
      * determine size, based on supplied or remembered -size, or screen size
@@ -1302,10 +1176,20 @@ main (int argc, char **argv)
     } else {
         SizeDefaults *szd = sizeDefaults;
         if (*appData.boardSize == NULLCHAR) {
+#ifdef TODO_GTK
            while (DisplayWidth(xDisplay, xScreen) < szd->minScreenSize ||
                   DisplayHeight(xDisplay, xScreen) < szd->minScreenSize) {
              szd++;
            }
+#else
+            GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(mainwindow));
+            guint screenwidth = gdk_screen_get_width(screen);
+            guint screenheight = gdk_screen_get_height(screen);
+           while (screenwidth < szd->minScreenSize ||
+                  screenheight < szd->minScreenSize) {
+             szd++;
+           }
+#endif
            if (szd->name == NULL) szd--;
            appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
        } else {
@@ -1327,24 +1211,6 @@ main (int argc, char **argv)
        // [HGM] font: use defaults from settings file if available and not overruled
     }
 
-    /* Now, using squareSize as a hint, find a good XPM/XIM set size */
-    if (strlen(appData.pixmapDirectory) > 0) {
-       p = ExpandPathName(appData.pixmapDirectory);
-       if (!p) {
-           fprintf(stderr, _("Error expanding path name \"%s\"\n"),
-                  appData.pixmapDirectory);
-           exit(1);
-       }
-       if (appData.debugMode) {
-          fprintf(stderr, _("\
-XBoard square size (hint): %d\n\
-%s fulldir:%s:\n"), squareSize, IMAGE_EXT, p);
-       }
-       squareSize = xpm_closest_to(p, squareSize, IMAGE_EXT);
-       if (appData.debugMode) {
-           fprintf(stderr, _("Closest %s size: %d\n"), IMAGE_EXT, squareSize);
-       }
-    }
     defaultLineGap = lineGap;
     if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
 
@@ -1355,14 +1221,18 @@ XBoard square size (hint): %d\n\
     /*
      * Determine what fonts to use.
      */
+#ifdef TODO_GTK
     InitializeFonts(clockFontPxlSize, coordFontPxlSize, fontPxlSize);
+#endif
 
     /*
      * Detect if there are not enough colors available and adapt.
      */
+#ifdef TODO_GTK
     if (DefaultDepth(xDisplay, xScreen) <= 2) {
       appData.monoMode = True;
     }
+#endif
 
     forceMono = MakeColors();
 
@@ -1372,15 +1242,11 @@ XBoard square size (hint): %d\n\
        appData.monoMode = True;
     }
 
-    if (appData.monoMode && appData.debugMode) {
-       fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
-               (unsigned long) XWhitePixel(xDisplay, xScreen),
-               (unsigned long) XBlackPixel(xDisplay, xScreen));
-    }
-
     ParseIcsTextColors();
 
+#ifdef TODO_GTK
     XtAppAddActions(appContext, boardActions, XtNumber(boardActions));
+#endif
 
     /*
      * widget hierarchy
@@ -1394,15 +1260,22 @@ XBoard square size (hint): %d\n\
     }
 
     optList = BoardPopUp(squareSize, lineGap, (void*)
+#ifdef TODO_GTK
 #if ENABLE_NLS
                                                &clockFontSet);
 #else
-                                               &clockFonStruct);
+                                               clockFontStruct);
+#endif
+#else
+0);
 #endif
+    InitDrawingHandle(optList + W_BOARD);
+    currBoard        = &optList[W_BOARD];
     boardWidget      = optList[W_BOARD].handle;
     menuBarWidget    = optList[W_MENU].handle;
     dropMenu         = optList[W_DROP].handle;
     titleWidget = optList[optList[W_TITLE].type != -1 ? W_TITLE : W_SMALL].handle;
+#ifdef TODO_GTK
     formWidget  = XtParent(boardWidget);
     XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
     XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
@@ -1412,23 +1285,21 @@ XBoard square size (hint): %d\n\
       XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
       XtGetValues(optList[W_PAUSE].handle, args, 2);
     }
-    AppendEnginesToMenu(appData.recentEngineList);
+#endif
 
+#ifdef TODO_GTK
     xBoardWindow = XtWindow(boardWidget);
+#endif
 
     // [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.
-     */
-    ReadBitmap(&xMarkPixmap, "checkmark.bm",
-              checkmark_bits, checkmark_width, checkmark_height);
     InitMenuMarkers();
 
     /*
      * Create an icon.
      */
+#ifdef TODO_GTK
     ReadBitmap(&wIconPixmap, "icon_white.bm",
               icon_white_bits, icon_white_width, icon_white_height);
     ReadBitmap(&bIconPixmap, "icon_black.bm",
@@ -1437,35 +1308,49 @@ XBoard square size (hint): %d\n\
     i = 0;
     XtSetArg(args[i], XtNiconPixmap, iconPixmap);  i++;
     XtSetValues(shellWidget, args, i);
+#endif
 
     /*
      * Create a cursor for the board widget.
      */
+#ifdef TODO_GTK
     window_attributes.cursor = XCreateFontCursor(xDisplay, XC_hand2);
     XChangeWindowAttributes(xDisplay, xBoardWindow,
                            CWCursor, &window_attributes);
+#endif
 
     /*
      * Inhibit shell resizing.
      */
+#ifdef TODO_GTK
     shellArgs[0].value = (XtArgVal) &w;
     shellArgs[1].value = (XtArgVal) &h;
     XtGetValues(shellWidget, shellArgs, 2);
     shellArgs[4].value = shellArgs[2].value = w;
     shellArgs[5].value = shellArgs[3].value = h;
-    XtSetValues(shellWidget, &shellArgs[2], 4);
+//    XtSetValues(shellWidget, &shellArgs[2], 4);
+#endif
     marginW =  w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
     marginH =  h - boardHeight;
 
+#ifdef TODO_GTK
     CatchDeleteWindow(shellWidget, "QuitProc");
+#endif
 
-    CreateGCs(False);
-    CreateGrid();
     CreateAnyPieces();
+    CreateGrid();
+
+    if(appData.logoSize)
+    {   // locate and read user logo
+       char buf[MSG_SIZ];
+       snprintf(buf, MSG_SIZ, "%s/%s.png", appData.logoDir, UserName());
+       ASSIGN(userLogo, buf);
+    }
 
     if (appData.animate || appData.animateDragging)
       CreateAnimVars();
 
+#ifdef TODO_GTK
     XtAugmentTranslations(formWidget,
                          XtParseTranslationTable(globalTranslations));
 
@@ -1473,6 +1358,7 @@ XBoard square size (hint): %d\n\
                      (XtEventHandler) MoveTypeInProc, NULL);
     XtAddEventHandler(shellWidget, StructureNotifyMask, False,
                      (XtEventHandler) EventProc, NULL);
+#endif
 
     /* [AS] Restore layout */
     if( wpMoveHistory.visible ) {
@@ -1510,10 +1396,18 @@ XBoard square size (hint): %d\n\
 
     gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
     InitPosition(TRUE);
+    UpdateLogos(TRUE);
 //    XtSetKeyboardFocus(shellWidget, formWidget);
+#ifdef TODO_GTK
     XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
+#endif
+
+    /* check for GTK events and process them */
+//    gtk_main();
+while(1) {
+gtk_main_iteration();
+}
 
-    XtAppMainLoop(appContext);
     if (appData.debugMode) fclose(debugFP); // [DM] debug
     return 0;
 }
@@ -1607,6 +1501,7 @@ InsertPxlSize (char *pattern, int targetPxlSize)
     return base_fnt_lst;
 }
 
+#ifdef TODO_GTK
 XFontSet
 CreateFontSet (char *base_fnt_lst)
 {
@@ -1641,6 +1536,7 @@ CreateFontSet (char *base_fnt_lst)
     }
     return fntSet;
 }
+#endif
 #else // not ENABLE_NLS
 /*
  * Find a font that matches "pattern" that is as close as
@@ -1657,6 +1553,7 @@ FindFont (char *pattern, int targetPxlSize)
     char **fonts, *p, *best, *scalable, *scalableTail;
     int i, j, nfonts, minerr, err, pxlSize;
 
+#ifdef TODO_GTK
     fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
     if (nfonts < 1) {
        fprintf(stderr, _("%s: no fonts match pattern %s\n"),
@@ -1705,606 +1602,75 @@ FindFont (char *pattern, int targetPxlSize)
                pattern, targetPxlSize, p);
     }
     XFreeFontNames(fonts);
+#endif
     return p;
 }
 #endif
 
 void
-DeleteGCs ()
-{   // [HGM] deletes GCs that are to be remade, to prevent resource leak;
-    // must be called before all non-first callse to CreateGCs()
-    XtReleaseGC(shellWidget, highlineGC);
-    XtReleaseGC(shellWidget, lightSquareGC);
-    XtReleaseGC(shellWidget, darkSquareGC);
-    XtReleaseGC(shellWidget, lineGC);
-    if (appData.monoMode) {
-       if (DefaultDepth(xDisplay, xScreen) == 1) {
-           XtReleaseGC(shellWidget, wbPieceGC);
-       } else {
-           XtReleaseGC(shellWidget, bwPieceGC);
-       }
-    } else {
-       XtReleaseGC(shellWidget, prelineGC);
-       XtReleaseGC(shellWidget, wdPieceGC);
-       XtReleaseGC(shellWidget, wlPieceGC);
-       XtReleaseGC(shellWidget, bdPieceGC);
-       XtReleaseGC(shellWidget, blPieceGC);
-    }
-}
-
-static GC
-CreateOneGC (XGCValues *gc_values, Pixel foreground, Pixel background)
-{
-    XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
-      | GCBackground | GCFunction | GCPlaneMask;
-    gc_values->foreground = foreground;
-    gc_values->background = background;
-    return XtGetGC(shellWidget, value_mask, gc_values);
-}
-
-static void
-CreateGCs (int redo)
-{
-    XGCValues gc_values;
-    GC copyInvertedGC;
-    Pixel white = XWhitePixel(xDisplay, xScreen);
-    Pixel black = XBlackPixel(xDisplay, xScreen);
-
-    gc_values.plane_mask = AllPlanes;
-    gc_values.line_width = lineGap;
-    gc_values.line_style = LineSolid;
-    gc_values.function = GXcopy;
-
-  if(redo) {
-    DeleteGCs(); // called a second time; clean up old GCs first
-  } else { // [HGM] grid and font GCs created on first call only
-    coordGC = CreateOneGC(&gc_values, black, white);
-    XSetFont(xDisplay, coordGC, coordFontID);
-
-    // [HGM] make font for holdings counts (white on black)
-    countGC = CreateOneGC(&gc_values, white, black);
-    XSetFont(xDisplay, countGC, countFontID);
-  }
-    lineGC = CreateOneGC(&gc_values, black, black);
-
-    if (appData.monoMode) {
-
-       highlineGC = CreateOneGC(&gc_values, white, white);
-       lightSquareGC = wbPieceGC = CreateOneGC(&gc_values, white, black);
-       darkSquareGC = bwPieceGC = CreateOneGC(&gc_values, black, white);
-
-       if (DefaultDepth(xDisplay, xScreen) == 1) {
-           /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
-           gc_values.function = GXcopyInverted;
-           copyInvertedGC = CreateOneGC(&gc_values, black, white);
-           gc_values.function = GXcopy;
-           if (XBlackPixel(xDisplay, xScreen) == 1) {
-               bwPieceGC = darkSquareGC;
-               wbPieceGC = copyInvertedGC;
-           } else {
-               bwPieceGC = copyInvertedGC;
-               wbPieceGC = lightSquareGC;
-           }
-       }
-    } else {
-
-       highlineGC = CreateOneGC(&gc_values, highlightSquareColor, highlightSquareColor);
-       prelineGC = CreateOneGC(&gc_values, premoveHighlightColor, premoveHighlightColor);
-       lightSquareGC = CreateOneGC(&gc_values, lightSquareColor, darkSquareColor);
-       darkSquareGC = CreateOneGC(&gc_values, darkSquareColor, lightSquareColor);
-       wdPieceGC = CreateOneGC(&gc_values, whitePieceColor, darkSquareColor);
-       wlPieceGC = CreateOneGC(&gc_values, whitePieceColor, lightSquareColor);
-       bdPieceGC = CreateOneGC(&gc_values, blackPieceColor, darkSquareColor);
-       blPieceGC = CreateOneGC(&gc_values, blackPieceColor, lightSquareColor);
-    }
-}
-
-void
-loadXIM (XImage *xim, XImage *xmask, char *filename, Pixmap *dest, Pixmap *mask)
-{
-    int x, y, w, h, p;
-    FILE *fp;
-    Pixmap temp;
-    XGCValues  values;
-    GC maskGC;
-
-    fp = fopen(filename, "rb");
-    if (!fp) {
-       fprintf(stderr, _("%s: error loading XIM!\n"), programName);
-       exit(1);
-    }
-
-    w = fgetc(fp);
-    h = fgetc(fp);
-
-    for (y=0; y<h; ++y) {
-       for (x=0; x<h; ++x) {
-           p = fgetc(fp);
-
-           switch (p) {
-             case 0:
-               XPutPixel(xim, x, y, blackPieceColor);
-               if (xmask)
-                 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
-               break;
-             case 1:
-               XPutPixel(xim, x, y, darkSquareColor);
-               if (xmask)
-                 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
-               break;
-             case 2:
-               XPutPixel(xim, x, y, whitePieceColor);
-               if (xmask)
-                 XPutPixel(xmask, x, y, WhitePixel(xDisplay,xScreen));
-               break;
-             case 3:
-               XPutPixel(xim, x, y, lightSquareColor);
-               if (xmask)
-                 XPutPixel(xmask, x, y, BlackPixel(xDisplay,xScreen));
-               break;
-           }
-       }
-    }
-
-    fclose(fp);
-
-    /* create Pixmap of piece */
-    *dest = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
-                         w, h, xim->depth);
-    XPutImage(xDisplay, *dest, lightSquareGC, xim,
-             0, 0, 0, 0, w, h);
-
-    /* create Pixmap of clipmask
-       Note: We assume the white/black pieces have the same
-             outline, so we make only 6 masks. This is okay
-             since the XPM clipmask routines do the same. */
-    if (xmask) {
-      temp = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
-                           w, h, xim->depth);
-      XPutImage(xDisplay, temp, lightSquareGC, xmask,
-             0, 0, 0, 0, w, h);
-
-      /* now create the 1-bit version */
-      *mask = XCreatePixmap(xDisplay, DefaultRootWindow(xDisplay),
-                         w, h, 1);
-
-      values.foreground = 1;
-      values.background = 0;
-
-      /* Don't use XtGetGC, not read only */
-      maskGC = XCreateGC(xDisplay, *mask,
-                   GCForeground | GCBackground, &values);
-      XCopyPlane(xDisplay, temp, *mask, maskGC,
-                 0, 0, squareSize, squareSize, 0, 0, 1);
-      XFreePixmap(xDisplay, temp);
-    }
-}
-
-
-char pieceBitmapNames[] = "pnbrqfeacwmohijgdvlsukpnsl";
-
-void
-CreateXIMPieces ()
+EnableNamedMenuItem (char *menuRef, int state)
 {
-    int piece, kind;
-    char buf[MSG_SIZ];
-    u_int ss;
-    static char *ximkind[] = { "ll", "ld", "dl", "dd" };
-    XImage *ximtemp;
-
-    ss = squareSize;
-
-    /* The XSynchronize calls were copied from CreatePieces.
-       Not sure if needed, but can't hurt */
-    XSynchronize(xDisplay, True); /* Work-around for xlib/xt
-                                    buffering bug */
-
-    /* temp needed by loadXIM() */
-    ximtemp = XGetImage(xDisplay, DefaultRootWindow(xDisplay),
-                0, 0, ss, ss, AllPlanes, XYPixmap);
-
-    if (strlen(appData.pixmapDirectory) == 0) {
-      useImages = 0;
-    } else {
-       useImages = 1;
-       if (appData.monoMode) {
-         DisplayFatalError(_("XIM pieces cannot be used in monochrome mode"),
-                           0, 2);
-         ExitEvent(2);
-       }
-       fprintf(stderr, _("\nLoading XIMs...\n"));
-       /* Load pieces */
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
-           fprintf(stderr, "%d", piece+1);
-           for (kind=0; kind<4; kind++) {
-               fprintf(stderr, ".");
-               snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xim",
-                       ExpandPathName(appData.pixmapDirectory),
-                       piece <= (int) WhiteKing ? "" : "w",
-                       pieceBitmapNames[piece],
-                       ximkind[kind], ss);
-               ximPieceBitmap[kind][piece] =
-                 XGetImage(xDisplay, DefaultRootWindow(xDisplay),
-                           0, 0, ss, ss, AllPlanes, XYPixmap);
-               if (appData.debugMode)
-                 fprintf(stderr, _("(File:%s:) "), buf);
-               loadXIM(ximPieceBitmap[kind][piece],
-                       ximtemp, buf,
-                       &(xpmPieceBitmap2[kind][piece]),
-                       &(ximMaskPm2[piece]));
-               if(piece <= (int)WhiteKing)
-                   xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
-           }
-           fprintf(stderr," ");
-       }
-       /* Load light and dark squares */
-       /* If the LSQ and DSQ pieces don't exist, we will
-          draw them with solid squares. */
-       snprintf(buf,sizeof(buf), "%s/lsq%u.xim", ExpandPathName(appData.pixmapDirectory), ss);
-       if (access(buf, 0) != 0) {
-           useImageSqs = 0;
-       } else {
-           useImageSqs = 1;
-           fprintf(stderr, _("light square "));
-           ximLightSquare=
-             XGetImage(xDisplay, DefaultRootWindow(xDisplay),
-                       0, 0, ss, ss, AllPlanes, XYPixmap);
-           if (appData.debugMode)
-             fprintf(stderr, _("(File:%s:) "), buf);
-
-           loadXIM(ximLightSquare, NULL, buf, &xpmLightSquare, NULL);
-           fprintf(stderr, _("dark square "));
-           snprintf(buf,sizeof(buf), "%s/dsq%u.xim",
-                   ExpandPathName(appData.pixmapDirectory), ss);
-           if (appData.debugMode)
-             fprintf(stderr, _("(File:%s:) "), buf);
-           ximDarkSquare=
-             XGetImage(xDisplay, DefaultRootWindow(xDisplay),
-                       0, 0, ss, ss, AllPlanes, XYPixmap);
-           loadXIM(ximDarkSquare, NULL, buf, &xpmDarkSquare, NULL);
-           xpmJailSquare = xpmLightSquare;
-       }
-       fprintf(stderr, _("Done.\n"));
-    }
-    XSynchronize(xDisplay, False); /* Work-around for xlib/xt buffering bug */
-}
-
-static VariantClass oldVariant = (VariantClass) -1; // [HGM] pieces: redo every time variant changes
-
-#if HAVE_LIBXPM
-void
-CreateXPMBoard (char *s, int kind)
-{
-    XpmAttributes attr;
-    attr.valuemask = 0;
-    if(!appData.useBitmaps || s == NULL || *s == 0 || *s == '*') { useTexture &= ~(kind+1); return; }
-    if (XpmReadFileToPixmap(xDisplay, xBoardWindow, s, &(xpmBoardBitmap[kind]), NULL, &attr) == 0) {
-       useTexture |= kind + 1; textureW[kind] = attr.width; textureH[kind] = attr.height;
-    }
-}
+    MenuItem *item = MenuNameToItem(menuRef);
 
-void
-FreeXPMPieces ()
-{   // [HGM] to prevent resoucre leak on calling CreaeXPMPieces() a second time,
-    // thisroutine has to be called t free the old piece pixmaps
-    int piece, kind;
-    for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++)
-       for (kind=0; kind<4; kind++) XFreePixmap(xDisplay, xpmPieceBitmap2[kind][piece]);
-    if(useImageSqs) {
-       XFreePixmap(xDisplay, xpmLightSquare);
-       XFreePixmap(xDisplay, xpmDarkSquare);
-    }
+    if(item) gtk_widget_set_sensitive(item->handle, state);
 }
 
 void
-CreateXPMPieces ()
+EnableButtonBar (int state)
 {
-    int piece, kind, r;
-    char buf[MSG_SIZ];
-    u_int ss = squareSize;
-    XpmAttributes attr;
-    static char *xpmkind[] = { "ll", "ld", "dl", "dd" };
-    XpmColorSymbol symbols[4];
-    static int redo = False;
-
-    if(redo) FreeXPMPieces(); else redo = 1;
-
-    /* The XSynchronize calls were copied from CreatePieces.
-       Not sure if needed, but can't hurt */
-    XSynchronize(xDisplay, True); /* Work-around for xlib/xt buffering bug */
-
-    /* Setup translations so piece colors match square colors */
-    symbols[0].name = "light_piece";
-    symbols[0].value = appData.whitePieceColor;
-    symbols[1].name = "dark_piece";
-    symbols[1].value = appData.blackPieceColor;
-    symbols[2].name = "light_square";
-    symbols[2].value = appData.lightSquareColor;
-    symbols[3].name = "dark_square";
-    symbols[3].value = appData.darkSquareColor;
-
-    attr.valuemask = XpmColorSymbols;
-    attr.colorsymbols = symbols;
-    attr.numsymbols = 4;
-
-    if (appData.monoMode) {
-      DisplayFatalError(_("XPM pieces cannot be used in monochrome mode"),
-                       0, 2);
-      ExitEvent(2);
-    }
-    if (strlen(appData.pixmapDirectory) == 0) {
-       XpmPieces* pieces = builtInXpms;
-       useImages = 1;
-       /* Load pieces */
-       while (pieces->size != squareSize && pieces->size) pieces++;
-       if (!pieces->size) {
-         fprintf(stderr, _("No builtin XPM pieces of size %d\n"), squareSize);
-         exit(1);
-       }
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
-           for (kind=0; kind<4; kind++) {
-
-               if ((r=XpmCreatePixmapFromData(xDisplay, xBoardWindow,
-                                              pieces->xpm[piece][kind],
-                                              &(xpmPieceBitmap2[kind][piece]),
-                                              NULL, &attr)) != 0) {
-                 fprintf(stderr, _("Error %d loading XPM image \"%s\"\n"),
-                         r, buf);
-                 exit(1);
-               }
-               if(piece <= (int) WhiteKing)
-                   xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
-           }
-       }
-       useImageSqs = 0;
-       xpmJailSquare = xpmLightSquare;
-    } else {
-       useImages = 1;
-
-       fprintf(stderr, _("\nLoading XPMs...\n"));
-
-       /* Load pieces */
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
-           fprintf(stderr, "%d ", piece+1);
-           for (kind=0; kind<4; kind++) {
-             snprintf(buf, sizeof(buf), "%s/%s%c%s%u.xpm",
-                       ExpandPathName(appData.pixmapDirectory),
-                       piece > (int) WhiteKing ? "w" : "",
-                       pieceBitmapNames[piece],
-                       xpmkind[kind], ss);
-               if (appData.debugMode) {
-                   fprintf(stderr, _("(File:%s:) "), buf);
-               }
-               if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
-                                          &(xpmPieceBitmap2[kind][piece]),
-                                          NULL, &attr)) != 0) {
-                   if(piece != (int)WhiteKing && piece > (int)WhiteQueen) {
-                     // [HGM] missing: read of unorthodox piece failed; substitute King.
-                     snprintf(buf, sizeof(buf), "%s/k%s%u.xpm",
-                               ExpandPathName(appData.pixmapDirectory),
-                               xpmkind[kind], ss);
-                       if (appData.debugMode) {
-                           fprintf(stderr, _("(Replace by File:%s:) "), buf);
-                       }
-                       r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
-                                               &(xpmPieceBitmap2[kind][piece]),
-                                               NULL, &attr);
-                   }
-                   if (r != 0) {
-                       fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"),
-                               r, buf);
-                       exit(1);
-                   }
-               }
-               if(piece <= (int) WhiteKing)
-                   xpmPieceBitmap[kind][piece] = xpmPieceBitmap2[kind][piece];
-           }
-       }
-       /* Load light and dark squares */
-       /* If the LSQ and DSQ pieces don't exist, we will
-          draw them with solid squares. */
-       fprintf(stderr, _("light square "));
-       snprintf(buf, sizeof(buf), "%s/lsq%u.xpm", ExpandPathName(appData.pixmapDirectory), ss);
-       if (access(buf, 0) != 0) {
-           useImageSqs = 0;
-       } else {
-           useImageSqs = 1;
-           if (appData.debugMode)
-             fprintf(stderr, _("(File:%s:) "), buf);
-
-           if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
-                                      &xpmLightSquare, NULL, &attr)) != 0) {
-               fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
-               exit(1);
-           }
-           fprintf(stderr, _("dark square "));
-           snprintf(buf, sizeof(buf), "%s/dsq%u.xpm",
-                   ExpandPathName(appData.pixmapDirectory), ss);
-           if (appData.debugMode) {
-               fprintf(stderr, _("(File:%s:) "), buf);
-           }
-           if ((r=XpmReadFileToPixmap(xDisplay, xBoardWindow, buf,
-                                      &xpmDarkSquare, NULL, &attr)) != 0) {
-               fprintf(stderr, _("Error %d loading XPM file \"%s\"\n"), r, buf);
-               exit(1);
-           }
-       }
-       xpmJailSquare = xpmLightSquare;
-       fprintf(stderr, _("Done.\n"));
-    }
-    oldVariant = -1; // kludge to force re-makig of animation masks
-    XSynchronize(xDisplay, False); /* Work-around for xlib/xt
-                                     buffering bug */
+#ifdef TODO_GTK
+    XtSetSensitive(optList[W_BUTTON].handle, state);
+#endif
 }
-#endif /* HAVE_LIBXPM */
 
-#if HAVE_LIBXPM
-/* No built-in bitmaps */
-void CreatePieces()
-{
-    int piece, kind;
-    char buf[MSG_SIZ];
-    u_int ss = squareSize;
-
-    XSynchronize(xDisplay, True); /* Work-around for xlib/xt
-                                    buffering bug */
-
-    for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
-         snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
-                  pieceBitmapNames[piece],
-                  ss, kind == SOLID ? 's' : 'o');
-         ReadBitmap(&pieceBitmap2[kind][piece], buf, NULL, ss, ss);
-         if(piece <= (int)WhiteKing)
-           pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
-       }
-    }
 
-    XSynchronize(xDisplay, False); /* Work-around for xlib/xt
-                                     buffering bug */
-}
-#else
-/* With built-in bitmaps */
 void
-CreatePieces ()
+SetMenuEnables (Enables *enab)
 {
-    BuiltInBits* bib = builtInBits;
-    int piece, kind;
-    char buf[MSG_SIZ];
-    u_int ss = squareSize;
-
-    XSynchronize(xDisplay, True); /* Work-around for xlib/xt
-                                    buffering bug */
-
-    while (bib->squareSize != ss && bib->squareSize != 0) bib++;
-
-    for (kind = SOLID; kind <= (appData.monoMode ? OUTLINE : SOLID); kind++) {
-       for (piece = (int) WhitePawn; piece <= (int) WhiteKing + 4; piece++) {
-         snprintf(buf, MSG_SIZ, "%s%c%u%c.bm", piece > (int)WhiteKing ? "w" : "",
-                  pieceBitmapNames[piece],
-                  ss, kind == SOLID ? 's' : 'o');
-         ReadBitmap(&pieceBitmap2[kind][piece], buf,
-                    bib->bits[kind][piece], ss, ss);
-         if(piece <= (int)WhiteKing)
-           pieceBitmap[kind][piece] = pieceBitmap2[kind][piece];
-       }
-    }
-
-    XSynchronize(xDisplay, False); /* Work-around for xlib/xt
-                                     buffering bug */
-}
-#endif
-
-void
-ReadBitmap (Pixmap *pm, String name, unsigned char bits[], u_int wreq, u_int hreq)
-{
-    int x_hot, y_hot;
-    u_int w, h;
-    int errcode;
-    char msg[MSG_SIZ], fullname[MSG_SIZ];
-
-    if (*appData.bitmapDirectory != NULLCHAR) {
-      safeStrCpy(fullname, appData.bitmapDirectory, sizeof(fullname)/sizeof(fullname[0]) );
-      strncat(fullname, "/", MSG_SIZ - strlen(fullname) - 1);
-      strncat(fullname, name, MSG_SIZ - strlen(fullname) - 1);
-      errcode = XReadBitmapFile(xDisplay, xBoardWindow, fullname,
-                               &w, &h, pm, &x_hot, &y_hot);
-      fprintf(stderr, "load %s\n", name);
-       if (errcode != BitmapSuccess) {
-           switch (errcode) {
-             case BitmapOpenFailed:
-               snprintf(msg, sizeof(msg), _("Can't open bitmap file %s"), fullname);
-               break;
-             case BitmapFileInvalid:
-               snprintf(msg, sizeof(msg), _("Invalid bitmap in file %s"), fullname);
-               break;
-             case BitmapNoMemory:
-               snprintf(msg, sizeof(msg), _("Ran out of memory reading bitmap file %s"),
-                       fullname);
-               break;
-             default:
-               snprintf(msg, sizeof(msg), _("Unknown XReadBitmapFile error %d on file %s"),
-                       errcode, fullname);
-               break;
-           }
-           fprintf(stderr, _("%s: %s...using built-in\n"),
-                   programName, msg);
-       } else if (w != wreq || h != hreq) {
-           fprintf(stderr,
-                   _("%s: Bitmap %s is %dx%d, not %dx%d...using built-in\n"),
-                   programName, fullname, w, h, wreq, hreq);
-       } else {
-           return;
-       }
-    }
-    if (bits != NULL) {
-       *pm = XCreateBitmapFromData(xDisplay, xBoardWindow, (char *) bits,
-                                   wreq, hreq);
-    }
+  while (enab->name != NULL) {
+    EnableNamedMenuItem(enab->name, enab->value);
+    enab++;
+  }
 }
 
-void
-CreateGrid ()
+#ifdef TODO_GTK
+gboolean KeyPressProc(window, eventkey, data)
+     GtkWindow *window;
+     GdkEventKey  *eventkey;
+     gpointer data;
 {
-    int i, j;
 
-    if (lineGap == 0) return;
+    MoveTypeInProc(eventkey); // pop up for typed in moves
 
-    /* [HR] Split this into 2 loops for non-square boards. */
+    // handle shift+<number> cases
+    if (eventkey->state & GDK_SHIFT_MASK) {
+        guint keyval;
 
-    for (i = 0; i < BOARD_HEIGHT + 1; i++) {
-        gridSegments[i].x1 = 0;
-        gridSegments[i].x2 =
-          lineGap + BOARD_WIDTH * (squareSize + lineGap);
-        gridSegments[i].y1 = gridSegments[i].y2
-          = lineGap / 2 + (i * (squareSize + lineGap));
-    }
-
-    for (j = 0; j < BOARD_WIDTH + 1; j++) {
-        gridSegments[j + i].y1 = 0;
-        gridSegments[j + i].y2 =
-          lineGap + BOARD_HEIGHT * (squareSize + lineGap);
-        gridSegments[j + i].x1 = gridSegments[j + i].x2
-          = lineGap / 2 + (j * (squareSize + lineGap));
+        gdk_keymap_translate_keyboard_state(NULL, eventkey->hardware_keycode,
+                                           0, eventkey->group,
+                                           &keyval, NULL, NULL, NULL);
+        switch(keyval) {
+            case GDK_1:
+                AskQuestionEvent("Direct command", "Send to chess program:", "", "1");
+                break;
+            case GDK_2:
+                AskQuestionEvent("Direct command", "Send to second chess program:", "", "2");
+                break;
+            default:
+                break;
+        }
     }
-}
-
-void
-MarkMenuItem (char *menuRef, int state)
-{
-    MenuItem *item = MenuNameToItem(menuRef);
 
-    if(item) {
-       Arg args[2];
-       XtSetArg(args[0], XtNleftBitmap, state ? xMarkPixmap : None);
-       XtSetValues(item->handle, args, 1);
+    /* check for other key values */
+    switch(eventkey->keyval) {
+        case GDK_question:
+         AboutGameEvent();
+         break;
+        default:
+         break;
     }
+    return False;
 }
-
-void
-EnableMenuItem (char *menuRef, int state)
-{
-    MenuItem *item = MenuNameToItem(menuRef);
-
-    if(item) XtSetSensitive(item->handle, state);
-}
-
-void
-EnableButtonBar (int state)
-{
-    XtSetSensitive(optList[W_BUTTON].handle, state);
-}
-
-
-void
-SetMenuEnables (Enables *enab)
-{
-  while (enab->name != NULL) {
-    EnableMenuItem(enab->name, enab->value);
-    enab++;
-  }
-}
-
 void
 KeyBindingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {   // [HGM] new method of key binding: specify MenuItem(FlipView) in stead of FlipViewProc in translation string
@@ -2313,22 +1679,12 @@ KeyBindingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
     item = MenuNameToItem(prms[0]);
     if(item) ((MenuProc *) item->proc) ();
 }
-
-static void
-MenuEngineSelect (Widget w, caddr_t addr, caddr_t index)
-{
-    RecentEngineEvent((int) (intptr_t) addr);
-}
-
-void
-AppendMenuItem (char *msg, int n)
-{
-    CreateMenuItem((Widget) optList[W_ENGIN].textValue, msg, (XtCallbackProc) MenuEngineSelect, n);
-}
+#endif
 
 void
 SetupDropMenu ()
 {
+#ifdef TODO_GTK
     int i, j, count;
     char label[32];
     Arg args[16];
@@ -2349,9 +1705,9 @@ SetupDropMenu ()
        XtSetArg(args[j], XtNlabel, label); j++;
        XtSetValues(entry, args, j);
     }
+#endif
 }
 
-
 static void
 do_flash_delay (unsigned long msec)
 {
@@ -2359,270 +1715,8 @@ do_flash_delay (unsigned long msec)
 }
 
 void
-DrawBorder (int x, int y, int type)
-{
-    GC gc = lineGC;
-
-    if(type == 1) gc = highlineGC; else if(type == 2) gc = prelineGC;
-
-    XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
-                  squareSize+lineGap, squareSize+lineGap);
-}
-
-static int
-CutOutSquare (int x, int y, int *x0, int *y0, int  kind)
-{
-    int W = BOARD_WIDTH, H = BOARD_HEIGHT;
-    int nx = x/(squareSize + lineGap), ny = y/(squareSize + lineGap);
-    *x0 = 0; *y0 = 0;
-    if(textureW[kind] < squareSize || textureH[kind] < squareSize) return 0;
-    if(textureW[kind] < W*squareSize)
-       *x0 = (textureW[kind] - squareSize) * nx/(W-1);
-    else
-       *x0 = textureW[kind]*nx / W + (textureW[kind] - W*squareSize) / (2*W);
-    if(textureH[kind] < H*squareSize)
-       *y0 = (textureH[kind] - squareSize) * ny/(H-1);
-    else
-       *y0 = textureH[kind]*ny / H + (textureH[kind] - H*squareSize) / (2*H);
-    return 1;
-}
-
-static void
-BlankSquare (int x, int y, int color, ChessSquare piece, Drawable dest, int fac)
-{   // [HGM] extra param 'fac' for forcing destination to (0,0) for copying to animation buffer
-    int x0, y0;
-    if (useImages && color != 2 && (useTexture & color+1) && CutOutSquare(x, y, &x0, &y0, color)) {
-       XCopyArea(xDisplay, xpmBoardBitmap[color], dest, wlPieceGC, x0, y0,
-                 squareSize, squareSize, x*fac, y*fac);
-    } else
-    if (useImages && useImageSqs) {
-       Pixmap pm;
-       switch (color) {
-         case 1: /* light */
-           pm = xpmLightSquare;
-           break;
-         case 0: /* dark */
-           pm = xpmDarkSquare;
-           break;
-         case 2: /* neutral */
-         default:
-           pm = xpmJailSquare; // [HGM] this is wrong, but apparently never used?
-           break;
-       }
-       XCopyArea(xDisplay, pm, dest, wlPieceGC, 0, 0,
-                 squareSize, squareSize, x*fac, y*fac);
-    } else {
-       GC gc;
-       switch (color) {
-         case 1: /* light */
-           gc = lightSquareGC;
-           break;
-         case 0: /* dark */
-           gc = darkSquareGC;
-           break;
-         case 2: /* neutral */
-         default:
-           gc = lineGC;
-           break;
-       }
-       XFillRectangle(xDisplay, dest, gc, x*fac, y*fac, squareSize, squareSize);
-    }
-}
-
-/*
-   I split out the routines to draw a piece so that I could
-   make a generic flash routine.
-*/
-static void
-monoDrawPiece_1bit (ChessSquare piece, int square_color, int x, int y, Drawable dest)
-{
-    /* Avoid XCopyPlane on 1-bit screens to work around Sun bug */
-    switch (square_color) {
-      case 1: /* light */
-      case 2: /* neutral */
-      default:
-       XCopyArea(xDisplay, (int) piece < (int) BlackPawn
-                 ? *pieceToOutline(piece)
-                 : *pieceToSolid(piece),
-                 dest, bwPieceGC, 0, 0,
-                 squareSize, squareSize, x, y);
-       break;
-      case 0: /* dark */
-       XCopyArea(xDisplay, (int) piece < (int) BlackPawn
-                 ? *pieceToSolid(piece)
-                 : *pieceToOutline(piece),
-                 dest, wbPieceGC, 0, 0,
-                 squareSize, squareSize, x, y);
-       break;
-    }
-}
-
-static void
-monoDrawPiece (ChessSquare piece, int square_color, int x, int y, Drawable dest)
-{
-    switch (square_color) {
-      case 1: /* light */
-      case 2: /* neutral */
-      default:
-       XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
-                  ? *pieceToOutline(piece)
-                  : *pieceToSolid(piece),
-                  dest, bwPieceGC, 0, 0,
-                  squareSize, squareSize, x, y, 1);
-       break;
-      case 0: /* dark */
-       XCopyPlane(xDisplay, (int) piece < (int) BlackPawn
-                  ? *pieceToSolid(piece)
-                  : *pieceToOutline(piece),
-                  dest, wbPieceGC, 0, 0,
-                  squareSize, squareSize, x, y, 1);
-       break;
-    }
-}
-
-static void
-colorDrawPiece (ChessSquare piece, int square_color, int x, int y, Drawable dest)
-{
-    if(pieceToSolid(piece) == NULL) return; // [HGM] bitmaps: make it non-fatal if we have no bitmap;
-    switch (square_color) {
-      case 1: /* light */
-       XCopyPlane(xDisplay, *pieceToSolid(piece),
-                  dest, (int) piece < (int) BlackPawn
-                  ? wlPieceGC : blPieceGC, 0, 0,
-                  squareSize, squareSize, x, y, 1);
-       break;
-      case 0: /* dark */
-       XCopyPlane(xDisplay, *pieceToSolid(piece),
-                  dest, (int) piece < (int) BlackPawn
-                  ? wdPieceGC : bdPieceGC, 0, 0,
-                  squareSize, squareSize, x, y, 1);
-       break;
-      case 2: /* neutral */
-      default:
-       break; // should never contain pieces
-    }
-}
-
-static void
-colorDrawPieceImage (ChessSquare piece, int square_color, int x, int y, Drawable dest)
-{
-    int kind, p = piece;
-
-    switch (square_color) {
-      case 1: /* light */
-      case 2: /* neutral */
-      default:
-       if ((int)piece < (int) BlackPawn) {
-           kind = 0;
-       } else {
-           kind = 2;
-           piece -= BlackPawn;
-       }
-       break;
-      case 0: /* dark */
-       if ((int)piece < (int) BlackPawn) {
-           kind = 1;
-       } else {
-           kind = 3;
-           piece -= BlackPawn;
-       }
-       break;
-    }
-    if(appData.upsideDown && flipView) { kind ^= 2; p += p < BlackPawn ? BlackPawn : -BlackPawn; }// swap white and black pieces
-    if(useTexture & square_color+1) {
-        BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background
-       XSetClipMask(xDisplay, wlPieceGC, xpmMask[p]);
-       XSetClipOrigin(xDisplay, wlPieceGC, x, y);
-       XCopyArea(xDisplay, xpmPieceBitmap[kind][piece], dest, wlPieceGC, 0, 0, squareSize, squareSize, x, y);
-       XSetClipMask(xDisplay, wlPieceGC, None);
-       XSetClipOrigin(xDisplay, wlPieceGC, 0, 0);
-    } else
-    XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
-             dest, wlPieceGC, 0, 0,
-             squareSize, squareSize, x, y);
-}
-
-typedef void (*DrawFunc)();
-
-DrawFunc
-ChooseDrawFunc ()
-{
-    if (appData.monoMode) {
-       if (DefaultDepth(xDisplay, xScreen) == 1) {
-           return monoDrawPiece_1bit;
-       } else {
-           return monoDrawPiece;
-       }
-    } else {
-       if (useImages)
-         return colorDrawPieceImage;
-       else
-         return colorDrawPiece;
-    }
-}
-
-void
-DrawDot (int marker, int x, int y, int r)
-{
-       if(appData.monoMode) {
-           XFillArc(xDisplay, xBoardWindow, marker == 2 ? darkSquareGC : lightSquareGC,
-                   x, y, r, r, 0, 64*360);
-           XDrawArc(xDisplay, xBoardWindow, marker == 2 ? lightSquareGC : darkSquareGC,
-                   x, y, r, r, 0, 64*360);
-       } else
-       XFillArc(xDisplay, xBoardWindow, marker == 2 ? prelineGC : highlineGC,
-                   x, y, r, r, 0, 64*360);
-}
-
-void
-DrawOneSquare (int x, int y, ChessSquare piece, int square_color, int marker, char *string, int align)
-{   // basic front-end board-draw function: takes care of everything that can be in square:
-    // piece, background, coordinate/count, marker dot
-    int direction, font_ascent, font_descent;
-    XCharStruct overall;
-    DrawFunc drawfunc;
-
-    if (piece == EmptySquare) {
-       BlankSquare(x, y, square_color, piece, xBoardWindow, 1);
-    } else {
-       drawfunc = ChooseDrawFunc();
-       drawfunc(piece, square_color, x, y, xBoardWindow);
-    }
-
-    if(align) { // square carries inscription (coord or piece count)
-       int xx = x, yy = y;
-       GC hGC = align < 3 ? coordGC : countGC;
-       // first calculate where it goes
-       XTextExtents(countFontStruct, string, 1, &direction,
-                        &font_ascent, &font_descent, &overall);
-       if (align == 1) {
-           xx += squareSize - overall.width - 2;
-           yy += squareSize - font_descent - 1;
-       } else if (align == 2) {
-           xx += 2, yy += font_ascent + 1;
-       } else if (align == 3) {
-           xx += squareSize - overall.width - 2;
-           yy += font_ascent + 1;
-       } else if (align == 4) {
-           xx += 2, yy += font_ascent + 1;
-       }
-       // then draw it
-       if (appData.monoMode) {
-           XDrawImageString(xDisplay, xBoardWindow, hGC, xx, yy, string, 1);
-       } else {
-           XDrawString(xDisplay, xBoardWindow, hGC, xx, yy, string, 1);
-       }
-    }
-
-    if(marker) { // print fat marker dot, if requested
-       DrawDot(marker, x + squareSize/4, y+squareSize/4, squareSize/2);
-    }
-}
-
-void
 FlashDelay (int flash_delay)
 {
-       XSync(xDisplay, False);
        if(flash_delay) do_flash_delay(flash_delay);
 }
 
@@ -2636,6 +1730,7 @@ Fraction (int x, int start, int stop)
 
 static WindowPlacement wpNew;
 
+#ifdef TODO_GTK
 void
 CoDrag (Widget sh, WindowPlacement *wp)
 {
@@ -2666,20 +1761,51 @@ CoDrag (Widget sh, WindowPlacement *wp)
     wp->y += wpNew.y - wpMain.y;
     if(touch == 1) wp->x += wpNew.width - wpMain.width; else
     if(touch == 3) wp->y += wpNew.height - wpMain.height;
+#ifdef TODO_GTK
     XtSetArg(args[j], XtNx, wp->x); j++;
     XtSetArg(args[j], XtNy, wp->y); j++;
     XtSetValues(sh, args, j);
+#endif
+}
+
+void
+ReSize (WindowPlacement *wp)
+{
+       int sqx, sqy, w, h;
+       if(wp->width == wpMain.width && wp->height == wpMain.height) return; // not sized
+       sqx = (wp->width  - lineGap - marginW) / BOARD_WIDTH - lineGap;
+       sqy = (wp->height - lineGap - marginH) / BOARD_HEIGHT - lineGap;
+       if(sqy < sqx) sqx = sqy;
+       if(sqx != squareSize) {
+           squareSize = sqx; // adopt new square size
+           CreatePNGPieces(); // make newly scaled pieces
+           InitDrawingSizes(0, 0); // creates grid etc.
+       } else ResizeBoardWindow(BOARD_WIDTH * (squareSize + lineGap) + lineGap, BOARD_HEIGHT * (squareSize + lineGap) + lineGap, 0);
+       w = BOARD_WIDTH * (squareSize + lineGap) + lineGap;
+       h = BOARD_HEIGHT * (squareSize + lineGap) + lineGap;
+       if(optList[W_BOARD].max   > w) optList[W_BOARD].max = w;
+       if(optList[W_BOARD].value > h) optList[W_BOARD].value = h;
 }
 
+#ifdef TODO_GTK
 static XtIntervalId delayedDragID = 0;
+#else
+static int delayedDragID = 0;
+#endif
 
 void
 DragProc ()
 {
+       static int busy;
+       if(busy) return;
+
+       busy = 1;
        GetActualPlacement(shellWidget, &wpNew);
        if(wpNew.x == wpMain.x && wpNew.y == wpMain.y && // not moved
-          wpNew.width == wpMain.width && wpNew.height == wpMain.height) // not sized
-           return; // false alarm
+          wpNew.width == wpMain.width && wpNew.height == wpMain.height) { // not sized
+           busy = 0; return; // false alarm
+       }
+       ReSize(&wpNew);
        if(shellUp[EngOutDlg]) CoDrag(shells[EngOutDlg], &wpEngineOutput);
        if(shellUp[HistoryDlg]) CoDrag(shells[HistoryDlg], &wpMoveHistory);
        if(shellUp[EvalGraphDlg]) CoDrag(shells[EvalGraphDlg], &wpEvalGraph);
@@ -2687,140 +1813,41 @@ DragProc ()
        wpMain = wpNew;
        DrawPosition(True, NULL);
        delayedDragID = 0; // now drag executed, make sure next DelayedDrag will not cancel timer event (which could now be used by other)
+       busy = 0;
 }
-
+#endif
 
 void
 DelayedDrag ()
 {
+#ifdef TODO_GTK
     if(delayedDragID) XtRemoveTimeOut(delayedDragID); // cancel pending
     delayedDragID =
-      XtAppAddTimeOut(appContext, 50, (XtTimerCallbackProc) DragProc, (XtPointer) 0); // and schedule new one 50 msec later
+      XtAppAddTimeOut(appContext, 200, (XtTimerCallbackProc) DragProc, (XtPointer) 0); // and schedule new one 50 msec later
+#endif
 }
 
+#ifdef TODO_GTK
 void
 EventProc (Widget widget, caddr_t unused, XEvent *event)
 {
     if(XtIsRealized(widget) && event->type == ConfigureNotify || appData.useStickyWindows)
        DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other
 }
-
-// [HGM] seekgraph: some low-level drawing routines cloned from xevalgraph
-void
-DrawSeekAxis (int x, int y, int xTo, int yTo)
-{
-      XDrawLine(xDisplay, xBoardWindow, lineGC, x, y, xTo, yTo);
-}
-
-void
-DrawSeekBackground (int left, int top, int right, int bottom)
-{
-    XFillRectangle(xDisplay, xBoardWindow, lightSquareGC, left, top, right-left, bottom-top);
-}
-
-void
-DrawSeekText (char *buf, int x, int y)
-{
-    XDrawString(xDisplay, xBoardWindow, coordGC, x, y+4, buf, strlen(buf));
-}
-
-void
-DrawSeekDot (int x, int y, int colorNr)
-{
-    int square = colorNr & 0x80;
-    GC color;
-    colorNr &= 0x7F;
-    color = colorNr == 0 ? prelineGC : colorNr == 1 ? darkSquareGC : highlineGC;
-    if(square)
-       XFillRectangle(xDisplay, xBoardWindow, color,
-               x-squareSize/9, y-squareSize/9, 2*squareSize/9, 2*squareSize/9);
-    else
-       XFillArc(xDisplay, xBoardWindow, color,
-               x-squareSize/8, y-squareSize/8, squareSize/4, squareSize/4, 0, 64*360);
-}
-
-void
-DrawGrid ()
-{
-         XDrawSegments(xDisplay, xBoardWindow, lineGC,
-                       gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
-}
-
+#endif
 
 /*
  * event handler for redrawing the board
  */
+#ifdef TODO_GTK
 void
 DrawPositionProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     DrawPosition(True, NULL);
 }
+#endif
 
 
-void
-HandlePV (Widget w, XEvent * event, String * params, Cardinal * nParams)
-{   // [HGM] pv: walk PV
-    MovePV(event->xmotion.x, event->xmotion.y, lineGap + BOARD_HEIGHT * (squareSize + lineGap));
-}
-
-static int savedIndex;  /* gross that this is global */
-
-void
-CommentClick (Widget w, XEvent * event, String * params, Cardinal * nParams)
-{
-       String val;
-       XawTextPosition index, dummy;
-       Arg arg;
-
-       XawTextGetSelectionPos(w, &index, &dummy);
-       XtSetArg(arg, XtNstring, &val);
-       XtGetValues(w, &arg, 1);
-       ReplaceComment(savedIndex, val);
-       if(savedIndex != currentMove) ToNrEvent(savedIndex);
-       LoadVariation( index, val ); // [HGM] also does the actual moving to it, now
-}
-
-void
-EditCommentPopUp (int index, char *title, char *text)
-{
-    savedIndex = index;
-    if (text == NULL) text = "";
-    NewCommentPopup(title, text, index);
-}
-
-void
-CommentPopUp (char *title, char *text)
-{
-    savedIndex = currentMove; // [HGM] vari
-    NewCommentPopup(title, text, currentMove);
-}
-
-void
-CommentPopDown ()
-{
-    PopDown(CommentDlg);
-}
-
-static char *openName;
-FILE *openFP;
-
-void
-DelayedLoad ()
-{
-  (void) (*fileProc)(openFP, 0, openName);
-}
-
-void
-FileNamePopUp (char *label, char *def, char *filter, FileProc proc, char *openMode)
-{
-    fileProc = proc;           /* I can't see a way not */
-    fileOpenMode = openMode;   /*   to use globals here */
-    {   // [HGM] use file-selector dialog stolen from Ghostview
-       // int index; // this is not supported yet
-       Browse(BoardWindow, label, (def[0] ? def : NULL), filter, False, openMode, &openName, &openFP);
-    }
-}
-
 
 /* Disable all user input other than deleting the window */
 static int frozen = 0;
@@ -2830,7 +1857,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;
 }
 
@@ -2839,19 +1866,17 @@ void
 ThawUI ()
 {
   if (!frozen) return;
-  XtRemoveGrab(optList[W_MESSG].handle);
+  gtk_grab_remove(optList[W_MESSG].handle);
   frozen = 0;
 }
 
 void
 ModeHighlight ()
 {
-    Arg args[16];
     static int oldPausing = FALSE;
     static GameMode oldmode = (GameMode) -1;
     char *wname;
-
-    if (!boardWidget || !XtIsRealized(boardWidget)) return;
+    if (!boardWidget) return;
 
     if (pausing != oldPausing) {
        oldPausing = pausing;
@@ -2861,16 +1886,9 @@ ModeHighlight ()
          /* Always toggle, don't set.  Previous code messes up when
             invoked while the button is pressed, as releasing it
             toggles the state again. */
-         {
-           Pixel oldbg, oldfg;
-           XtSetArg(args[0], XtNbackground, &oldbg);
-           XtSetArg(args[1], XtNforeground, &oldfg);
-           XtGetValues(optList[W_PAUSE].handle,
-                       args, 2);
-           XtSetArg(args[0], XtNbackground, oldfg);
-           XtSetArg(args[1], XtNforeground, oldbg);
-         }
-         XtSetValues(optList[W_PAUSE].handle, args, 2);
+           GdkColor color;     
+            gdk_color_parse( pausing ? "#808080" : "#F0F0F0", &color );
+            gtk_widget_modify_bg ( GTK_WIDGET(optList[W_PAUSE].handle), GTK_STATE_NORMAL, &color );
        }
     }
 
@@ -2886,7 +1904,9 @@ ModeHighlight ()
     MarkMenuItem("Mode.MachineMatch", matchMode && matchGame < appData.matchGames);
 
     /* Maybe all the enables should be handled here, not just this one */
-    EnableMenuItem("Mode.Training", gameMode == Training || gameMode == PlayFromGameFile);
+    EnableNamedMenuItem("Mode.Training", gameMode == Training || gameMode == PlayFromGameFile);
+
+    DisplayLogos(&optList[W_WHITE-1], &optList[W_BLACK+1]);
 }
 
 
@@ -2894,6 +1914,7 @@ ModeHighlight ()
  * Button/menu procedures
  */
 
+#ifdef TODO_GTK
 /* this variable is shared between CopyPositionProc and SendPositionSelection */
 char *selected_fen_position=NULL;
 
@@ -2960,6 +1981,7 @@ SendPositionSelection (Widget w, Atom *selection, Atom *target,
     return False;
   }
 }
+#endif
 
 /* note: when called from menu all parameters are NULL, so no clue what the
  * Widget which was clicked on was, or what the click event was
@@ -2967,6 +1989,7 @@ SendPositionSelection (Widget w, Atom *selection, Atom *target,
 void
 CopySomething (char *src)
 {
+#ifdef TODO_GTK
     selected_fen_position = src;
     /*
      * Set both PRIMARY (the selection) and CLIPBOARD, since we don't
@@ -2983,8 +2006,10 @@ CopySomething (char *src)
                   SendPositionSelection,
                   NULL/* lose_ownership_proc */ ,
                   NULL/* transfer_done_proc */);
+#endif
 }
 
+#ifdef TODO_GTK
 /* function called when the data to Paste is ready */
 static void
 PastePositionCB (Widget w, XtPointer client_data, Atom *selection,
@@ -2996,12 +2021,14 @@ PastePositionCB (Widget w, XtPointer client_data, Atom *selection,
   EditPositionPasteFEN(fenstr);
   XtFree(value);
 }
+#endif
 
 /* called when Paste Position button is pressed,
  * all parameters will be NULL */
 void
 PastePositionProc ()
 {
+#ifdef TODO_GTK
     XtGetSelectionValue(menuBarWidget,
       appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
       /* (XtSelectionCallbackProc) */ PastePositionCB,
@@ -3013,8 +2040,10 @@ PastePositionProc ()
       CurrentTime
     );
     return;
+#endif
 }
 
+#ifdef TODO_GTK
 /* note: when called from menu all parameters are NULL, so no clue what the
  * Widget which was clicked on was, or what the click event was
  */
@@ -3037,12 +2066,14 @@ PasteGameCB (Widget w, XtPointer client_data, Atom *selection,
   XtFree(value);
   LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
 }
+#endif
 
 /* called when Paste Game button is pressed,
  * all parameters will be NULL */
 void
 PasteGameProc ()
 {
+#ifdef TODO_GTK
     XtGetSelectionValue(menuBarWidget,
       appData.pasteSelection ? XA_PRIMARY: XA_CLIPBOARD(xDisplay), XA_STRING,
       /* (XtSelectionCallbackProc) */ PasteGameCB,
@@ -3054,59 +2085,52 @@ PasteGameProc ()
       CurrentTime
     );
     return;
+#endif
 }
 
 
+#ifdef TODO_GTK
 void
 QuitWrapper (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
     QuitProc();
 }
+#endif
 
 int
 ShiftKeys ()
 {   // bassic primitive for determining if modifier keys are pressed
+    int i,j,  k=0;
+#ifdef TODO_GTK
     long int codes[] = { XK_Meta_L, XK_Meta_R, XK_Control_L, XK_Control_R, XK_Shift_L, XK_Shift_R };
     char keys[32];
-    int i,j,  k=0;
     XQueryKeymap(xDisplay,keys);
     for(i=0; i<6; i++) {
        k <<= 1;
        j = XKeysymToKeycode(xDisplay, codes[i]);
        k += ( (keys[j>>3]&1<<(j&7)) != 0 );
     }
+#endif
     return k;
 }
 
-static void
-MoveTypeInProc (Widget widget, caddr_t unused, XEvent *event)
+void MoveTypeInProc(eventkey)
+    GdkEventKey  *eventkey;
 {
     char buf[10];
-    KeySym sym;
-    int n = XLookupString(&(event->xkey), buf, 10, &sym, NULL);
-    if ( n == 1 && *buf >= 32 // printable
-        && !(ShiftKeys() & 0x3C) // no Alt, Ctrl
-       ) BoxAutoPopUp (buf);
-}
 
-static void
-UpKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{   // [HGM] input: let up-arrow recall previous line from history
-    IcsKey(1);
-}
+    // ingnore if ctrl or alt is pressed
+    if (eventkey->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) {
+        return;
+    }
 
-static void
-DownKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{   // [HGM] input: let down-arrow recall next line from history
-    IcsKey(-1);
-}
-
-static void
-EnterKeyProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{
-    IcsKey(0);
+    buf[0]=eventkey->keyval;
+    buf[1]='\0';
+    if (*buf >= 32)        
+       BoxAutoPopUp (buf);
 }
 
+#ifdef TODO_GTK
 void
 TempBackwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 {
@@ -3144,10 +2168,20 @@ ManInner (Widget w, XEvent *event, String *prms, Cardinal *nprms)
     snprintf(buf, sizeof(buf), "xterm -e man %s &", name);
     system(buf);
 }
+#endif
+
+void
+ManProc ()
+{   // called from menu
+#ifdef TODO_GTK
+    ManInner(NULL, NULL, NULL, NULL);
+#endif
+}
 
 void
 SetWindowTitle (char *text, char *title, char *icon)
 {
+#ifdef TODO_GTK
     Arg args[16];
     int i;
     if (appData.titleInWindow) {
@@ -3160,6 +2194,11 @@ SetWindowTitle (char *text, char *title, char *icon)
     XtSetArg(args[i], XtNtitle, (XtArgVal) title);      i++;
     XtSetValues(shellWidget, args, i);
     XSync(xDisplay, False);
+#endif
+    if (appData.titleInWindow) {
+       SetWidgetLabel(titleWidget, text);
+    }
+    gtk_window_set_title (GTK_WINDOW(shells[BoardWindow]), title);
 }
 
 
@@ -3172,6 +2211,7 @@ NullXErrorCheck (Display *dpy, XErrorEvent *error_event)
 void
 DisplayIcsInteractionTitle (String message)
 {
+#ifdef TODO_GTK
   if (oldICSInteractionTitle == NULL) {
     /* Magic to find the old window title, adapted from vim */
     char *wina = getenv("WINDOWID");
@@ -3196,183 +2236,50 @@ DisplayIcsInteractionTitle (String message)
   }
   printf("\033]0;%s\007", message);
   fflush(stdout);
+#endif
 }
 
 
-XtIntervalId delayedEventTimerXID = 0;
-DelayedEventCallback delayedEventCallback = 0;
-
-void
-FireDelayedEvent ()
-{
-    delayedEventTimerXID = 0;
-    delayedEventCallback();
-}
-
-void
-ScheduleDelayedEvent (DelayedEventCallback cb, long millisec)
-{
-    if(delayedEventTimerXID && delayedEventCallback == cb)
-       // [HGM] alive: replace, rather than add or flush identical event
-       XtRemoveTimeOut(delayedEventTimerXID);
-    delayedEventCallback = cb;
-    delayedEventTimerXID =
-      XtAppAddTimeOut(appContext, millisec,
-                     (XtTimerCallbackProc) FireDelayedEvent, (XtPointer) 0);
-}
-
-DelayedEventCallback
-GetDelayedEvent ()
-{
-  if (delayedEventTimerXID) {
-    return delayedEventCallback;
-  } else {
-    return NULL;
-  }
-}
-
-void
-CancelDelayedEvent ()
-{
-  if (delayedEventTimerXID) {
-    XtRemoveTimeOut(delayedEventTimerXID);
-    delayedEventTimerXID = 0;
-  }
-}
-
-XtIntervalId loadGameTimerXID = 0;
-
-int
-LoadGameTimerRunning ()
-{
-    return loadGameTimerXID != 0;
-}
-
-int
-StopLoadGameTimer ()
-{
-    if (loadGameTimerXID != 0) {
-       XtRemoveTimeOut(loadGameTimerXID);
-       loadGameTimerXID = 0;
-       return TRUE;
-    } else {
-       return FALSE;
-    }
-}
-
-void
-LoadGameTimerCallback (XtPointer arg, XtIntervalId *id)
-{
-    loadGameTimerXID = 0;
-    AutoPlayGameLoop();
-}
-
-void
-StartLoadGameTimer (long millisec)
-{
-    loadGameTimerXID =
-      XtAppAddTimeOut(appContext, millisec,
-                     (XtTimerCallbackProc) LoadGameTimerCallback,
-                     (XtPointer) 0);
-}
-
-XtIntervalId analysisClockXID = 0;
-
 void
-AnalysisClockCallback (XtPointer arg, XtIntervalId *id)
-{
-    if (gameMode == AnalyzeMode || gameMode == AnalyzeFile
-         || appData.icsEngineAnalyze) { // [DM]
-       AnalysisPeriodicEvent(0);
-       StartAnalysisClock();
-    }
-}
-
-void
-StartAnalysisClock ()
-{
-    analysisClockXID =
-      XtAppAddTimeOut(appContext, 2000,
-                     (XtTimerCallbackProc) AnalysisClockCallback,
-                     (XtPointer) 0);
-}
-
-XtIntervalId clockTimerXID = 0;
-
-int
-ClockTimerRunning ()
+DisplayTimerLabel (Option *opt, char *color, long timer, int highlight)
 {
-    return clockTimerXID != 0;
-}
+    GtkWidget *w = (GtkWidget *) opt->handle;
+    char *markup;
+    char bgcolor[10];
+    char fgcolor[10];
 
-int
-StopClockTimer ()
-{
-    if (clockTimerXID != 0) {
-       XtRemoveTimeOut(clockTimerXID);
-       clockTimerXID = 0;
-       return TRUE;
+    if (highlight) {
+       strcpy(bgcolor, "black");
+        strcpy(fgcolor, "white");
     } else {
-       return FALSE;
+        strcpy(bgcolor, "white");
+        strcpy(fgcolor, "black");
     }
-}
-
-void
-ClockTimerCallback (XtPointer arg, XtIntervalId *id)
-{
-    clockTimerXID = 0;
-    DecrementClocks();
-}
-
-void
-StartClockTimer (long millisec)
-{
-    clockTimerXID =
-      XtAppAddTimeOut(appContext, millisec,
-                     (XtTimerCallbackProc) ClockTimerCallback,
-                     (XtPointer) 0);
-}
-
-void
-DisplayTimerLabel (Option *opt, char *color, long timer, int highlight)
-{
-    char buf[MSG_SIZ];
-    Arg args[16];
-    Widget w = (Widget) opt->handle;
-
-    /* check for low time warning */
-    Pixel foregroundOrWarningColor = timerForegroundPixel;
-
     if (timer > 0 &&
         appData.lowTimeWarning &&
-        (timer / 1000) < appData.icsAlarmTime)
-      foregroundOrWarningColor = lowTimeWarningColor;
-
-    if (appData.clockMode) {
-      snprintf(buf, MSG_SIZ, "%s: %s", color, 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);
+    gtk_label_set_markup(GTK_LABEL(w), markup);
+    g_free(markup);
 }
 
+#ifdef TODO_GTK
 static Pixmap *clockIcons[] = { &wIconPixmap, &bIconPixmap };
+#endif
 
 void
 SetClockIcon (int color)
 {
+#ifdef TODO_GTK
     Arg args[16];
     Pixmap pm = *clockIcons[color];
     if (iconPixmap != pm) {
@@ -3380,25 +2287,53 @@ SetClockIcon (int color)
        XtSetArg(args[0], XtNiconPixmap, iconPixmap);
        XtSetValues(shellWidget, args, 1);
     }
+#endif
 }
 
-void
-DoInputCallback (caddr_t closure, int *source, XtInputId *xid)
-{
-    InputSource *is = (InputSource *) closure;
+#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;
+{
+  /* 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;
@@ -3406,12 +2341,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;
@@ -3419,12 +2358,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
 }
 
-InputSourceRef
-AddInputSource (ProcRef pr, int lineByLine, InputCallback func, VOIDSTAR closure)
+InputSourceRef AddInputSource(pr, lineByLine, func, closure)
+     ProcRef pr;
+     int lineByLine;
+     InputCallback func;
+     VOIDSTAR closure;
 {
     InputSource *is;
+    GIOChannel *channel;
     ChildProc *cp = (ChildProc *) pr;
 
     is = (InputSource *) calloc(1, sizeof(InputSource));
@@ -3437,164 +2381,32 @@ AddInputSource (ProcRef pr, int lineByLine, InputCallback func, VOIDSTAR closure
        is->kind = cp->kind;
        is->fd = cp->fdFrom;
     }
-    if (lineByLine) {
-       is->unused = is->buf;
-    }
-
-    is->xid = XtAppAddInput(appContext, is->fd,
-                           (XtPointer) (XtInputReadMask),
-                           (XtInputCallbackProc) DoInputCallback,
-                           (XtPointer) is);
-    is->closure = closure;
-    return (InputSourceRef) is;
-}
-
-void
-RemoveInputSource (InputSourceRef isr)
-{
-    InputSource *is = (InputSource *) isr;
-
-    if (is->xid == 0) return;
-    XtRemoveInput(is->xid);
-    is->xid = 0;
-}
-
-/****  Animation code by Hugh Fisher, DCS, ANU. ****/
-
-/*     Masks for XPM pieces. Black and white pieces can have
-       different shapes, but in the interest of retaining my
-       sanity pieces must have the same outline on both light
-       and dark squares, and all pieces must use the same
-       background square colors/images.                */
-
-static int xpmDone = 0;
-static Pixmap animBufs[3*NrOfAnims]; // newBuf, saveBuf
-static GC animGCs[3*NrOfAnims]; // blitGC, pieceGC, outlineGC;
-
-static void
-CreateAnimMasks (int pieceDepth)
-{
-  ChessSquare   piece;
-  Pixmap       buf;
-  GC           bufGC, maskGC;
-  int          kind, n;
-  unsigned long        plane;
-  XGCValues    values;
-
-  /* Need a bitmap just to get a GC with right depth */
-  buf = XCreatePixmap(xDisplay, xBoardWindow,
-                       8, 8, 1);
-  values.foreground = 1;
-  values.background = 0;
-  /* Don't use XtGetGC, not read only */
-  maskGC = XCreateGC(xDisplay, buf,
-                   GCForeground | GCBackground, &values);
-  XFreePixmap(xDisplay, buf);
-
-  buf = XCreatePixmap(xDisplay, xBoardWindow,
-                     squareSize, squareSize, pieceDepth);
-  values.foreground = XBlackPixel(xDisplay, xScreen);
-  values.background = XWhitePixel(xDisplay, xScreen);
-  bufGC = XCreateGC(xDisplay, buf,
-                   GCForeground | GCBackground, &values);
-
-  for (piece = WhitePawn; piece <= BlackKing; piece++) {
-    /* Begin with empty mask */
-    if(!xpmDone) // [HGM] pieces: keep using existing
-    xpmMask[piece] = XCreatePixmap(xDisplay, xBoardWindow,
-                                squareSize, squareSize, 1);
-    XSetFunction(xDisplay, maskGC, GXclear);
-    XFillRectangle(xDisplay, xpmMask[piece], maskGC,
-                  0, 0, squareSize, squareSize);
-
-    /* Take a copy of the piece */
-    if (White(piece))
-      kind = 0;
+    if (lineByLine)
+      is->unused = is->buf;
     else
-      kind = 2;
-    XSetFunction(xDisplay, bufGC, GXcopy);
-    XCopyArea(xDisplay, xpmPieceBitmap[kind][((int)piece) % (int)BlackPawn],
-             buf, bufGC,
-             0, 0, squareSize, squareSize, 0, 0);
-
-    /* XOR the background (light) over the piece */
-    XSetFunction(xDisplay, bufGC, GXxor);
-    if (useImageSqs)
-      XCopyArea(xDisplay, xpmLightSquare, buf, bufGC,
-               0, 0, squareSize, squareSize, 0, 0);
-    else {
-      XSetForeground(xDisplay, bufGC, lightSquareColor);
-      XFillRectangle(xDisplay, buf, bufGC, 0, 0, squareSize, squareSize);
-    }
+      is->unused = NULL;
 
-    /* We now have an inverted piece image with the background
-       erased. Construct mask by just selecting all the non-zero
-       pixels - no need to reconstruct the original image.     */
-    XSetFunction(xDisplay, maskGC, GXor);
-    plane = 1;
-    /* Might be quicker to download an XImage and create bitmap
-       data from it rather than this N copies per piece, but it
-       only takes a fraction of a second and there is a much
-       longer delay for loading the pieces.            */
-    for (n = 0; n < pieceDepth; n ++) {
-      XCopyPlane(xDisplay, buf, xpmMask[piece], maskGC,
-                0, 0, squareSize, squareSize,
-                0, 0, plane);
-      plane = plane << 1;
-    }
-  }
-  /* Clean up */
-  XFreePixmap(xDisplay, buf);
-  XFreeGC(xDisplay, bufGC);
-  XFreeGC(xDisplay, maskGC);
-}
+   /* GTK-TODO: will this work on windows?*/
 
-static void
-InitAnimState (AnimNr anr, XWindowAttributes *info)
-{
-  XtGCMask  mask;
-  XGCValues values;
-
-  /* Each buffer is square size, same depth as window */
-  animBufs[anr+4] = xBoardWindow;
-  animBufs[anr+2] = XCreatePixmap(xDisplay, xBoardWindow,
-                       squareSize, squareSize, info->depth);
-  animBufs[anr] = XCreatePixmap(xDisplay, xBoardWindow,
-                       squareSize, squareSize, info->depth);
-
-  /* Create a plain GC for blitting */
-  mask = GCForeground | GCBackground | GCFunction |
-         GCPlaneMask | GCGraphicsExposures;
-  values.foreground = XBlackPixel(xDisplay, xScreen);
-  values.background = XWhitePixel(xDisplay, xScreen);
-  values.function   = GXcopy;
-  values.plane_mask = AllPlanes;
-  values.graphics_exposures = False;
-  animGCs[anr] = XCreateGC(xDisplay, xBoardWindow, mask, &values);
-
-  /* Piece will be copied from an existing context at
-     the start of each new animation/drag. */
-  animGCs[anr+2] = XCreateGC(xDisplay, xBoardWindow, 0, &values);
+    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);
 
-  /* Outline will be a read-only copy of an existing */
-  animGCs[anr+4] = None;
+    is->closure = closure;
+    return (InputSourceRef) is;
 }
 
+
 void
-CreateAnimVars ()
+RemoveInputSource(isr)
+     InputSourceRef isr;
 {
-  XWindowAttributes info;
-
-  if (xpmDone && gameInfo.variant == oldVariant) return;
-  if(xpmDone) oldVariant = gameInfo.variant; // first time pieces might not be created yet
-  XGetWindowAttributes(xDisplay, xBoardWindow, &info);
-
-  InitAnimState(Game, &info);
-  InitAnimState(Player, &info);
+    InputSource *is = (InputSource *) isr;
 
-  /* For XPM pieces, we need bitmaps to use as masks. */
-  if (useImages)
-    CreateAnimMasks(info.depth), xpmDone = 1;
+    if (is->sid == 0) return;
+    g_source_remove(is->sid);
+    is->sid = 0;
+    return;
 }
 
 #ifndef HAVE_USLEEP
@@ -3614,8 +2426,6 @@ FrameDelay (int time)
 {
   struct itimerval delay;
 
-  XSync(xDisplay, False);
-
   if (time > 0) {
     frameWaiting = True;
     signal(SIGALRM, FrameAlarm);
@@ -3636,7 +2446,11 @@ FrameDelay (int time)
 void
 FrameDelay (int time)
 {
+#ifdef TODO_GTK
   XSync(xDisplay, False);
+#endif
+//  gtk_main_iteration_do(False);
+
   if (time > 0)
     usleep(time * 1000);
 }
@@ -3644,116 +2458,29 @@ FrameDelay (int time)
 #endif
 
 static void
-SelectGCMask (ChessSquare piece, GC *clip, GC *outline, Pixmap *mask)
-{
-  GC source;
-
-  /* Bitmap for piece being moved. */
-  if (appData.monoMode) {
-      *mask = *pieceToSolid(piece);
-  } else if (useImages) {
-#if HAVE_LIBXPM
-      *mask = xpmMask[piece];
-#else
-      *mask = ximMaskPm[piece];
-#endif
-  } else {
-      *mask = *pieceToSolid(piece);
-  }
-
-  /* GC for piece being moved. Square color doesn't matter, but
-     since it gets modified we make a copy of the original. */
-  if (White(piece)) {
-    if (appData.monoMode)
-      source = bwPieceGC;
-    else
-      source = wlPieceGC;
-  } else {
-    if (appData.monoMode)
-      source = wbPieceGC;
-    else
-      source = blPieceGC;
-  }
-  XCopyGC(xDisplay, source, 0xFFFFFFFF, *clip);
-
-  /* Outline only used in mono mode and is not modified */
-  if (White(piece))
-    *outline = bwPieceGC;
-  else
-    *outline = wbPieceGC;
-}
-
-static void
-OverlayPiece (ChessSquare piece, GC clip, GC outline,  Drawable dest)
-{
-  int  kind;
-
-  if (!useImages) {
-    /* Draw solid rectangle which will be clipped to shape of piece */
-    XFillRectangle(xDisplay, dest, clip,
-                  0, 0, squareSize, squareSize);
-    if (appData.monoMode)
-      /* Also draw outline in contrasting color for black
-        on black / white on white cases                */
-      XCopyPlane(xDisplay, *pieceToOutline(piece), dest, outline,
-                0, 0, squareSize, squareSize, 0, 0, 1);
-  } else {
-    /* Copy the piece */
-    if (White(piece))
-      kind = 0;
-    else
-      kind = 2;
-    if(appData.upsideDown && flipView) kind ^= 2;
-    XCopyArea(xDisplay, xpmPieceBitmap[kind][piece],
-             dest, clip,
-             0, 0, squareSize, squareSize,
-             0, 0);
-  }
-}
-
-void
-InsertPiece (AnimNr anr, ChessSquare piece)
-{
-  OverlayPiece(piece, animGCs[anr+2], animGCs[anr+4], animBufs[anr]);
-}
-
-void
-DrawBlank (AnimNr anr, int x, int y, int startColor)
-{
-    BlankSquare(x, y, startColor, EmptySquare, animBufs[anr+2], 0);
-}
-
-void CopyRectangle (AnimNr anr, int srcBuf, int destBuf,
-                int srcX, int srcY, int width, int height, int destX, int destY)
-{
-    XCopyArea(xDisplay, animBufs[anr+srcBuf], animBufs[anr+destBuf], animGCs[anr],
-               srcX, srcY, width, height, destX, destY);
-}
-
-void
-SetDragPiece (AnimNr anr, ChessSquare piece)
-{
-  Pixmap mask;
-  /* The piece will be drawn using its own bitmap as a matte   */
-  SelectGCMask(piece, &animGCs[anr+2], &animGCs[anr+4], &mask);
-  XSetClipMask(xDisplay, animGCs[anr+2], mask);
-}
-
-/* [AS] Arrow highlighting support */
-
-void
-DrawPolygon (Pnt arrow[], int nr)
-{
-    XPoint pts[10];
-    int i;
-    for(i=0; i<10; i++) pts[i].x = arrow[i].x, pts[i].y = arrow[i].y;
-    XFillPolygon(xDisplay, xBoardWindow, highlineGC, pts, nr, Nonconvex, CoordModeOrigin);
-    if(appData.monoMode) arrow[nr] = arrow[0], XDrawLines(xDisplay, xBoardWindow, darkSquareGC, pts, nr+1, CoordModeOrigin);
+LoadLogo (ChessProgramState *cps, int n, Boolean ics)
+{
+    char buf[MSG_SIZ], *logoName = buf;
+    if(appData.logo[n][0]) {
+       logoName = appData.logo[n];
+    } else if(appData.autoLogo) {
+       if(ics) { // [HGM] logo: in ICS mode second can be used for ICS
+           sprintf(buf, "%s/%s.png", appData.logoDir, appData.icsHost);
+       } else if(appData.directory[n] && appData.directory[n][0]) {
+           sprintf(buf, "%s/%s.png", appData.logoDir, cps->tidy);
+       }
+    }
+    if(logoName[0])
+       { ASSIGN(cps->programLogo, logoName); }
 }
 
 void
 UpdateLogos (int displ)
 {
-    return; // no logos in XBoard yet
+    if(optList[W_WHITE-1].handle == NULL) return;
+    LoadLogo(&first, 0, 0);
+    LoadLogo(&second, 1, appData.icsActive);
+    if(displ) DisplayLogos(&optList[W_WHITE-1], &optList[W_BLACK+1]);
+    return;
 }