Create new (empty) branch for board themes
[xboard.git] / gtk / xboard.c
diff --git a/gtk/xboard.c b/gtk/xboard.c
deleted file mode 100644 (file)
index 5ad75b1..0000000
+++ /dev/null
@@ -1,2518 +0,0 @@
-/*
- * xboard.c -- X front end for XBoard
- *
- * Copyright 1991 by Digital Equipment Corporation, Maynard,
- * Massachusetts.
- *
- * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,
- * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free
- * Software Foundation, Inc.
- *
- * The following terms apply to Digital Equipment Corporation's copyright
- * interest in XBoard:
- * ------------------------------------------------------------------------
- * All Rights Reserved
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted,
- * provided that the above copyright notice appear in all copies and that
- * both that copyright notice and this permission notice appear in
- * supporting documentation, and that the name of Digital not be
- * used in advertising or publicity pertaining to distribution of the
- * software without specific, written prior permission.
- *
- * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- * ------------------------------------------------------------------------
- *
- * The following terms apply to the enhanced version of XBoard
- * distributed by the Free Software Foundation:
- * ------------------------------------------------------------------------
- *
- * GNU XBoard is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or (at
- * your option) any later version.
- *
- * GNU XBoard is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see http://www.gnu.org/licenses/.  *
- *
- *------------------------------------------------------------------------
- ** See the file ChangeLog for a revision history.  */
-
-#define HIGHDRAG 1
-
-#include "config.h"
-
-#include <stdio.h>
-#include <ctype.h>
-#include <signal.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <pwd.h>
-#include <math.h>
-#include <cairo/cairo.h>
-#include <gtk/gtk.h>
-
-#if !OMIT_SOCKETS
-# if HAVE_SYS_SOCKET_H
-#  include <sys/socket.h>
-#  include <netinet/in.h>
-#  include <netdb.h>
-# else /* not HAVE_SYS_SOCKET_H */
-#  if HAVE_LAN_SOCKET_H
-#   include <lan/socket.h>
-#   include <lan/in.h>
-#   include <lan/netdb.h>
-#  else /* not HAVE_LAN_SOCKET_H */
-#   define OMIT_SOCKETS 1
-#  endif /* not HAVE_LAN_SOCKET_H */
-# endif /* not HAVE_SYS_SOCKET_H */
-#endif /* !OMIT_SOCKETS */
-
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <string.h>
-#else /* not STDC_HEADERS */
-extern char *getenv();
-# if HAVE_STRING_H
-#  include <string.h>
-# else /* not HAVE_STRING_H */
-#  include <strings.h>
-# endif /* not HAVE_STRING_H */
-#endif /* not STDC_HEADERS */
-
-#if HAVE_SYS_FCNTL_H
-# include <sys/fcntl.h>
-#else /* not HAVE_SYS_FCNTL_H */
-# if HAVE_FCNTL_H
-#  include <fcntl.h>
-# endif /* HAVE_FCNTL_H */
-#endif /* not HAVE_SYS_FCNTL_H */
-
-#if HAVE_SYS_SYSTEMINFO_H
-# include <sys/systeminfo.h>
-#endif /* HAVE_SYS_SYSTEMINFO_H */
-
-#if TIME_WITH_SYS_TIME
-# include <sys/time.h>
-# include <time.h>
-#else
-# if HAVE_SYS_TIME_H
-#  include <sys/time.h>
-# else
-#  include <time.h>
-# endif
-#endif
-
-#if HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#if HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-
-#if HAVE_DIRENT_H
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-# define HAVE_DIR_STRUCT
-#else
-# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
-# if HAVE_SYS_NDIR_H
-#  include <sys/ndir.h>
-#  define HAVE_DIR_STRUCT
-# endif
-# if HAVE_SYS_DIR_H
-#  include <sys/dir.h>
-#  define HAVE_DIR_STRUCT
-# endif
-# if HAVE_NDIR_H
-#  include <ndir.h>
-#  define HAVE_DIR_STRUCT
-# endif
-#endif
-
-#if ENABLE_NLS
-#include <locale.h>
-#endif
-
-// [HGM] bitmaps: put before incuding the bitmaps / pixmaps, to know how many piece types there are.
-#include "common.h"
-
-#include "frontend.h"
-#include "backend.h"
-#include "backendz.h"
-#include "moves.h"
-#include "xboard.h"
-#include "xboard2.h"
-#include "childio.h"
-#include "menus.h"
-#include "board.h"
-#include "dialogs.h"
-#include "engineoutput.h"
-#include "usystem.h"
-#include "gettext.h"
-#include "draw.h"
-
-#ifdef OSXAPP
-#  include <gtkmacintegration/gtkosxapplication.h>
-   // prevent pathname of positional file argument provided by OS X being be mistaken for option name
-   // (price is that we won't recognize Windows option format anymore).
-#  define SLASH '-'
-#  define IMG ".png"
-   // redefine some defaults
-#  undef ICS_LOGON
-#  undef LOCALEDIR
-#  undef SETTINGS_FILE
-#  define ICS_LOGON "Library/Preferences/XboardICS.conf"
-#  define LOCALEDIR localeDir
-#  define SETTINGS_FILE masterSettings
-#  define SYNC_MENUBAR gtkosx_application_sync_menubar(theApp)
-   char localeDir[MSG_SIZ];
-   char masterSettings[MSG_SIZ];
-#else
-#  define SLASH '/'
-#  define IMG ".svg"
-#  define SYNC_MENUBAR
-#endif
-
-#ifdef __EMX__
-#ifndef HAVE_USLEEP
-#define HAVE_USLEEP
-#endif
-#define usleep(t)   _sleep2(((t)+500)/1000)
-#endif
-
-#ifdef ENABLE_NLS
-# define  _(s) gettext (s)
-# define N_(s) gettext_noop (s)
-#else
-# define  _(s) (s)
-# define N_(s)  s
-#endif
-
-int main P((int argc, char **argv));
-RETSIGTYPE CmailSigHandler P((int sig));
-RETSIGTYPE IntSigHandler P((int sig));
-RETSIGTYPE TermSizeSigHandler P((int sig));
-char *InsertPxlSize P((char *pattern, int targetPxlSize));
-#ifdef TODO_GTK
-#if ENABLE_NLS
-XFontSet CreateFontSet P((char *base_fnt_lst));
-#else
-char *FindFont P((char *pattern, int targetPxlSize));
-#endif
-#endif
-void DelayedDrag P((void));
-void ICSInputBoxPopUp P((void));
-void MoveTypeInProc P((GdkEventKey *eventkey));
-gboolean KeyPressProc P((GtkWindow *window, GdkEventKey *eventkey, gpointer data));
-Boolean TempBackwardActive = False;
-void DisplayMove P((int moveNumber));
-void update_ics_width P(());
-int CopyMemoProc P(());
-static gboolean EventProc P((GtkWidget *widget, GdkEvent *event, gpointer g));
-static int FindLogo P((char *place, char *name, char *buf));
-
-#ifdef TODO_GTK
-#if ENABLE_NLS
-XFontSet fontSet, clockFontSet;
-#else
-Font clockFontID;
-XFontStruct *clockFontStruct;
-#endif
-Font coordFontID, countFontID;
-XFontStruct *coordFontStruct, *countFontStruct;
-#else
-void *shellWidget, *formWidget, *boardWidget, *titleWidget, *dropMenu, *menuBarWidget;
-GtkWidget       *mainwindow;
-#endif
-Option *optList; // contains all widgets of main window
-char *layoutName;
-
-char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
-
-/* pixbufs */
-static GdkPixbuf       *mainwindowIcon=NULL;
-static GdkPixbuf       *WhiteIcon=NULL;
-static GdkPixbuf       *BlackIcon=NULL;
-
-/* key board accelerators */
-GtkAccelGroup *GtkAccelerators;
-
-typedef unsigned int BoardSize;
-BoardSize boardSize;
-Boolean chessProgram;
-int initialSquareSize;
-
-int  minX, minY; // [HGM] placement: volatile limits on upper-left corner
-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;
-#endif
-char *chessDir, *programName, *programVersion;
-Boolean alwaysOnTop = False;
-char *icsTextMenuString;
-char *icsNames;
-char *firstChessProgramNames;
-char *secondChessProgramNames;
-
-WindowPlacement wpMain;
-WindowPlacement wpConsole;
-WindowPlacement wpComment;
-WindowPlacement wpMoveHistory;
-WindowPlacement wpEvalGraph;
-WindowPlacement wpEngineOutput;
-WindowPlacement wpGameList;
-WindowPlacement wpTags;
-WindowPlacement wpDualBoard;
-
-/* 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.  */
-#define kFactor           4
-
-SizeDefaults sizeDefaults[] = SIZE_DEFAULTS;
-
-typedef struct {
-    char piece;
-    char* widget;
-} DropMenuEnables;
-
-DropMenuEnables dmEnables[] = {
-    { 'P', "Pawn" },
-    { 'N', "Knight" },
-    { 'B', "Bishop" },
-    { 'R', "Rook" },
-    { 'Q', "Queen" }
-};
-
-#ifdef TODO_GTK
-XtResource clientResources[] = {
-    { "flashCount", "flashCount", XtRInt, sizeof(int),
-       XtOffset(AppDataPtr, flashCount), XtRImmediate,
-       (XtPointer) FLASH_COUNT  },
-};
-#endif
-
-/* keyboard shortcuts not yet transistioned int menuitem @ menu.c */
-char globalTranslations[] =
-  ":Ctrl<Key>Down: LoadSelectedProc(3) \n \
-   :Ctrl<Key>Up: LoadSelectedProc(-3) \n \
-   :<KeyDown>Return: TempBackwardProc() \n \
-   :<KeyUp>Return: TempForwardProc() \n";
-
-char ICSInputTranslations[] =
-    "<Key>Up: UpKeyProc() \n "
-    "<Key>Down: DownKeyProc() \n "
-    "<Key>Return: EnterKeyProc() \n";
-
-// [HGM] vari: another hideous kludge: call extend-end first so we can be sure select-start works,
-//             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
-
-void
-BoardToTop ()
-{
-  gtk_window_present(GTK_WINDOW(shells[BoardWindow]));
-}
-
-//---------------------------------------------------------------------------------------------------------
-// some symbol definitions to provide the proper (= XBoard) context for the code in args.h
-#define XBOARD True
-#define JAWS_ARGS
-#define CW_USEDEFAULT (1<<31)
-#define ICS_TEXT_MENU_SIZE 90
-#define DEBUG_FILE "xboard.debug"
-#define SetCurrentDirectory chdir
-#define GetCurrentDirectory(SIZE, NAME) getcwd(NAME, SIZE)
-#define OPTCHAR "-"
-#define SEPCHAR " "
-
-// The option definition and parsing code common to XBoard and WinBoard is collected in this file
-#include "args.h"
-
-// front-end part of option handling
-
-// [HGM] This platform-dependent table provides the location for storing the color info
-extern char *crWhite, * crBlack;
-
-void *
-colorVariable[] = {
-  &appData.whitePieceColor,
-  &appData.blackPieceColor,
-  &appData.lightSquareColor,
-  &appData.darkSquareColor,
-  &appData.highlightSquareColor,
-  &appData.premoveHighlightColor,
-  &appData.lowTimeWarningColor,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  &crWhite,
-  &crBlack,
-  NULL
-};
-
-// [HGM] font: keep a font for each square size, even non-stndard ones
-#define NUM_SIZES 18
-Boolean fontIsSet[NUM_FONTS], fontValid[NUM_FONTS][MAX_SIZE];
-char *fontTable[NUM_FONTS][MAX_SIZE];
-
-void
-ParseFont (char *name, int number)
-{ // in XBoard, only 2 of the fonts are currently implemented, and we just copy their name
-  int size;
-  if(sscanf(name, "size%d:", &size)) {
-    // [HGM] font: font is meant for specific boardSize (likely from settings file);
-    //       defer processing it until we know if it matches our board size
-    if(!strstr(name, "-*-") &&       // ignore X-fonts
-       size >= 0 && size<MAX_SIZE) { // for now, fixed limit
-       fontTable[number][size] = strdup(strchr(name, ':')+1);
-       fontValid[number][size] = True;
-    }
-    return;
-  }
-  switch(number) {
-    case 0: // CLOCK_FONT
-       appData.clockFont = strdup(name);
-      break;
-    case 1: // MESSAGE_FONT
-       appData.font = strdup(name);
-      break;
-    case 2: // COORD_FONT
-       appData.coordFont = strdup(name);
-      break;
-    case CONSOLE_FONT:
-       appData.icsFont = strdup(name);
-      break;
-    case EDITTAGS_FONT:
-       appData.tagsFont = strdup(name);
-      break;
-    case COMMENT_FONT:
-       appData.commentFont = strdup(name);
-      break;
-    case MOVEHISTORY_FONT:
-       appData.historyFont = strdup(name);
-      break;
-    case GAMELIST_FONT:
-       appData.gameListFont = strdup(name);
-      break;
-    default:
-      return;
-  }
-  fontIsSet[number] = True; // [HGM] font: indicate a font was specified (not from settings file)
-}
-
-void
-SetFontDefaults ()
-{ // only 2 fonts currently
-  appData.clockFont = strdup(CLOCK_FONT_NAME);
-  appData.coordFont = strdup(COORD_FONT_NAME);
-  appData.font  =   strdup(DEFAULT_FONT_NAME);
-  appData.icsFont = strdup(CONSOLE_FONT_NAME);
-  appData.tagsFont = strdup(TAGS_FONT_NAME);
-  appData.commentFont = strdup(COMMENT_FONT_NAME);
-  appData.historyFont = strdup(HISTORY_FONT_NAME);
-  appData.gameListFont = strdup(GAMELIST_FONT_NAME);
-}
-
-void
-ChangeFont (int force, char **font, int fnr, int size, char *def, int pix)
-{
-    if(!fontValid[fnr][size]) {
-       if(fontIsSet[fnr] && !force) return; // unless forced we do not replace an explicitly specified font by a default
-       ASSIGN(fontTable[fnr][size], def);   // use default
-       fontIsSet[fnr] = False;
-    } else fontIsSet[fnr] = True;
-    FREE(*font); *font = InsertPxlSize(fontTable[fnr][size], pix);
-}
-
-void
-CreateFonts ()
-{ // no-op, until we identify the code for this already in XBoard and move it here
-}
-
-void
-ParseColor (int n, char *name)
-{ // in XBoard, just copy the color-name string
-  if(colorVariable[n] && *name == '#') *(char**)colorVariable[n] = strdup(name);
-}
-
-char *
-Col2Text (int n)
-{
-    return *(char**)colorVariable[n];
-}
-
-void
-ParseTextAttribs (ColorClass cc, char *s)
-{
-    (&appData.colorShout)[cc] = strdup(s);
-}
-
-void
-ParseBoardSize (void *addr, char *name)
-{
-    appData.boardSize = strdup(name);
-}
-
-void
-LoadAllSounds ()
-{ // In XBoard the sound-playing program takes care of obtaining the actual sound
-}
-
-void
-SetCommPortDefaults ()
-{ // for now, this is a no-op, as the corresponding option does not exist in XBoard
-}
-
-// [HGM] args: these three cases taken out to stay in front-end
-void
-SaveFontArg (FILE *f, ArgDescriptor *ad)
-{
-  char *name;
-  int i, n = (int)(intptr_t)ad->argLoc;
-  switch(n) {
-    case 0: // CLOCK_FONT
-       name = appData.clockFont;
-      break;
-    case 1: // MESSAGE_FONT
-       name = appData.font;
-      break;
-    case 2: // COORD_FONT
-       name = appData.coordFont;
-      break;
-    case CONSOLE_FONT:
-       name = appData.icsFont;
-      break;
-    case EDITTAGS_FONT:
-       name = appData.tagsFont;
-      break;
-    case COMMENT_FONT:
-       name = appData.commentFont;
-      break;
-    case MOVEHISTORY_FONT:
-       name = appData.historyFont;
-      break;
-    case GAMELIST_FONT:
-       name = appData.gameListFont;
-      break;
-    default:
-      return;
-  }
-  if(fontIsSet[n])           // only save fonts that were not defaults
-  for(i=0; i<NUM_SIZES; i++) // [HGM] font: current font becomes standard for current size
-    if(sizeDefaults[i].squareSize == initialSquareSize) { // only for standard sizes!
-       ASSIGN(fontTable[n][initialSquareSize], name);
-       fontValid[n][initialSquareSize] = True;
-       break;
-  }
-  for(i=0; i<MAX_SIZE; i++) if(fontValid[n][i]) // [HGM] font: store all standard fonts
-    fprintf(f, OPTCHAR "%s" SEPCHAR "\"size%d:%s\"\n", ad->argName, i, fontTable[n][i]);
-}
-
-void
-ExportSounds ()
-{ // nothing to do, as the sounds are at all times represented by their text-string names already
-}
-
-void
-SaveAttribsArg (FILE *f, ArgDescriptor *ad)
-{      // here the "argLoc" defines a table index. It could have contained the 'ta' pointer itself, though
-       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, (&appData.colorShout)[(int)(intptr_t)ad->argLoc]);
-}
-
-void
-SaveColor (FILE *f, ArgDescriptor *ad)
-{      // in WinBoard the color is an int and has to be converted to text. In X it would be a string already?
-       if(colorVariable[(int)(intptr_t)ad->argLoc])
-       fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", ad->argName, *(char**)colorVariable[(int)(intptr_t)ad->argLoc]);
-}
-
-void
-SaveBoardSize (FILE *f, char *name, void *addr)
-{ // wrapper to shield back-end from BoardSize & sizeInfo
-  fprintf(f, OPTCHAR "%s" SEPCHAR "%s\n", name, appData.boardSize);
-}
-
-void
-ParseCommPortSettings (char *s)
-{ // no such option in XBoard (yet)
-}
-
-int frameX, frameY;
-
-void
-GetActualPlacement (GtkWidget *shell, WindowPlacement *wp)
-{
-  GtkAllocation a;
-  if(!shell) return;
-  gtk_widget_get_allocation(shell, &a);
-  gtk_window_get_position(GTK_WINDOW(shell), &a.x, &a.y);
-  wp->x = a.x;
-  wp->y = a.y;
-  wp->width = a.width;
-  wp->height = a.height;
-//printf("placement: (%d,%d) %dx%d\n", a.x, a.y, a.width, a.height);
-  frameX = 3; frameY = 3; // remember to decide if windows touch
-}
-
-void
-GetPlacement (DialogClass dlg, WindowPlacement *wp)
-{ // wrapper to shield back-end from widget type
-  if(shellUp[dlg]) GetActualPlacement(shells[dlg], wp);
-}
-
-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
-  GetActualPlacement(shellWidget, &wpMain);
-  if(shellUp[EngOutDlg]) GetActualPlacement(shells[EngOutDlg], &wpEngineOutput);
-  if(shellUp[HistoryDlg]) GetActualPlacement(shells[HistoryDlg], &wpMoveHistory);
-  if(shellUp[EvalGraphDlg]) GetActualPlacement(shells[EvalGraphDlg], &wpEvalGraph);
-  if(shellUp[GameListDlg]) GetActualPlacement(shells[GameListDlg], &wpGameList);
-  if(shellUp[CommentDlg]) GetActualPlacement(shells[CommentDlg], &wpComment);
-  if(shellUp[TagsDlg]) GetActualPlacement(shells[TagsDlg], &wpTags);
-  GetPlacement(ChatDlg, &wpConsole); if(appData.icsActive) wpConsole.visible = shellUp[ChatDlg];
-}
-
-void
-PrintCommPortSettings (FILE *f, char *name)
-{ // This option does not exist in XBoard
-}
-
-void
-EnsureOnScreen (int *x, int *y, int minX, int minY)
-{
-  return;
-}
-
-int
-MainWindowUp ()
-{ // [HGM] args: allows testing if main window is realized from back-end
-  return DialogExists(BoardWindow);
-}
-
-void
-PopUpStartupDialog ()
-{  // start menu not implemented in XBoard
-}
-
-char *
-ConvertToLine (int argc, char **argv)
-{
-  static char line[128*1024], buf[1024];
-  int i;
-
-  line[0] = NULLCHAR;
-  for(i=1; i<argc; i++)
-    {
-      if( (strchr(argv[i], ' ') || strchr(argv[i], '\n') ||strchr(argv[i], '\t') || argv[i][0] == NULLCHAR)
-         && argv[i][0] != '{' )
-       snprintf(buf, sizeof(buf)/sizeof(buf[0]), "{%s} ", argv[i]);
-      else
-       snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s ", argv[i]);
-      strncat(line, buf, 128*1024 - strlen(line) - 1 );
-    }
-
-  line[strlen(line)-1] = NULLCHAR;
-  return line;
-}
-
-//--------------------------------------------------------------------------------------------
-
-int clockKludge;
-
-void
-ResizeBoardWindow (int w, int h, int inhibit)
-{
-    GtkAllocation a;
-    int bw;
-//    if(clockKludge) return; // ignore as long as clock does not have final height
-    gtk_widget_get_allocation(optList[W_BOARD].handle, &a);
-    bw = a.width;
-    gtk_widget_get_allocation(shellWidget, &a);
-    marginW = a.width - bw;
-    gtk_widget_get_allocation(optList[W_WHITE].handle, &a);
-    gtk_widget_set_size_request(optList[W_BOARD].handle, w, h);   // protect board widget
-//    w += marginW + 1; // [HGM] not sure why the +1 is (sometimes) needed...
-//    h += marginH + a.height + 1;
-    gtk_window_resize(GTK_WINDOW(shellWidget), w, 10);
-    DoEvents();
-    gtk_widget_set_size_request(optList[W_BOARD].handle, 100, 100); // liberate board again
-}
-
-int
-MakeColors ()
-{   // dummy, as the GTK code does not make colors in advance
-    return FALSE;
-}
-
-void
-InitializeFonts (int clockFontPxlSize, int coordFontPxlSize, int fontPxlSize)
-{   // determine what fonts to use, and create them
-
-    if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
-       appData.clockFont = fontTable[CLOCK_FONT][squareSize], fontIsSet[CLOCK_FONT] = True;
-    if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
-       appData.font = fontTable[MESSAGE_FONT][squareSize], fontIsSet[MESSAGE_FONT] = True;
-    if(!fontIsSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
-       appData.coordFont = fontTable[COORD_FONT][squareSize], fontIsSet[COORD_FONT] = True;
-    if(!fontIsSet[CONSOLE_FONT] && fontValid[CONSOLE_FONT][squareSize])
-       appData.icsFont = fontTable[CONSOLE_FONT][squareSize], fontIsSet[CONSOLE_FONT] = True;
-    if(!fontIsSet[EDITTAGS_FONT] && fontValid[EDITTAGS_FONT][squareSize])
-       appData.tagsFont = fontTable[EDITTAGS_FONT][squareSize], fontIsSet[EDITTAGS_FONT] = True;
-    if(!fontIsSet[COMMENT_FONT] && fontValid[COMMENT_FONT][squareSize])
-       appData.commentFont = fontTable[COMMENT_FONT][squareSize], fontIsSet[COMMENT_FONT] = True;
-    if(!fontIsSet[MOVEHISTORY_FONT] && fontValid[MOVEHISTORY_FONT][squareSize])
-       appData.historyFont = fontTable[MOVEHISTORY_FONT][squareSize], fontIsSet[MOVEHISTORY_FONT] = True;
-    if(!fontIsSet[GAMELIST_FONT] && fontValid[GAMELIST_FONT][squareSize])
-       appData.gameListFont = fontTable[GAMELIST_FONT][squareSize], fontIsSet[GAMELIST_FONT] = True;
-
-    appData.font = InsertPxlSize(appData.font, coordFontPxlSize);
-    appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
-    appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
-    appData.icsFont = InsertPxlSize(appData.icsFont, coordFontPxlSize);
-    appData.tagsFont = InsertPxlSize(appData.tagsFont, coordFontPxlSize);
-    appData.commentFont = InsertPxlSize(appData.commentFont, coordFontPxlSize);
-    appData.historyFont = InsertPxlSize(appData.historyFont, coordFontPxlSize);
-    appData.gameListFont = InsertPxlSize(appData.gameListFont, coordFontPxlSize);
-
-#ifdef TODO_GTK
-    XrmValue vTo;
-    XrmDatabase xdb;
-
-    if(!fontIsSet[CLOCK_FONT] && fontValid[CLOCK_FONT][squareSize])
-       appData.clockFont = fontTable[CLOCK_FONT][squareSize];
-    if(!fontIsSet[MESSAGE_FONT] && fontValid[MESSAGE_FONT][squareSize])
-       appData.font = fontTable[MESSAGE_FONT][squareSize];
-    if(!fontIsSet[COORD_FONT] && fontValid[COORD_FONT][squareSize])
-       appData.coordFont = fontTable[COORD_FONT][squareSize];
-
-#if ENABLE_NLS
-    appData.font = InsertPxlSize(appData.font, fontPxlSize);
-    appData.clockFont = InsertPxlSize(appData.clockFont, clockFontPxlSize);
-    appData.coordFont = InsertPxlSize(appData.coordFont, coordFontPxlSize);
-    fontSet = CreateFontSet(appData.font);
-    clockFontSet = CreateFontSet(appData.clockFont);
-    {
-      /* For the coordFont, use the 0th font of the fontset. */
-      XFontSet coordFontSet = CreateFontSet(appData.coordFont);
-      XFontStruct **font_struct_list;
-      XFontSetExtents *fontSize;
-      char **font_name_list;
-      XFontsOfFontSet(coordFontSet, &font_struct_list, &font_name_list);
-      coordFontID = XLoadFont(xDisplay, font_name_list[0]);
-      coordFontStruct = XQueryFont(xDisplay, coordFontID);
-      fontSize = XExtentsOfFontSet(fontSet); // [HGM] figure out how much vertical space font takes
-      textHeight = fontSize->max_logical_extent.height + 5; // add borderWidth
-    }
-#else
-    appData.font = FindFont(appData.font, fontPxlSize);
-    appData.clockFont = FindFont(appData.clockFont, clockFontPxlSize);
-    appData.coordFont = FindFont(appData.coordFont, coordFontPxlSize);
-    clockFontID = XLoadFont(xDisplay, appData.clockFont);
-    clockFontStruct = XQueryFont(xDisplay, clockFontID);
-    coordFontID = XLoadFont(xDisplay, appData.coordFont);
-    coordFontStruct = XQueryFont(xDisplay, coordFontID);
-    // textHeight in !NLS mode!
-#endif
-    countFontID = coordFontID;  // [HGM] holdings
-    countFontStruct = coordFontStruct;
-
-    xdb = XtDatabase(xDisplay);
-#if ENABLE_NLS
-    XrmPutLineResource(&xdb, "*international: True");
-    vTo.size = sizeof(XFontSet);
-    vTo.addr = (XtPointer) &fontSet;
-    XrmPutResource(&xdb, "*fontSet", XtRFontSet, &vTo);
-#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 ArgBackupSettingsFile:
-    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:
-    default:
-      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);
-}
-
-void
-SlaveResize (Option *opt)
-{
-    static int slaveW, slaveH, w, h;
-    GtkAllocation a;
-    if(!slaveH) {
-       gtk_widget_get_allocation(shells[DummyDlg], &a);
-       w = a.width; h = a.height;
-       gtk_widget_get_allocation(opt->handle, &a);
-       slaveW =  w - opt->max; // [HGM] needed to set new shellWidget size when we resize board
-       slaveH =  h - a.height + 13;
-   }
-  gtk_window_resize(GTK_WINDOW(shells[DummyDlg]), slaveW + opt->max, slaveH + opt->value);
-}
-
-GdkPixbuf *
-LoadIconFile (gchar *svgFilename)
-{
-    char buf[MSG_SIZ];
-
-    snprintf(buf, MSG_SIZ, "%s/%s" IMG, svgDir, svgFilename);
-    return gdk_pixbuf_new_from_file(buf, NULL);
-}
-
-#ifdef OSXAPP
-static char clickedFile[MSG_SIZ];
-TimeMark started;
-
-static gboolean
-StartNewXBoard(GtkosxApplication *app, gchar *path, gpointer user_data)
-{ // handler of OSX OpenFile signal, which sends us the filename of clicked file or first argument
-    TimeMark now;
-    GetTimeMark(&now);
-    if(1000*now.sec + now.ms - 1000*started.sec - started.ms < 1000) { // received during first second
-        strncpy(clickedFile, path, MSG_SIZ); // remember file name, but otherwise ignore
-    } else {       // we are running something presumably useful
-        char buf[MSG_SIZ];
-        snprintf(buf, MSG_SIZ, "open -n -a \"xboard\" --args \"%s\"", path);
-        system(buf); // start new instance on this file
-    }
-    return TRUE;
-}
-
-GtkosxApplication *theApp;
-#endif
-
-int
-main (int argc, char **argv)
-{
-    int i, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
-    int boardWidth, w, h; //, boardHeight;
-    char *p;
-    int forceMono = False;
-
-    srandom(time(0)); // [HGM] book: make random truly random
-
-    setbuf(stdout, NULL);
-    setbuf(stderr, NULL);
-    debugFP = stderr;
-
-    if(argc > 1 && (!strcmp(argv[1], "-v" ) || !strcmp(argv[1], "--version" ))) {
-        printf("%s version %s\n\n  configure options: %s\n", PACKAGE_NAME, PACKAGE_VERSION, CONFIGURE_OPTIONS);
-       exit(0);
-    }
-
-    if(argc > 1 && !strcmp(argv[1], "--help" )) {
-       PrintOptions();
-       exit(0);
-    }
-
-    /* set up GTK */
-    gtk_init (&argc, &argv);
-#ifdef OSXAPP
-    {   // prepare to catch OX OpenFile signal, which will tell us the clicked file
-        char *path = gtkosx_application_get_bundle_path();
-#ifdef ENABLE_NLS
-        char *res_path = gtkosx_application_get_resource_path();
-        snprintf(localeDir, MSG_SIZ, "%s/share/locale", res_path); // redefine locale dir for OSX bundle
-#endif
-        GetTimeMark(&started); // remember start time
-        theApp = g_object_new(GTKOSX_TYPE_APPLICATION, NULL);
-        snprintf(masterSettings, MSG_SIZ, "%s/Contents/Resources/etc/xboard.conf", path);
-        snprintf(dataDir, MSG_SIZ, "%s/Contents/Resources/share/xboard", path);
-        snprintf(manDir, MSG_SIZ, "%s/Contents/Resources/share/man", path);
-        snprintf(svgDir, MSG_SIZ, "%s/themes/default", dataDir);
-        g_signal_connect(theApp, "NSApplicationOpenFile", G_CALLBACK(StartNewXBoard), NULL);
-        g_signal_connect(theApp, "NSApplicationWillTerminate", G_CALLBACK(ExitEvent), NULL);
-        // we must call application ready before we can get the signal,
-        // and supply a (dummy) menu bar before that, to avoid problems with dual apples in it
-        gtkosx_application_set_menu_bar(theApp, GTK_MENU_SHELL(gtk_menu_bar_new()));
-        gtkosx_application_ready(theApp);
-        if(argc == 1) {                  // called without args: OSX open-file signal might follow
-            static char *fakeArgv[3] = {NULL, clickedFile, NULL};
-            usleep(10000);               // wait 10 msec (and hope this is long enough).
-            while(gtk_events_pending())
-            gtk_main_iteration();    // process all events that came in upto now
-            if(clickedFile[0]) {         // we were sent an open-file signal with filename!
-                fakeArgv[0] = argv[0];
-                argc = 2; argv = fakeArgv; // fake that we were called as "xboard filename"
-            }
-        }
-    }
-#endif
-
-    if(argc > 1 && !strcmp(argv[1], "--show-config")) { // [HGM] install: called to print config info
-       typedef struct {char *name, *value; } Config;
-       static Config configList[] = {
-         { "Datadir", dataDir },
-         { "Mandir", manDir },
-         { "Sysconfdir", SYSCONFDIR },
-         { NULL }
-       };
-       int i;
-
-       for(i=0; configList[i].name; i++) {
-           if(argc > 2 && strcmp(argv[2], configList[i].name)) continue;
-           if(argc > 2) printf("%s", configList[i].value);
-           else printf("%-12s: %s\n", configList[i].name, configList[i].value);
-       }
-       exit(0);
-    }
-
-    /* set up keyboard accelerators group */
-    GtkAccelerators = gtk_accel_group_new();
-
-    programName = strrchr(argv[0], '/');
-    if (programName == NULL)
-      programName = argv[0];
-    else
-      programName++;
-
-#ifdef ENABLE_NLS
-//    if (appData.debugMode) {
-//      fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
-//    }
-
-    bindtextdomain(PACKAGE, LOCALEDIR);
-    bind_textdomain_codeset(PACKAGE, "UTF-8"); // needed when creating markup for the clocks
-    textdomain(PACKAGE);
-#endif
-
-    appData.boardSize = "";
-    InitAppData(ConvertToLine(argc, argv));
-    p = getenv("HOME");
-    if (p == NULL) p = "/tmp";
-    i = strlen(p) + strlen("/.xboardXXXXXx.pgn") + 1;
-    gameCopyFilename = (char*) malloc(i);
-    gamePasteFilename = (char*) malloc(i);
-    snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
-    snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
-
-    { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
-       static char buf[MSG_SIZ];
-       snprintf(buf, MSG_SIZ, appData.sysOpen, dataDir);
-       ASSIGN(appData.sysOpen, buf); // expand %s in -openCommand to DATADIR (usefull for OS X configuring)
-       EscapeExpand(buf, appData.firstInitString);
-       appData.firstInitString = strdup(buf);
-       EscapeExpand(buf, appData.secondInitString);
-       appData.secondInitString = strdup(buf);
-       EscapeExpand(buf, appData.firstComputerString);
-       appData.firstComputerString = strdup(buf);
-       EscapeExpand(buf, appData.secondComputerString);
-       appData.secondComputerString = strdup(buf);
-    }
-
-    if ((chessDir = (char *) getenv("CHESSDIR")) == NULL) {
-       chessDir = ".";
-    } else {
-       if (chdir(chessDir) != 0) {
-           fprintf(stderr, _("%s: can't cd to CHESSDIR: "), programName);
-           perror(chessDir);
-           exit(1);
-       }
-    }
-
-    if (appData.debugMode && appData.nameOfDebugFile && strcmp(appData.nameOfDebugFile, "stderr")) {
-       /* [DM] debug info to file [HGM] make the filename a command-line option, and allow it to remain stderr */
-        if ((debugFP = fopen(appData.nameOfDebugFile, "w")) == NULL)  {
-           printf(_("Failed to open file '%s'\n"), appData.nameOfDebugFile);
-           exit(errno);
-        }
-        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   )
-        DisplayFatalError(_("Recompile with larger BOARD_RANKS or BOARD_FILES to support this size"), 0, 2);
-
-#if !HIGHDRAG
-    /* This feature does not work; animation needs a rewrite */
-    appData.highlightDragging = FALSE;
-#endif
-    InitBackEnd1();
-
-       gameInfo.variant = StringToVariant(appData.variant);
-       InitPosition(FALSE);
-
-    /*
-     * determine size, based on supplied or remembered -size, or screen size
-     */
-    if (isdigit(appData.boardSize[0])) {
-        i = sscanf(appData.boardSize, "%d,%d,%d,%d,%d,%d,%d", &squareSize,
-                  &lineGap, &clockFontPxlSize, &coordFontPxlSize,
-                  &fontPxlSize, &smallLayout, &tinyLayout);
-        if (i == 0) {
-           fprintf(stderr, _("%s: bad boardSize syntax %s\n"),
-                   programName, appData.boardSize);
-           exit(2);
-       }
-       if (i < 7) {
-           /* Find some defaults; use the nearest known size */
-           SizeDefaults *szd, *nearest;
-           int distance = 99999;
-           nearest = szd = sizeDefaults;
-           while (szd->name != NULL) {
-               if (abs(szd->squareSize - squareSize) < distance) {
-                   nearest = szd;
-                   distance = abs(szd->squareSize - squareSize);
-                   if (distance == 0) break;
-               }
-               szd++;
-           }
-           if (i < 2) lineGap = nearest->lineGap;
-           if (i < 3) clockFontPxlSize = nearest->clockFontPxlSize;
-           if (i < 4) coordFontPxlSize = nearest->coordFontPxlSize;
-           if (i < 5) fontPxlSize = nearest->fontPxlSize;
-           if (i < 6) smallLayout = nearest->smallLayout;
-           if (i < 7) tinyLayout = nearest->tinyLayout;
-       }
-    } else {
-        SizeDefaults *szd = sizeDefaults;
-        if (*appData.boardSize == NULLCHAR) {
-//            GdkScreen *screen = gtk_window_get_screen(GTK_WINDOW(mainwindow)); // TODO: this does not work, as no mainwindow yet
-            GdkScreen *screen = gdk_screen_get_default();
-            guint screenwidth = gdk_screen_get_width(screen);
-            guint screenheight = gdk_screen_get_height(screen);
-           while (screenwidth  < (szd->minScreenSize*BOARD_WIDTH  + 4)/8 ||
-                  screenheight < (szd->minScreenSize*BOARD_HEIGHT + 4)/8) {
-             szd++;
-           }
-           if (szd->name == NULL) szd--;
-           appData.boardSize = strdup(szd->name); // [HGM] settings: remember name for saving settings
-       } else {
-           while (szd->name != NULL &&
-                  StrCaseCmp(szd->name, appData.boardSize) != 0) szd++;
-           if (szd->name == NULL) {
-               fprintf(stderr, _("%s: unrecognized boardSize name %s\n"),
-                       programName, appData.boardSize);
-               exit(2);
-           }
-       }
-       squareSize = szd->squareSize;
-       lineGap = szd->lineGap;
-       clockFontPxlSize = szd->clockFontPxlSize;
-       coordFontPxlSize = szd->coordFontPxlSize;
-       fontPxlSize = szd->fontPxlSize;
-       smallLayout = szd->smallLayout;
-       tinyLayout = szd->tinyLayout;
-       // [HGM] font: use defaults from settings file if available and not overruled
-    }
-    initialSquareSize = squareSize; // [HGM] remember for saving font info
-    if(BOARD_WIDTH != 8) {
-       squareSize = (squareSize*8 + BOARD_WIDTH/2)/BOARD_WIDTH; // keep width the same
-       lineGap = (squareSize < 37 ? 1 : squareSize < 59 ? 2 : squareSize < 116 ? 3 : 4);
-    }
-
-    defaultLineGap = lineGap;
-    if(appData.overrideLineGap >= 0) lineGap = appData.overrideLineGap;
-
-    /* [HR] height treated separately (hacked) */
-    boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
-//    boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
-
-    /*
-     * Determine what fonts to use.
-     */
-    InitializeFonts((2*clockFontPxlSize+1)/3, coordFontPxlSize, fontPxlSize);
-
-    /*
-     * Detect if there are not enough colors available and adapt.
-     */
-#ifdef TODO_GTK
-    if (DefaultDepth(xDisplay, xScreen) <= 2) {
-      appData.monoMode = True;
-    }
-#endif
-
-    forceMono = MakeColors();
-
-    if (forceMono) {
-      fprintf(stderr, _("%s: too few colors available; trying monochrome mode\n"),
-             programName);
-       appData.monoMode = True;
-    }
-
-    ParseIcsTextColors();
-
-    /*
-     * widget hierarchy
-     */
-    if (tinyLayout) {
-       layoutName = "tinyLayout";
-    } else if (smallLayout) {
-       layoutName = "smallLayout";
-    } else {
-       layoutName = "normalLayout";
-    }
-
-    if(appData.logoSize) appData.logoSize = boardWidth/4-3;
-    wpMain.width = -1; // prevent popup sizes window
-    optList = BoardPopUp(squareSize, lineGap, (void*)
-#ifdef TODO_GTK
-#if ENABLE_NLS
-                                               &clockFontSet);
-#else
-                                               clockFontStruct);
-#endif
-#else
-0);
-#endif
-    InitDrawingHandle(optList + W_BOARD);
-    shellWidget      = shells[BoardWindow];
-    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 != Skip ? W_TITLE : W_SMALL].handle;
-#ifdef TODO_GTK
-    formWidget  = XtParent(boardWidget);
-    XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
-    XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
-    XtGetValues(optList[W_WHITE].handle, args, 2);
-    if (appData.showButtonBar) { // can't we use timer pixels for this? (Or better yet, just black & white?)
-      XtSetArg(args[0], XtNbackground, &buttonBackgroundPixel);
-      XtSetArg(args[1], XtNforeground, &buttonForegroundPixel);
-      XtGetValues(optList[W_PAUSE].handle, args, 2);
-    }
-#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().
-
-    InitMenuMarkers();
-
-    // add accelerators to main shell
-    gtk_window_add_accel_group(GTK_WINDOW(shellWidget), GtkAccelerators);
-
-    /*
-     * Create an icon. (Use two icons, to indicate whther it is white's or black's turn.)
-     */
-    WhiteIcon  = LoadIconFile("icon_white");
-    BlackIcon  = LoadIconFile("icon_black");
-    SetClockIcon(0); // sets white icon
-
-
-    /*
-     * 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);
-#endif
-    {
-       // Note: We cannot do sensible sizing here, because the height of the clock widget is not yet known
-       // It wil only become known asynchronously, when we first write a string into it.
-       // This will then change the clock widget height, which triggers resizing the top-level window
-       // and a configure event. Only then can we know the total height of the top-level window,
-       // and calculate the height we need. The clockKludge flag suppresses all resizing until
-       // that moment comes, after which the configure event-handler handles it through a (delayed) DragProg.
-       int hc;
-       GtkAllocation a;
-       gtk_widget_get_allocation(shells[BoardWindow], &a);
-       w = a.width; h = a.height;
-       gtk_widget_get_allocation(optList[W_WHITE].handle, &a);
-       clockKludge = hc = a.height;
-       gtk_widget_get_allocation(boardWidget, &a);
-       marginW =  w - boardWidth; // [HGM] needed to set new shellWidget size when we resize board
-       marginH =  h - a.height - hc; // subtract current clock height, so it can be added back dynamically
-    }
-
-    CreateAnyPieces(1);
-    CreateGrid();
-
-    if(appData.logoSize)
-    {   // locate and read user logo
-       char buf[MSG_SIZ], name[MSG_SIZ];
-       snprintf(name, MSG_SIZ, "/home/%s", UserName());
-       if(!FindLogo(name, ".logo", buf))
-           FindLogo(appData.logoDir, name + 6, buf);
-       ASSIGN(userLogo, buf);
-    }
-
-    if (appData.animate || appData.animateDragging)
-      CreateAnimVars();
-
-    g_signal_connect(shells[BoardWindow], "key-press-event", G_CALLBACK(KeyPressProc), NULL);
-    g_signal_connect(shells[BoardWindow], "configure-event", G_CALLBACK(EventProc), NULL);
-
-    /* [AS] Restore layout */
-    if( wpMoveHistory.visible ) {
-      HistoryPopUp();
-    }
-
-    if( wpEvalGraph.visible )
-      {
-       EvalGraphPopUp();
-      };
-
-    if( wpEngineOutput.visible ) {
-      EngineOutputPopUp();
-    }
-
-    if( wpConsole.visible && appData.icsActive ) {
-      ChatProc();
-      BoardToTop();
-    }
-
-    gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
-    InitPosition(TRUE);
-
-    InitBackEnd2();
-
-    if (errorExitStatus == -1) {
-       if (appData.icsActive) {
-           /* We now wait until we see "login:" from the ICS before
-              sending the logon script (problems with timestamp otherwise) */
-           /*ICSInitScript();*/
-           if (appData.icsInputBox) ICSInputBoxPopUp();
-       }
-
-    #ifdef SIGWINCH
-    signal(SIGWINCH, TermSizeSigHandler);
-    #endif
-       signal(SIGINT, IntSigHandler);
-       signal(SIGTERM, IntSigHandler);
-       if (*appData.cmailGameName != NULLCHAR) {
-           signal(SIGUSR1, CmailSigHandler);
-       }
-    }
-
-    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();
-}
-
-    if (appData.debugMode) fclose(debugFP); // [DM] debug
-    return 0;
-}
-
-void
-DoEvents ()
-{
-    while(gtk_events_pending()) gtk_main_iteration();
-}
-
-RETSIGTYPE
-TermSizeSigHandler (int sig)
-{
-    update_ics_width();
-}
-
-RETSIGTYPE
-IntSigHandler (int sig)
-{
-    ExitEvent(sig);
-}
-
-RETSIGTYPE
-CmailSigHandler (int sig)
-{
-    int dummy = 0;
-    int error;
-
-    signal(SIGUSR1, SIG_IGN);  /* suspend handler     */
-
-    /* Activate call-back function CmailSigHandlerCallBack()             */
-    OutputToProcess(cmailPR, (char *)(&dummy), sizeof(int), &error);
-
-    signal(SIGUSR1, CmailSigHandler); /* re-activate handler */
-}
-
-void
-CmailSigHandlerCallBack (InputSourceRef isr, VOIDSTAR closure, char *message, int count, int error)
-{
-    BoardToTop();
-    ReloadCmailMsgEvent(TRUE); /* Reload cmail msg  */
-}
-/**** end signal code ****/
-
-
-#define Abs(n) ((n)<0 ? -(n) : (n))
-
-char *
-InsertPxlSize (char *pattern, int targetPxlSize)
-{
-    char buf[MSG_SIZ];
-    snprintf(buf, MSG_SIZ, pattern, targetPxlSize); // pattern is something like "Sans Bold %d"
-    return strdup(buf);
-}
-
-#ifdef ENABLE_NLS
-#ifdef TODO_GTK
-char *
-InsertPxlSize (char *pattern, int targetPxlSize)
-{
-    char *base_fnt_lst, strInt[12], *p, *q;
-    int alternatives, i, len, strIntLen;
-
-    /*
-     * Replace the "*" (if present) in the pixel-size slot of each
-     * alternative with the targetPxlSize.
-     */
-    p = pattern;
-    alternatives = 1;
-    while ((p = strchr(p, ',')) != NULL) {
-      alternatives++;
-      p++;
-    }
-    snprintf(strInt, sizeof(strInt), "%d", targetPxlSize);
-    strIntLen = strlen(strInt);
-    base_fnt_lst = calloc(1, strlen(pattern) + strIntLen * alternatives + 1);
-
-    p = pattern;
-    q = base_fnt_lst;
-    while (alternatives--) {
-      char *comma = strchr(p, ',');
-      for (i=0; i<14; i++) {
-       char *hyphen = strchr(p, '-');
-       if (!hyphen) break;
-       if (comma && hyphen > comma) break;
-       len = hyphen + 1 - p;
-       if (i == 7 && *p == '*' && len == 2) {
-         p += len;
-         memcpy(q, strInt, strIntLen);
-         q += strIntLen;
-         *q++ = '-';
-       } else {
-         memcpy(q, p, len);
-         p += len;
-         q += len;
-       }
-      }
-      if (!comma) break;
-      len = comma + 1 - p;
-      memcpy(q, p, len);
-      p += len;
-      q += len;
-    }
-    strcpy(q, p);
-
-    return base_fnt_lst;
-}
-#endif
-
-#ifdef TODO_GTK
-XFontSet
-CreateFontSet (char *base_fnt_lst)
-{
-    XFontSet fntSet;
-    char **missing_list;
-    int missing_count;
-    char *def_string;
-
-    fntSet = XCreateFontSet(xDisplay, base_fnt_lst,
-                           &missing_list, &missing_count, &def_string);
-    if (appData.debugMode) {
-      int i, count;
-      XFontStruct **font_struct_list;
-      char **font_name_list;
-      fprintf(debugFP, "Requested font set for list %s\n", base_fnt_lst);
-      if (fntSet) {
-       fprintf(debugFP, " got list %s, locale %s\n",
-               XBaseFontNameListOfFontSet(fntSet),
-               XLocaleOfFontSet(fntSet));
-       count = XFontsOfFontSet(fntSet, &font_struct_list, &font_name_list);
-       for (i = 0; i < count; i++) {
-         fprintf(debugFP, " got charset %s\n", font_name_list[i]);
-       }
-      }
-      for (i = 0; i < missing_count; i++) {
-       fprintf(debugFP, " missing charset %s\n", missing_list[i]);
-      }
-    }
-    if (fntSet == NULL) {
-      fprintf(stderr, _("Unable to create font set for %s.\n"), base_fnt_lst);
-      exit(2);
-    }
-    return fntSet;
-}
-#endif
-#else // not ENABLE_NLS
-/*
- * Find a font that matches "pattern" that is as close as
- * possible to the targetPxlSize.  Prefer fonts that are k
- * pixels smaller to fonts that are k pixels larger.  The
- * pattern must be in the X Consortium standard format,
- * e.g. "-*-helvetica-bold-r-normal--*-*-*-*-*-*-*-*".
- * The return value should be freed with XtFree when no
- * longer needed.
- */
-#ifdef TODO_GTK
-char *
-FindFont (char *pattern, int targetPxlSize)
-{
-    char **fonts, *p, *best, *scalable, *scalableTail;
-    int i, j, nfonts, minerr, err, pxlSize;
-
-    fonts = XListFonts(xDisplay, pattern, 999999, &nfonts);
-    if (nfonts < 1) {
-       fprintf(stderr, _("%s: no fonts match pattern %s\n"),
-               programName, pattern);
-       exit(2);
-    }
-
-    best = fonts[0];
-    scalable = NULL;
-    minerr = 999999;
-    for (i=0; i<nfonts; i++) {
-       j = 0;
-       p = fonts[i];
-       if (*p != '-') continue;
-       while (j < 7) {
-           if (*p == NULLCHAR) break;
-           if (*p++ == '-') j++;
-       }
-       if (j < 7) continue;
-       pxlSize = atoi(p);
-       if (pxlSize == 0) {
-           scalable = fonts[i];
-           scalableTail = p;
-       } else {
-           err = pxlSize - targetPxlSize;
-           if (Abs(err) < Abs(minerr) ||
-               (minerr > 0 && err < 0 && -err == minerr)) {
-               best = fonts[i];
-               minerr = err;
-           }
-       }
-    }
-    if (scalable && Abs(minerr) > appData.fontSizeTolerance) {
-        /* If the error is too big and there is a scalable font,
-          use the scalable font. */
-        int headlen = scalableTail - scalable;
-        p = (char *) XtMalloc(strlen(scalable) + 10);
-       while (isdigit(*scalableTail)) scalableTail++;
-       sprintf(p, "%.*s%d%s", headlen, scalable, targetPxlSize, scalableTail);
-    } else {
-        p = (char *) XtMalloc(strlen(best) + 2);
-        safeStrCpy(p, best, strlen(best)+1 );
-    }
-    if (appData.debugMode) {
-        fprintf(debugFP, "resolved %s at pixel size %d\n  to %s\n",
-               pattern, targetPxlSize, p);
-    }
-    XFreeFontNames(fonts);
-    return p;
-}
-#endif
-#endif
-
-void
-MarkMenuItem (char *menuRef, int state)
-{
-    MenuItem *item = MenuNameToItem(menuRef);
-
-    if(item && item->handle) {
-        ((GtkCheckMenuItem *) (item->handle))->active = state;
-    }
-    SYNC_MENUBAR;
-}
-
-void
-EnableNamedMenuItem (char *menuRef, int state)
-{
-    MenuItem *item = MenuNameToItem(menuRef);
-
-    if(item && item->handle) gtk_widget_set_sensitive(item->handle, state);
-    SYNC_MENUBAR;
-}
-
-void
-EnableButtonBar (int state)
-{
-#ifdef TODO_GTK
-    XtSetSensitive(optList[W_BUTTON].handle, state);
-#endif
-}
-
-
-void
-SetMenuEnables (Enables *enab)
-{
-  while (enab->name != NULL) {
-    EnableNamedMenuItem(enab->name, enab->value);
-    enab++;
-  }
-}
-
-gboolean KeyPressProc(window, eventkey, data)
-     GtkWindow *window;
-     GdkEventKey  *eventkey;
-     gpointer data;
-{
-
-    MoveTypeInProc(eventkey); // pop up for typed in moves
-
-#ifdef TODO_GTK
-    /* check for other key values */
-    switch(eventkey->keyval) {
-        case GDK_question:
-         AboutGameEvent();
-         break;
-        default:
-         break;
-    }
-#endif
-    return False;
-}
-#ifdef TODO_GTK
-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
-    MenuItem *item;
-    if(*nprms == 0) return;
-    item = MenuNameToItem(prms[0]);
-    if(item) ((MenuProc *) item->proc) ();
-}
-#endif
-
-void
-SetupDropMenu ()
-{
-#ifdef TODO_GTK
-    int i, j, count;
-    char label[32];
-    Arg args[16];
-    Widget entry;
-    char* p;
-
-    for (i=0; i<sizeof(dmEnables)/sizeof(DropMenuEnables); i++) {
-       entry = XtNameToWidget(dropMenu, dmEnables[i].widget);
-       p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,
-                  dmEnables[i].piece);
-       XtSetSensitive(entry, p != NULL || !appData.testLegality
-                      /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse
-                                      && !appData.icsActive));
-       count = 0;
-       while (p && *p++ == dmEnables[i].piece) count++;
-       snprintf(label, sizeof(label), "%s  %d", dmEnables[i].widget, count);
-       j = 0;
-       XtSetArg(args[j], XtNlabel, label); j++;
-       XtSetValues(entry, args, j);
-    }
-#endif
-}
-
-static void
-do_flash_delay (unsigned long msec)
-{
-    TimeDelay(msec);
-}
-
-void
-FlashDelay (int flash_delay)
-{
-       if(flash_delay) do_flash_delay(flash_delay);
-}
-
-double
-Fraction (int x, int start, int stop)
-{
-   double f = ((double) x - start)/(stop - start);
-   if(f > 1.) f = 1.; else if(f < 0.) f = 0.;
-   return f;
-}
-
-static WindowPlacement wpNew;
-
-void
-CoDrag (GtkWidget *sh, WindowPlacement *wp)
-{
-    int touch=0, fudge = 4, f = 3;
-    GetActualPlacement(sh, wp);
-    if(abs(wpMain.x + wpMain.width + 2*frameX - f - wp->x)         < fudge) touch = 1; else // right touch
-    if(abs(wp->x + wp->width + 2*frameX - f - wpMain.x)            < fudge) touch = 2; else // left touch
-    if(abs(wpMain.y + wpMain.height + frameX - f + frameY - wp->y) < fudge) touch = 3; else // bottom touch
-    if(abs(wp->y + wp->height + frameX + frameY - f - wpMain.y)    < fudge) touch = 4;      // top touch
-//printf("CoDrag: touch = %d x=%d w=%d x2=%d w2=%d fx=%d\n", touch, wpMain.x, wpMain.width, wp->x, wp->width, frameX);
-    if(!touch ) return; // only windows that touch co-move
-    if(touch < 3 && wpNew.height != wpMain.height) { // left or right and height changed
-       int heightInc = wpNew.height - wpMain.height;
-       double fracTop = Fraction(wp->y, wpMain.y, wpMain.y + wpMain.height + frameX + frameY);
-       double fracBot = Fraction(wp->y + wp->height + frameX + frameY + 1, wpMain.y, wpMain.y + wpMain.height + frameX + frameY);
-       wp->y += fracTop * heightInc;
-       heightInc = (int) (fracBot * heightInc) - (int) (fracTop * heightInc);
-#ifdef TODO_GTK
-       if(heightInc) XtSetArg(args[j], XtNheight, wp->height + heightInc), j++;
-#endif
-       wp->height += heightInc;
-    } else if(touch > 2 && wpNew.width != wpMain.width) { // top or bottom and width changed
-       int widthInc = wpNew.width - wpMain.width;
-       double fracLeft = Fraction(wp->x, wpMain.x, wpMain.x + wpMain.width + 2*frameX);
-       double fracRght = Fraction(wp->x + wp->width + 2*frameX + 1, wpMain.x, wpMain.x + wpMain.width + 2*frameX);
-       wp->y += fracLeft * widthInc;
-       widthInc = (int) (fracRght * widthInc) - (int) (fracLeft * widthInc);
-#ifdef TODO_GTK
-       if(widthInc) XtSetArg(args[j], XtNwidth, wp->width + widthInc), j++;
-#endif
-       wp->width += widthInc;
-    }
-    wp->x += wpNew.x - wpMain.x;
-    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
-       gtk_window_move(GTK_WINDOW(sh), wp->x, wp->y);
-//printf("moved to (%d,%d)\n", wp->x, wp->y);
-       gtk_window_resize(GTK_WINDOW(sh), wp->width, wp->height);
-}
-
-void
-ReSize (WindowPlacement *wp)
-{
-       GtkAllocation a;
-       int sqx, sqy, i, w, h, lg = lineGap;
-       static int first = 1;
-//     DisplayBothClocks();
-       if(wp->width == wpMain.width && wp->height == wpMain.height && !first) return; // not sized
-       gtk_widget_get_allocation(optList[W_DROP+1].handle, &a); // table that should contain everything
-       w = a.width; h = a.height;
-       gtk_widget_get_allocation(shellWidget, &a);
-       if(a.width < w || a.height < h) { // outer window smaller than dialog content?
-           w = a.width - w; h = a.height - h; // subtract matrgins, measured as table minus board dimensions
-           gtk_widget_get_allocation(optList[W_BOARD].handle, &a);
-           w += a.width; h += a.height;
-       } else {
-           gtk_widget_get_allocation(optList[W_BOARD].handle, &a);
-           w = a.width; h = a.height;
-       }
-       sqx = (w - lg) / BOARD_WIDTH - lg;
-       sqy = (h - lg) / BOARD_HEIGHT - lg;
-       if(sqy < sqx) sqx = sqy;
-        if(sqx < 20) return;
-       if(appData.overrideLineGap < 0) { // do second iteration with adjusted lineGap
-           int oldSqx = sqx;
-           lg = lineGap = sqx < 37 ? 1 : sqx < 59 ? 2 : sqx < 116 ? 3 : 4;
-           sqx = (w  - lg) / BOARD_WIDTH - lg;
-           sqy = (h - lg) / BOARD_HEIGHT - lg;
-           if(sqy < sqx) sqx = sqy;
-           lg = sqx < 37 ? 1 : sqx < 59 ? 2 : sqx < 116 ? 3 : 4;
-           if(sqx == oldSqx + 1 && lg == lineGap + 1) sqx = oldSqx, squareSize = 0; // prevent oscillations, force resize by kludge
-       }
-       for(h=0; sizeDefaults[h+1].name && sizeDefaults[h].squareSize*8 > sqx*BOARD_WIDTH; h++) {}
-       if(initialSquareSize != sizeDefaults[h].squareSize) { // boardSize changed
-           initialSquareSize = sizeDefaults[h].squareSize; // used for saving font
-           ChangeFont(1, &appData.clockFont, CLOCK_FONT, initialSquareSize, CLOCK_FONT_NAME, 2*(sizeDefaults[h].clockFontPxlSize+1)/3);
-           ChangeFont(1, &appData.font, MESSAGE_FONT, initialSquareSize, DEFAULT_FONT_NAME, sizeDefaults[h].coordFontPxlSize);
-           ChangeFont(0, &appData.icsFont, CONSOLE_FONT, initialSquareSize, CONSOLE_FONT_NAME, sizeDefaults[h].coordFontPxlSize);
-           ChangeFont(0, &appData.tagsFont, EDITTAGS_FONT, initialSquareSize, TAGS_FONT_NAME, sizeDefaults[h].coordFontPxlSize);
-           ChangeFont(0, &appData.commentFont, COMMENT_FONT, initialSquareSize, COMMENT_FONT_NAME, sizeDefaults[h].coordFontPxlSize);
-           ChangeFont(0, &appData.gameListFont, GAMELIST_FONT, initialSquareSize, GAMELIST_FONT_NAME, sizeDefaults[h].coordFontPxlSize);
-           ChangeFont(0, &appData.historyFont, MOVEHISTORY_FONT, initialSquareSize, HISTORY_FONT_NAME, sizeDefaults[h].coordFontPxlSize);
-           DisplayBothClocks();
-           ApplyFont(&mainOptions[W_MESSG], NULL);
-           for(i=1; i<6; i++) ApplyFont(&mainOptions[W_BUTTON+i], NULL);
-           ApplyFont(&tagsOptions[1], NULL);
-           ApplyFont(&commentOptions[0], NULL);
-           ApplyFont(&historyOptions[0], NULL);
-           ApplyFont(&engoutOptions[5], NULL);
-           ApplyFont(&engoutOptions[12], NULL);
-           ApplyFont(&chatOptions[11], appData.icsFont);
-           AppendColorized(&chatOptions[6], NULL, 0); // kludge to replace font tag
-       }
-       if(!strchr(appData.boardSize, ',')) {
-           ASSIGN(appData.boardSize, sizeDefaults[h].name);
-       }
-#ifndef OSXAPP
-       if(sizeDefaults[h].tinyLayout != tinyLayout) { // alter clipping of menu names to conform to board width
-           int clip = (tinyLayout = sizeDefaults[h].tinyLayout) + 1;
-           char text[MSG_SIZ];
-           for(h=1; mainOptions[h].type == DropDown; h++) {
-               strncpy(text, _(mainOptions[h].name), MSG_SIZ);
-               if(clip != 1) text[clip + (text[clip-1] == '_')] = NULLCHAR;
-               gtk_menu_item_set_label((GtkMenuItem *) mainOptions[h].handle, text);
-           }
-       }
-#endif
-       if(sqx != squareSize && !first) {
-           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;
-       first = appData.fixedSize;
-       if(twoBoards && shellUp[DummyDlg]) {
-           SlavePopUp(); dualOptions[3].max = 0; DoEvents(); // calls SlaveResize, kludge to force assigning new canvas
-           partnerUp = !partnerUp; flipView = !flipView;
-           DrawPosition(True, NULL);
-           partnerUp = !partnerUp; flipView = !flipView;
-       }
-}
-
-static guint delayedDragTag = 0;
-
-void
-DragProc ()
-{
-    static int busy;
-    if(busy++) return; // prevent recursive calling, but remember we missed an event in 'busy'
-
-    if(delayedDragTag) g_source_remove(delayedDragTag); // no more timer interrupts from same event!
-    delayedDragTag = 0;
-
-    do {
-       GetActualPlacement(shellWidget, &wpNew);
-       if(wpNew.x == wpMain.x && wpNew.y == wpMain.y && // not moved
-          wpNew.width == wpMain.width && wpNew.height == wpMain.height) { // not sized
-           busy = 0; break; // false alarm
-       }
-       ReSize(&wpNew); // this can be interrupted by other events
-       if(appData.useStickyWindows) {
-           if(shellUp[EngOutDlg]) CoDrag(shells[EngOutDlg], &wpEngineOutput);
-           if(shellUp[HistoryDlg]) CoDrag(shells[HistoryDlg], &wpMoveHistory);
-           if(shellUp[EvalGraphDlg]) CoDrag(shells[EvalGraphDlg], &wpEvalGraph);
-           if(shellUp[GameListDlg]) CoDrag(shells[GameListDlg], &wpGameList);
-           if(shellUp[ChatDlg]) CoDrag(shells[ChatDlg], &wpConsole);
-        }
-       wpMain = wpNew;
-       DrawPosition(True, NULL);
-       if(busy > 2) busy = 2; // if multiple events were backlogged, only do one more
-    } while(--busy);
-}
-
-void
-DelayedDrag ()
-{
-//printf("old timr = %d\n", delayedDragTag);
-    if(delayedDragTag) g_source_remove(delayedDragTag);
-    delayedDragTag = g_timeout_add( 200, (GSourceFunc) DragProc, NULL);
-//printf("new timr = %d\n", delayedDragTag);
-}
-
-static gboolean
-EventProc (GtkWidget *widget, GdkEvent *event, gpointer g)
-{
-//printf("event proc (%d,%d) %dx%d\n", event->configure.x, event->configure.y, event->configure.width, event->configure.height);
-    // immediately
-    wpNew.x = event->configure.x;
-    wpNew.y = event->configure.y;
-    wpNew.width  = event->configure.width;
-    wpNew.height = event->configure.height;
-//    SetWidgetLabel(&mainOptions[W_WHITE], ""); SetWidgetLabel(&mainOptions[W_BLACK], "");
-    DelayedDrag(); // as long as events keep coming in faster than 50 msec, they destroy each other
-    return FALSE;
-}
-
-
-
-/* Disable all user input other than deleting the window */
-static int frozen = 0;
-
-void
-FreezeUI ()
-{
-  if (frozen) return;
-  /* Grab by a widget that doesn't accept input */
-  gtk_grab_add(optList[W_MESSG].handle);
-  frozen = 1;
-}
-
-/* Undo a FreezeUI */
-void
-ThawUI ()
-{
-  if (!frozen) return;
-  gtk_grab_remove(optList[W_MESSG].handle);
-  frozen = 0;
-}
-
-void
-ModeHighlight ()
-{
-    static int oldPausing = FALSE;
-    static GameMode oldMode = (GameMode) -1;
-    char *wname;
-    if (!boardWidget) return;
-
-    if (pausing != oldPausing) {
-       oldPausing = pausing;
-       MarkMenuItem("Mode.Pause", pausing);
-
-       if (appData.showButtonBar) {
-         /* Always toggle, don't set.  Previous code messes up when
-            invoked while the button is pressed, as releasing it
-            toggles the state again. */
-           GdkColor color;
-            gdk_color_parse( pausing ? "#808080" : "#F0F0F0", &color );
-            gtk_widget_modify_bg ( GTK_WIDGET(optList[W_PAUSE].handle), GTK_STATE_NORMAL, &color );
-       }
-    }
-
-    wname = ModeToWidgetName(oldMode);
-    if (wname != NULL) {
-       MarkMenuItem(wname, False);
-    }
-    wname = ModeToWidgetName(gameMode);
-    if (wname != NULL) {
-       MarkMenuItem(wname, True);
-    }
-    if(oldMode == TwoMachinesPlay) EnableNamedMenuItem("Mode.MachineMatch", True);
-    MarkMenuItem("Mode.MachineMatch", matchMode && matchGame < appData.matchGames);
-    oldMode = gameMode;
-
-    /* Maybe all the enables should be handled here, not just this one */
-    EnableNamedMenuItem("Mode.Training", gameMode == Training || gameMode == PlayFromGameFile);
-
-    DisplayLogos(&optList[W_WHITE-1], &optList[W_BLACK+1]);
-}
-
-
-/*
- * Button/menu procedures
- */
-
-void CopyFileToClipboard(gchar *filename)
-{
-    gchar *selection_tmp;
-    GtkClipboard *cb;
-
-    // read the file
-    FILE* f = fopen(filename, "r");
-    long len;
-    size_t count;
-    if (f == NULL) return;
-    fseek(f, 0, 2);
-    len = ftell(f);
-    rewind(f);
-    selection_tmp = g_try_malloc(len + 1);
-    if (selection_tmp == NULL) {
-        printf("Malloc failed in CopyFileToClipboard\n");
-        return;
-    }
-    count = fread(selection_tmp, 1, len, f);
-    fclose(f);
-    if (len != count) {
-      g_free(selection_tmp);
-      return;
-    }
-    selection_tmp[len] = NULLCHAR; // file is now in selection_tmp
-
-    // copy selection_tmp to clipboard
-    GdkDisplay *gdisp = gdk_display_get_default();
-    if (!gdisp) {
-        g_free(selection_tmp);
-        return;
-    }
-    cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD);
-    gtk_clipboard_set_text(cb, selection_tmp, -1);
-    g_free(selection_tmp);
-}
-
-void
-CopySomething (char *src)
-{
-    GdkDisplay *gdisp = gdk_display_get_default();
-    GtkClipboard *cb;
-    if(!src) { CopyFileToClipboard(gameCopyFilename); return; }
-    if (gdisp == NULL) return;
-    cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD);
-    gtk_clipboard_set_text(cb, src, -1);
-}
-
-void
-PastePositionProc ()
-{
-    GdkDisplay *gdisp = gdk_display_get_default();
-    GtkClipboard *cb;
-    gchar *fenstr;
-
-    if (gdisp == NULL) return;
-    cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD);
-    fenstr = gtk_clipboard_wait_for_text(cb);
-    if (fenstr==NULL) return; // nothing had been selected to copy
-    EditPositionPasteFEN(fenstr);
-    return;
-}
-
-void
-PasteGameProc ()
-{
-    gchar *text=NULL;
-    GtkClipboard *cb;
-    guint len=0; int flip = appData.flipView;
-    FILE* f;
-
-    // get game from clipboard
-    GdkDisplay *gdisp = gdk_display_get_default();
-    if (gdisp == NULL) return;
-    cb = gtk_clipboard_get_for_display(gdisp, GDK_SELECTION_CLIPBOARD);
-    text = gtk_clipboard_wait_for_text(cb);
-    if (text == NULL) return; // nothing to paste
-    len = strlen(text);
-
-    // write to temp file
-    if (text == NULL || len == 0) {
-      return; //nothing to paste
-    }
-    f = fopen(gamePasteFilename, "w");
-    if (f == NULL) {
-      DisplayError(_("Can't open temp file"), errno);
-      return;
-    }
-    fwrite(text, 1, len, f);
-    fclose(f);
-
-    // load from file
-    if(!appData.autoFlipView) appData.flipView = flipView;
-    LoadGameFromFile(gamePasteFilename, 0, gamePasteFilename, TRUE);
-    appData.flipView = flip;
-    return;
-}
-
-
-#ifdef TODO_GTK
-void
-QuitWrapper (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{
-    QuitProc();
-}
-#endif
-
-void MoveTypeInProc(eventkey)
-    GdkEventKey  *eventkey;
-{
-    char buf[10];
-
-    // ingnore if ctrl, alt, or meta is pressed
-    if (eventkey->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_META_MASK)) {
-        return;
-    }
-
-    buf[0]=eventkey->keyval;
-    buf[1]='\0';
-    if (eventkey->keyval > 32 && eventkey->keyval < 256 || *buf == 27)
-       ConsoleAutoPopUp (buf);
-}
-
-#ifdef TODO_GTK
-void
-TempBackwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{
-       if (!TempBackwardActive) {
-               TempBackwardActive = True;
-               BackwardEvent();
-       }
-}
-
-void
-TempForwardProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
-{
-       /* Check to see if triggered by a key release event for a repeating key.
-        * If so the next queued event will be a key press of the same key at the same time */
-       if (XEventsQueued(xDisplay, QueuedAfterReading)) {
-               XEvent next;
-               XPeekEvent(xDisplay, &next);
-               if (next.type == KeyPress && next.xkey.time == event->xkey.time &&
-                       next.xkey.keycode == event->xkey.keycode)
-                               return;
-       }
-    ForwardEvent();
-       TempBackwardActive = False;
-}
-#endif
-
-void
-ManProc ()
-{   // called from menu
-#ifdef OSXAPP
-    char buf[MSG_SIZ];
-    snprintf(buf, MSG_SIZ, "osascript -e 'tell application \"Terminal\"' -e 'activate' -e 'do script \"man %s/../man/man6/xboard.6\"' -e 'end tell'", dataDir);
-    system(buf);
-#else
-    system("xterm -e man xboard &");
-#endif
-}
-
-void
-InfoProc ()
-{
-    char buf[MSG_SIZ];
-#ifdef OSXAPP
-    snprintf(buf, MSG_SIZ, "osascript -e 'tell application \"Terminal\"' -e 'activate' -e 'do script \"info -d %s/../info -f xboard.info\"' -e 'end tell'", dataDir);
-#else
-        snprintf(buf, sizeof(buf), "xterm -e info --directory %s --directory . -f %s &",
-                 INFODIR, INFOFILE);
-#endif
-    system(buf);
-}
-
-
-void
-SetWindowTitle (char *text, char *title, char *icon)
-{
-#ifdef TODO_GTK
-    Arg args[16];
-    int i;
-    if (appData.titleInWindow) {
-       i = 0;
-       XtSetArg(args[i], XtNlabel, text);   i++;
-       XtSetValues(titleWidget, args, i);
-    }
-    i = 0;
-    XtSetArg(args[i], XtNiconName, (XtArgVal) icon);    i++;
-    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);
-}
-
-
-void
-DisplayIcsInteractionTitle (String message)
-{
-#ifdef TODO_GTK
-  if (oldICSInteractionTitle == NULL) {
-    /* Magic to find the old window title, adapted from vim */
-    char *wina = getenv("WINDOWID");
-    if (wina != NULL) {
-      Window win = (Window) atoi(wina);
-      Window root, parent, *children;
-      unsigned int nchildren;
-      int (*oldHandler)() = XSetErrorHandler(NullXErrorCheck);
-      for (;;) {
-       if (XFetchName(xDisplay, win, &oldICSInteractionTitle)) break;
-       if (!XQueryTree(xDisplay, win, &root, &parent,
-                       &children, &nchildren)) break;
-       if (children) XFree((void *)children);
-       if (parent == root || parent == 0) break;
-       win = parent;
-      }
-      XSetErrorHandler(oldHandler);
-    }
-    if (oldICSInteractionTitle == NULL) {
-      oldICSInteractionTitle = "xterm";
-    }
-  }
-  printf("\033]0;%s\007", message);
-  fflush(stdout);
-#endif
-}
-
-void
-LockBoardSize (int after)
-{
-    static char *oldClockFont, *oldMessgFont;
-    int w, h;
-    if(oldMessgFont && !strcmp(oldMessgFont, appData.font) &&
-       oldClockFont && !strcmp(oldClockFont, appData.clockFont) && after < 2) return; // only do something when font changed
-    w = BOARD_WIDTH*(squareSize + lineGap) + lineGap;
-    h = BOARD_HEIGHT*(squareSize + lineGap) + lineGap;
-    if(after & 1) {
-       ASSIGN(oldClockFont, appData.clockFont);
-       ASSIGN(oldMessgFont, appData.font);
-       gtk_window_resize(GTK_WINDOW(shellWidget), w, h);
-       DoEvents();
-       gtk_widget_set_size_request(optList[W_BOARD].handle, -1, -1); // liberate board
-    } else { // before
-       gtk_widget_set_size_request(optList[W_BOARD].handle, w, h);   // protect board widget
-    }
-}
-
-void
-DisplayTimerLabel (Option *opt, char *color, long timer, int highlight)
-{
-    static int twoLines = -1;
-    GtkWidget *w = (GtkWidget *) opt->handle;
-    GdkColor col;
-    char *markup, two = (appData.logoSize != 0);
-    char bgcolor[10];
-    char fgcolor[10];
-
-    if (highlight) {
-       strcpy(bgcolor, "black");
-        strcpy(fgcolor, "white");
-    } else {
-        strcpy(bgcolor, "white");
-        strcpy(fgcolor, "black");
-    }
-    if (timer > 0 &&
-        appData.lowTimeWarning &&
-        (timer / 1000) < appData.icsAlarmTime) {
-        strcpy(fgcolor, appData.lowTimeWarningColor);
-    }
-
-    if(! partnerUp && two != twoLines) LockBoardSize(2); // lock board size if clock height changes
-
-    gdk_color_parse( bgcolor, &col );
-    gtk_widget_modify_bg(gtk_widget_get_parent(opt->handle), GTK_STATE_NORMAL, &col);
-
-    if (appData.clockMode) {
-        markup = g_markup_printf_escaped("<span font=\"%s\" background=\"%s\" foreground=\"%s\">%s:%s%s</span>", appData.clockFont,
-                                        bgcolor, fgcolor, color, two ? "\n" : " ", TimeString(timer));
-//        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 {
-        markup = g_markup_printf_escaped("<span font=\"%s\" background=\"%s\" foreground=\"%s\">%s  </span>", appData.clockFont,
-                                        bgcolor, fgcolor, color);
-//        markup = g_markup_printf_escaped("<span size=\"xx-large\" weight=\"heavy\" background=\"%s\" foreground=\"%s\">%s  </span>",
-//                                      bgcolor, fgcolor, color);
-    }
-    gtk_label_set_markup(GTK_LABEL(w), markup);
-    g_free(markup);
-
-    if(!partnerUp && two != twoLines) LockBoardSize(3), twoLines = two;
-}
-
-static GdkPixbuf **clockIcons[] = { &WhiteIcon, &BlackIcon };
-
-void
-SetClockIcon (int color)
-{
-    GdkPixbuf *pm = *clockIcons[color];
-    if (mainwindowIcon != pm) {
-        mainwindowIcon = pm;
-#ifdef OSXAPP
-        gtkosx_application_set_dock_icon_pixbuf(theApp, mainwindowIcon);
-#else
-        gtk_window_set_icon(GTK_WINDOW(shellWidget), mainwindowIcon);
-#endif
-    }
-}
-
-#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) {
-           if(count == 0 && is->kind == CPReal && shells[ChatDlg]) { // [HGM] absence of terminal is no error if ICS Console present
-               RemoveInputSource(is); // cease reading stdin
-               stdoutClosed = TRUE;   // suppress future output
-               return True;
-           } 
-           (is->func)(is, is->closure, is->buf, count, count ? errno : 0);
-           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;
-           q++;
-           (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;
-       else
-         error = 0;
-       (is->func)(is, is->closure, is->buf, count, error);
-    }
-    return True; // Must return true or the watch will be removed
-}
-
-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));
-    is->lineByLine = lineByLine;
-    is->func = func;
-    if (pr == NoProc) {
-       is->kind = CPReal;
-       is->fd = fileno(stdin);
-    } else {
-       is->kind = cp->kind;
-       is->fd = cp->fdFrom;
-    }
-    if (lineByLine)
-      is->unused = is->buf;
-    else
-      is->unused = NULL;
-
-   /* GTK-TODO: will this work on windows?*/
-
-    channel = g_io_channel_unix_new(is->fd);
-    g_io_channel_set_close_on_unref (channel, TRUE);
-    is->sid = g_io_add_watch(channel, G_IO_IN,(GIOFunc) DoInputCallback, is);
-
-    is->closure = closure;
-    return (InputSourceRef) is;
-}
-
-
-void
-RemoveInputSource(isr)
-     InputSourceRef isr;
-{
-    InputSource *is = (InputSource *) isr;
-
-    if (is->sid == 0) return;
-    g_source_remove(is->sid);
-    is->sid = 0;
-    return;
-}
-
-#ifndef HAVE_USLEEP
-
-static Boolean frameWaiting;
-
-static RETSIGTYPE
-FrameAlarm (int sig)
-{
-  frameWaiting = False;
-  /* In case System-V style signals.  Needed?? */
-  signal(SIGALRM, FrameAlarm);
-}
-
-void
-FrameDelay (int time)
-{
-  struct itimerval delay;
-
-  if (time > 0) {
-    frameWaiting = True;
-    signal(SIGALRM, FrameAlarm);
-    delay.it_interval.tv_sec =
-      delay.it_value.tv_sec = time / 1000;
-    delay.it_interval.tv_usec =
-      delay.it_value.tv_usec = (time % 1000) * 1000;
-    setitimer(ITIMER_REAL, &delay, NULL);
-    while (frameWaiting) pause();
-    delay.it_interval.tv_sec = delay.it_value.tv_sec = 0;
-    delay.it_interval.tv_usec = delay.it_value.tv_usec = 0;
-    setitimer(ITIMER_REAL, &delay, NULL);
-  }
-}
-
-#else
-
-void
-FrameDelay (int time)
-{
-#ifdef TODO_GTK
-  XSync(xDisplay, False);
-#endif
-//  gtk_main_iteration_do(False);
-
-  if (time > 0)
-    usleep(time * 1000);
-}
-
-#endif
-
-static int
-FindLogo (char *place, char *name, char *buf)
-{   // check if file exists in given place
-    FILE *f;
-    if(!place) return 0;
-    snprintf(buf, MSG_SIZ, "%s/%s.png", place, name);
-    if(*place && strcmp(place, ".") && (f = fopen(buf, "r")) ) {
-       fclose(f);
-       return 1;
-    }
-    return 0;
-}
-
-static void
-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 { // engine; cascade
-           if(!FindLogo(appData.logoDir, cps->tidy, buf) &&   // first try user log folder
-              !FindLogo(appData.directory[n], "logo", buf) && // then engine directory
-              !FindLogo("/usr/local/share/games/plugins/logos", cps->tidy, buf) ) // then system folders
-               FindLogo("/usr/share/games/plugins/logos", cps->tidy, buf);
-       }
-    }
-    if(logoName[0])
-       { ASSIGN(cps->programLogo, logoName); }
-}
-
-void
-UpdateLogos (int displ)
-{
-    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;
-}
-
-void FileNamePopUpWrapper(
-     char *label,
-     char *def,
-     char *filter,
-     FileProc proc,
-     Boolean pathFlag,
-     char *openMode,
-     char **name,
-     FILE **fp)
-{
-  GtkWidget     *dialog;
-  GtkFileFilter *gtkfilter;
-  GtkFileFilter *gtkfilter_all;
-  char space[]     = " ";
-  char fileext[10] = "";
-  char *result     = NULL;
-  char *cp;
-  char curDir[MSG_SIZ];
-
-  StartDir(filter, NULL); // change to start directory for this file type
-
-  if(def && *def && def[strlen(def)-1] == '/') {
-    getcwd(curDir, MSG_SIZ);
-    chdir(def);
-  }
-
-
-  /* make a copy of the filter string, so that strtok can work with it*/
-  cp = strdup(filter);
-
-  /* add filters for file extensions */
-  gtkfilter     = gtk_file_filter_new();
-  gtkfilter_all = gtk_file_filter_new();
-
-  /* one filter to show everything */
-  gtk_file_filter_add_pattern(gtkfilter_all, "*.*");
-  gtk_file_filter_set_name   (gtkfilter_all, "All Files");
-
-  /* add filter if present */
-  result = strtok(cp, space);
-  while( result != NULL  ) {
-    snprintf(fileext,10,"*%s",result);
-    result = strtok( NULL, space );
-    gtk_file_filter_add_pattern(gtkfilter, fileext);
-  };
-
-  /* second filter to only show what's useful */
-  gtk_file_filter_set_name (gtkfilter,filter);
-
-  if (openMode[0] == 'r')
-    {
-      dialog = gtk_file_chooser_dialog_new (label,
-                                           NULL,
-                                           GTK_FILE_CHOOSER_ACTION_OPEN,
-                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                           GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
-                                           NULL);
-    }
-  else
-    {
-      dialog = gtk_file_chooser_dialog_new (label,
-                                           NULL,
-                                           GTK_FILE_CHOOSER_ACTION_SAVE,
-                                           GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                           GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT,
-                                           NULL);
-      /* add filename suggestions */
-      if (strlen(def) > 0 )
-       gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(dialog), def);
-
-      //gtk_file_chooser_set_create_folders(GTK_FILE_CHOOSER (dialog),TRUE);
-    }
-
-  /* add filters */
-  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter_all);
-  gtk_file_chooser_add_filter (GTK_FILE_CHOOSER(dialog),gtkfilter);
-  /* activate filter */
-  gtk_file_chooser_set_filter (GTK_FILE_CHOOSER(dialog),gtkfilter);
-
-  if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
-    {
-      char *filename;
-      FILE *f;
-
-      filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
-
-      //see loadgamepopup
-      f = fopen(filename, openMode);
-      if (f == NULL)
-        {
-          DisplayError(_("Failed to open file"), errno);
-        }
-      else
-        {
-          /* TODO add indec */
-           *fp = f;
-           ASSIGN(*name, filename);
-           ScheduleDelayedEvent(DelayedLoad, 50);
-        }
-      StartDir(filter, filename);
-      g_free (filename);
-    }
-  else StartDir(filter, "");
-
-  gtk_widget_destroy (dialog);
-  ModeHighlight();
-
-  if(def && *def && def[strlen(def)-1] == '/') chdir(curDir);
-
-  free(cp);
-  return;
-
-}