Add mode to draw PNG piece images through cairo
[xboard.git] / xboard.c
index 4c96479..4bc8d38 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -61,6 +61,8 @@
 #include <sys/stat.h>
 #include <pwd.h>
 #include <math.h>
+#include <cairo/cairo.h>
+#include <cairo/cairo-xlib.h>
 
 #if !OMIT_SOCKETS
 # if HAVE_SYS_SOCKET_H
@@ -202,6 +204,7 @@ extern char *getenv();
 #include "childio.h"
 #include "xgamelist.h"
 #include "xhistory.h"
+#include "xevalgraph.h"
 #include "xedittags.h"
 #include "menus.h"
 #include "board.h"
@@ -234,6 +237,7 @@ static void CreateGCs P((int redo));
 static void CreateAnyPieces P((void));
 void CreateXIMPieces P((void));
 void CreateXPMPieces P((void));
+void CreatePNGPieces P((void));
 void CreateXPMBoard P((char *s, int n));
 void CreatePieces P((void));
 Widget CreateMenuBar P((Menu *mb, int boardWidth));
@@ -256,8 +260,6 @@ void DrawPositionProc P((Widget w, XEvent *event,
 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));
@@ -272,9 +274,7 @@ 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));
 
 /*
 * XBoard depends on Xt R4 or higher
@@ -293,7 +293,6 @@ GC lightSquareGC, darkSquareGC, lineGC, wdPieceGC, wlPieceGC,
 Pixmap iconPixmap, wIconPixmap, bIconPixmap, xMarkPixmap;
 Widget shellWidget, formWidget, boardWidget, titleWidget, dropMenu, menuBarWidget;
 Option *optList; // contains all widgets of main window
-XSegment secondSegments[BOARD_RANKS + BOARD_FILES + 2];
 XSegment gridSegments[BOARD_RANKS + BOARD_FILES + 2];
 #if ENABLE_NLS
 XFontSet fontSet, clockFontSet;
@@ -306,8 +305,6 @@ XFontStruct *coordFontStruct, *countFontStruct;
 XtAppContext appContext;
 char *layoutName;
 
-FileProc fileProc;
-char *fileOpenMode;
 char installDir[] = "."; // [HGM] UCI: needed for UCI; probably needs run-time initializtion
 
 Position commentX = -1, commentY = -1;
@@ -343,6 +340,8 @@ WindowPlacement wpTags;
 
 #define SOLID 0
 #define OUTLINE 1
+cairo_surface_t *pngPieceBitmaps[2][(int)BlackPawn];    // scaled pieces as used
+cairo_surface_t *pngPieceBitmaps2[2][(int)BlackPawn+4]; // scaled pieces in store
 Pixmap pieceBitmap[2][(int)BlackPawn];
 Pixmap pieceBitmap2[2][(int)BlackPawn+4];       /* [HGM] pieces */
 Pixmap xpmPieceBitmap[4][(int)BlackPawn];      /* LL, LD, DL, DD actually used*/
@@ -840,23 +839,20 @@ int frameX, frameY;
 void
 GetActualPlacement (Widget wg, WindowPlacement *wp)
 {
-  Arg args[16];
-  Dimension w, h;
-  Position x, y;
   XWindowAttributes winAt;
   Window win, dummy;
-  int i, rx, ry;
+  int rx, ry;
 
   if(!wg) return;
 
-    win = XtWindow(wg);
-    XGetWindowAttributes(xDisplay, win, &winAt); // this works, where XtGetValues on XtNx, XtNy does not!
-    XTranslateCoordinates (xDisplay, win, winAt.root, -winAt.border_width, -winAt.border_width, &rx, &ry, &dummy);
-    wp->x = rx - winAt.x;
-    wp->y = ry - winAt.y;
-    wp->height = winAt.height;
-    wp->width = winAt.width;
-    frameX = winAt.x; frameY = winAt.y; // remember to decide if windows touch
+  win = XtWindow(wg);
+  XGetWindowAttributes(xDisplay, win, &winAt); // this works, where XtGetValues on XtNx, XtNy does not!
+  XTranslateCoordinates (xDisplay, win, winAt.root, -winAt.border_width, -winAt.border_width, &rx, &ry, &dummy);
+  wp->x = rx - winAt.x;
+  wp->y = ry - winAt.y;
+  wp->height = winAt.height;
+  wp->width = winAt.width;
+  frameX = winAt.x; frameY = winAt.y; // remember to decide if windows touch
 }
 
 void
@@ -890,6 +886,17 @@ MainWindowUp ()
 }
 
 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;
+}
+
+void
 PopUpStartupDialog ()
 {  // start menu not implemented in XBoard
 }
@@ -921,35 +928,30 @@ ConvertToLine (int argc, char **argv)
 void
 InitDrawingSizes (BoardSize boardSize, int flags)
 {   // [HGM] resize is functional now, but for board format changes only (nr of ranks, files)
-    Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
-    Arg args[16];
-    XtGeometryResult gres;
+    Dimension boardWidth, boardHeight, w, h;
     int i;
     static Dimension oldWidth, oldHeight;
     static VariantClass oldVariant;
-    static int oldDual = -1, oldMono = -1;
+    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 || oldDual != twoBoards) { // do resizing stuff only if size actually changed
+  if(boardWidth != oldWidth || boardHeight != oldHeight) { // do resizing stuff only if size actually changed
 
-    oldWidth = boardWidth; oldHeight = boardHeight; oldDual = twoBoards;
+    oldWidth = boardWidth; oldHeight = boardHeight;
     CreateGrid();
-    hOffset = boardWidth + 10;
-    for(i=0; i<BOARD_WIDTH+BOARD_HEIGHT+2; i++) { // [HGM] dual: grid for second board
-       secondSegments[i] = gridSegments[i];
-       secondSegments[i].x1 += hOffset;
-       secondSegments[i].x2 += hOffset;
-    }
 
     /*
      * Inhibit shell resizing.
      */
-    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW + twoBoards*hOffset; // [HGM] dual
+    shellArgs[0].value = w = (XtArgVal) boardWidth + marginW ;
     shellArgs[1].value = h = (XtArgVal) boardHeight + marginH;
     shellArgs[4].value = shellArgs[2].value = w;
     shellArgs[5].value = shellArgs[3].value = h;
@@ -1030,6 +1032,12 @@ InitDrawingSizes (BoardSize boardSize, int flags)
        }
       }
     }
+    for(i=0; i<2; i++) {
+       int p;
+printf("Copy pieces\n");
+       for(p=0; p<=(int)WhiteKing; p++)
+          pngPieceBitmaps[i][p] = pngPieceBitmaps2[i][p]; // defaults
+    }
     oldMono = -10; // kludge to force recreation of animation masks
     oldVariant = gameInfo.variant;
   }
@@ -1069,6 +1077,8 @@ MakeColors ()
     forceMono |= MakeOneColor(appData.blackPieceColor, &blackPieceColor);
     forceMono |= MakeOneColor(appData.highlightSquareColor, &highlightSquareColor);
     forceMono |= MakeOneColor(appData.premoveHighlightColor, &premoveHighlightColor);
+    if (appData.lowTimeWarning)
+       forceMono |= MakeOneColor(appData.lowTimeWarningColor, &lowTimeWarningColor);
     if(appData.dialogColor[0]) MakeOneColor(appData.dialogColor, &dialogColor);
     if(appData.buttonColor[0]) MakeOneColor(appData.buttonColor, &buttonColor);
 
@@ -1090,6 +1100,9 @@ CreateAnyPieces ()
       CreateXPMBoard(appData.liteBackTextureFile, 1);
       CreateXPMBoard(appData.darkBackTextureFile, 0);
     }
+    if (appData.pngDirectory[0] != NULLCHAR) { // for now do in parallel
+      CreatePNGPieces();
+    }
 #else
     CreateXIMPieces();
     /* Create regular pieces */
@@ -1104,17 +1117,126 @@ InitDrawingParams ()
     CreateAnyPieces();
 }
 
+void
+InitializeFonts (int clockFontPxlSize, int coordFontPxlSize, int fontPxlSize)
+{   // detervtomine what fonts to use, and create them
+    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
+}
+
+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, j, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
+    int i, clockFontPxlSize, coordFontPxlSize, fontPxlSize;
     XSetWindowAttributes window_attributes;
     Arg args[16];
-    Dimension timerWidth, boardWidth, boardHeight, w, h, sep, bor, wr, hr;
-    XrmValue vFrom, vTo;
-    XtGeometryResult gres;
+    Dimension boardWidth, boardHeight, w, h;
     char *p;
-    XrmDatabase xdb;
     int forceMono = False;
 
     srandom(time(0)); // [HGM] book: make random truly random
@@ -1128,6 +1250,11 @@ main (int argc, char **argv)
        exit(0);
     }
 
+    if(argc > 1 && !strcmp(argv[1], "--help" )) {
+       PrintOptions();
+       exit(0);
+    }
+
     programName = strrchr(argv[0], '/');
     if (programName == NULL)
       programName = argv[0];
@@ -1136,14 +1263,14 @@ main (int argc, char **argv)
 
 #ifdef ENABLE_NLS
     XtSetLanguageProc(NULL, NULL, NULL);
+    if (appData.debugMode) {
+      fprintf(debugFP, "locale = %s\n", setlocale(LC_ALL, NULL));
+    }
+
     bindtextdomain(PACKAGE, LOCALEDIR);
     textdomain(PACKAGE);
 #endif
 
-    shellWidget =
-      XtAppInitialize(&appContext, "XBoard", shellOptions,
-                     XtNumber(shellOptions),
-                     &argc, argv, xboardResources, NULL, 0);
     appData.boardSize = "";
     InitAppData(ConvertToLine(argc, argv));
     p = getenv("HOME");
@@ -1154,10 +1281,6 @@ main (int argc, char **argv)
     snprintf(gameCopyFilename,i, "%s/.xboard%05uc.pgn", p, getpid());
     snprintf(gamePasteFilename,i, "%s/.xboard%05up.pgn", p, getpid());
 
-    XtGetApplicationResources(shellWidget, (XtPointer) &appData,
-                             clientResources, XtNumber(clientResources),
-                             NULL, 0);
-
     { // [HGM] initstring: kludge to fix bad bug. expand '\n' characters in init string and computer string.
        static char buf[MSG_SIZ];
        EscapeExpand(buf, appData.firstInitString);
@@ -1189,12 +1312,6 @@ 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   )
@@ -1206,13 +1323,25 @@ main (int argc, char **argv)
 #endif
     InitBackEnd1();
 
+       gameInfo.variant = StringToVariant(appData.variant);
+       InitPosition(FALSE);
+
+    shellWidget =
+      XtAppInitialize(&appContext, "XBoard", shellOptions,
+                     XtNumber(shellOptions),
+                     &argc, argv, xboardResources, NULL, 0);
+
+    XtGetApplicationResources(shellWidget, (XtPointer) &appData,
+                             clientResources, XtNumber(clientResources),
+                             NULL, 0);
+
     xDisplay = XtDisplay(shellWidget);
     xScreen = DefaultScreen(xDisplay);
     wm_delete_window = XInternAtom(xDisplay, "WM_DELETE_WINDOW", True);
 
-       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,
@@ -1269,12 +1398,6 @@ main (int argc, char **argv)
        tinyLayout = szd->tinyLayout;
        // [HGM] font: use defaults from settings file if available and not overruled
     }
-    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];
 
     /* Now, using squareSize as a hint, find a good XPM/XIM set size */
     if (strlen(appData.pixmapDirectory) > 0) {
@@ -1304,46 +1427,7 @@ XBoard square size (hint): %d\n\
     /*
      * Determine what fonts to use.
      */
-#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
+    InitializeFonts(clockFontPxlSize, coordFontPxlSize, fontPxlSize);
 
     /*
      * Detect if there are not enough colors available and adapt.
@@ -1360,16 +1444,6 @@ XBoard square size (hint): %d\n\
        appData.monoMode = True;
     }
 
-    if (appData.lowTimeWarning && !appData.monoMode) {
-      vFrom.addr = (caddr_t) appData.lowTimeWarningColor;
-      vFrom.size = strlen(appData.lowTimeWarningColor);
-      XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
-      if (vTo.addr == NULL)
-               appData.monoMode = True;
-      else
-               lowTimeWarningColor = *(Pixel *) vTo.addr;
-    }
-
     if (appData.monoMode && appData.debugMode) {
        fprintf(stderr, _("white pixel = 0x%lx, black pixel = 0x%lx\n"),
                (unsigned long) XWhitePixel(xDisplay, xScreen),
@@ -1395,20 +1469,20 @@ XBoard square size (hint): %d\n\
 #if ENABLE_NLS
                                                &clockFontSet);
 #else
-                                               &clockFonStruct);
+                                               clockFontStruct);
 #endif
-    boardWidget      = optList[22].handle;
-    menuBarWidget    = optList[ 0].handle;
-    dropMenu         = optList[25].handle;
-    titleWidget = optList[optList[10].type != -1 ? 10 : 13].handle;
+    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;
     formWidget  = XtParent(boardWidget);
     XtSetArg(args[0], XtNbackground, &timerBackgroundPixel);
     XtSetArg(args[1], XtNforeground, &timerForegroundPixel);
-    XtGetValues(optList[11].handle, args, 2);
+    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[18].handle, args, 2);
+      XtGetValues(optList[W_PAUSE].handle, args, 2);
     }
     AppendEnginesToMenu(appData.recentEngineList);
 
@@ -1461,6 +1535,13 @@ XBoard square size (hint): %d\n\
     CreateGrid();
     CreateAnyPieces();
 
+    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();
 
@@ -1508,6 +1589,7 @@ XBoard square size (hint): %d\n\
 
     gameInfo.boardWidth = 0; // [HGM] pieces: kludge to ensure InitPosition() calls InitDrawingSizes()
     InitPosition(TRUE);
+    UpdateLogos(TRUE);
 //    XtSetKeyboardFocus(shellWidget, formWidget);
     XSetInputFocus(xDisplay, XtWindow(formWidget), RevertToPointerRoot, CurrentTime);
 
@@ -1743,8 +1825,6 @@ CreateOneGC (XGCValues *gc_values, Pixel foreground, Pixel background)
 static void
 CreateGCs (int redo)
 {
-    XtGCMask value_mask = GCLineWidth | GCLineStyle | GCForeground
-      | GCBackground | GCFunction | GCPlaneMask;
     XGCValues gc_values;
     GC copyInvertedGC;
     Pixel white = XWhitePixel(xDisplay, xScreen);
@@ -2138,6 +2218,53 @@ CreateXPMPieces ()
 }
 #endif /* HAVE_LIBXPM */
 
+char *pngPieceNames[] = // must be in same order as internal piece encoding
+{ "Pawn", "Knight", "Bishop", "Rook", "Queen", "Advisor", "Elephant", "Archbishop", "Marshall", "Gold", "Commoner", 
+  "Canon", "Nightrider", "CrownedBishop", "CrownedRook", "Princess", "Chancellor", "Hawk", "Lance", "Cobra", "Unicorn", "King", 
+  "GoldKnight", "GoldLance", "GoldPawn", "GoldSilver", NULL
+};
+
+void
+ScaleOnePiece (char *name, int color, int piece)
+{
+  int w, h;
+  char buf[MSG_SIZ];
+  cairo_surface_t *img, *cs;
+  cairo_t *cr;
+  static cairo_surface_t *pngPieceImages[2][(int)BlackPawn+4];   // png 256 x 256 images
+
+  if(pngPieceImages[color][piece] == NULL) { // if PNG file for this piece was not yet read, read it now and store it
+    snprintf(buf, MSG_SIZ, "%s/%s%s.png", appData.pngDirectory, color ? "Black" : "White", pngPieceNames[piece]);
+    pngPieceImages[color][piece] = img = cairo_image_surface_create_from_png (buf);
+    w = cairo_image_surface_get_width (img);
+    h = cairo_image_surface_get_height (img);
+    if(w != 256 || h != 256) { printf("Bad png size %dx%d in %s\n", w, h, buf); exit(1); }
+  }
+
+  // create new bitmap to hold scaled piece image (and remove any old)
+  if(pngPieceBitmaps2[color][piece]) cairo_surface_destroy (pngPieceBitmaps2[color][piece]);
+  pngPieceBitmaps2[color][piece] = cs = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, squareSize, squareSize);
+  if(piece <= WhiteKing) pngPieceBitmaps[color][piece] = cs;
+  // scaled copying of the raw png image
+  cr = cairo_create(cs);
+  cairo_scale(cr, squareSize/256., squareSize/256.);
+  cairo_set_source_surface (cr, img, 0, 0);
+  cairo_paint (cr);
+  cairo_destroy (cr);
+  cairo_surface_destroy (img);
+}
+
+void
+CreatePNGPieces ()
+{
+  int p;
+
+  for(p=0; pngPieceNames[p]; p++) {
+    ScaleOnePiece(pngPieceNames[p], 0, p);
+    ScaleOnePiece(pngPieceNames[p], 1, p);
+  }
+}
+
 #if HAVE_LIBXPM
 /* No built-in bitmaps */
 void CreatePieces()
@@ -2282,7 +2409,7 @@ MarkMenuItem (char *menuRef, int state)
 }
 
 void
-EnableMenuItem (char *menuRef, int state)
+EnableNamedMenuItem (char *menuRef, int state)
 {
     MenuItem *item = MenuNameToItem(menuRef);
 
@@ -2292,7 +2419,7 @@ EnableMenuItem (char *menuRef, int state)
 void
 EnableButtonBar (int state)
 {
-    XtSetSensitive(optList[15].handle, state);
+    XtSetSensitive(optList[W_BUTTON].handle, state);
 }
 
 
@@ -2300,7 +2427,7 @@ void
 SetMenuEnables (Enables *enab)
 {
   while (enab->name != NULL) {
-    EnableMenuItem(enab->name, enab->value);
+    EnableNamedMenuItem(enab->name, enab->value);
     enab++;
   }
 }
@@ -2308,8 +2435,6 @@ SetMenuEnables (Enables *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
-    int i;
-    char *p;
     MenuItem *item;
     if(*nprms == 0) return;
     item = MenuNameToItem(prms[0]);
@@ -2317,14 +2442,6 @@ KeyBindingProc (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 }
 
 static void
-MenuBarSelect (Widget w, caddr_t addr, caddr_t index)
-{
-    MenuProc *proc = (MenuProc *) addr;
-
-    (proc)();
-}
-
-static void
 MenuEngineSelect (Widget w, caddr_t addr, caddr_t index)
 {
     RecentEngineEvent((int) (intptr_t) addr);
@@ -2333,7 +2450,7 @@ MenuEngineSelect (Widget w, caddr_t addr, caddr_t index)
 void
 AppendMenuItem (char *msg, int n)
 {
-    CreateMenuItem((Widget) optList[6].textValue, msg, (XtCallbackProc) MenuEngineSelect, n);
+    CreateMenuItem((Widget) optList[W_ENGIN].textValue, msg, (XtCallbackProc) MenuEngineSelect, n);
 }
 
 void
@@ -2368,15 +2485,21 @@ do_flash_delay (unsigned long msec)
     TimeDelay(msec);
 }
 
+static cairo_surface_t *cs; // to keep out of back-end :-(
+
 void
 DrawBorder (int x, int y, int type)
 {
-    GC gc = lineGC;
+    cairo_t *cr;
+    DrawSeekOpen();
 
-    if(type == 1) gc = highlineGC; else if(type == 2) gc = prelineGC;
+    cr = cairo_create(cs);
+    cairo_set_antialias(cr, CAIRO_ANTIALIAS_NONE);
+    cairo_rectangle(cr, x, y, squareSize+lineGap, squareSize+lineGap);
+    SetPen(cr, lineGap, type == 1 ? appData.highlightSquareColor : appData.premoveHighlightColor, 0);
+    cairo_stroke(cr);
 
-    XDrawRectangle(xDisplay, xBoardWindow, gc, x, y,
-                  squareSize+lineGap, squareSize+lineGap);
+    DrawSeekClose();
 }
 
 static int
@@ -2397,6 +2520,27 @@ CutOutSquare (int x, int y, int *x0, int *y0, int  kind)
     return 1;
 }
 
+void
+DrawLogo (void *handle, void *logo)
+{
+    cairo_surface_t *img, *cs;
+    cairo_t *cr;
+    int w, h;
+
+    if(!logo || !handle) return;
+    cs = cairo_xlib_surface_create(xDisplay, XtWindow(handle), DefaultVisual(xDisplay, 0), appData.logoSize, appData.logoSize/2);
+    img = cairo_image_surface_create_from_png (logo);
+    w = cairo_image_surface_get_width (img);
+    h = cairo_image_surface_get_height (img);
+    cr = cairo_create(cs);
+    cairo_scale(cr, (float)appData.logoSize/w, appData.logoSize/(2.*h));
+    cairo_set_source_surface (cr, img, 0, 0);
+    cairo_paint (cr);
+    cairo_destroy (cr);
+    cairo_surface_destroy (img);
+    cairo_surface_destroy (cs);
+}
+
 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
@@ -2552,6 +2696,28 @@ colorDrawPieceImage (ChessSquare piece, int square_color, int x, int y, Drawable
              squareSize, squareSize, x, y);
 }
 
+static void
+pngDrawPiece (ChessSquare piece, int square_color, int x, int y, Drawable dest)
+{
+    int kind, p = piece;
+    cairo_t *cr;
+
+    if ((int)piece < (int) BlackPawn) {
+       kind = 0;
+    } else {
+       kind = 1;
+       piece -= BlackPawn;
+    }
+    if(appData.upsideDown && flipView) { p += p < BlackPawn ? BlackPawn : -BlackPawn; }// swap white and black pieces
+    BlankSquare(x, y, square_color, piece, dest, 1); // erase previous contents with background
+    DrawSeekOpen();
+    cr = cairo_create (cs);
+    cairo_set_source_surface (cr, pngPieceBitmaps[kind][piece], x, y);
+    cairo_paint(cr);
+    cairo_destroy (cr);
+    DrawSeekClose();
+}
+
 typedef void (*DrawFunc)();
 
 DrawFunc
@@ -2563,6 +2729,8 @@ ChooseDrawFunc ()
        } else {
            return monoDrawPiece;
        }
+    } else if(appData.pngDirectory[0]) {
+       return pngDrawPiece;
     } else {
        if (useImages)
          return colorDrawPieceImage;
@@ -2574,14 +2742,22 @@ ChooseDrawFunc ()
 void
 DrawDot (int marker, int x, int y, int r)
 {
+       cairo_t *cr;
+       DrawSeekOpen();
+       cr = cairo_create(cs);
+       cairo_arc(cr, x+r/2, y+r/2, r/2, 0.0, 2*M_PI);
        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);
+           SetPen(cr, 2, marker == 2 ? "#000000" : "#FFFFFF", 0);
+           cairo_stroke_preserve(cr);
+           SetPen(cr, 2, marker == 2 ? "#FFFFFF" : "#000000", 0);
+       } else {
+           SetPen(cr, 2, marker == 2 ? "#FF0000" : "#FFFF00", 0);
+       }
+       cairo_fill(cr);
+       cairo_stroke(cr);
+
+       cairo_destroy(cr);
+       DrawSeekClose();
 }
 
 void
@@ -2715,48 +2891,143 @@ EventProc (Widget widget, caddr_t unused, XEvent *event)
        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)
+// [HGM] seekgraph: some low-level drawing routines (by JC, mostly)
+
+float
+Color (char *col, int n)
 {
-      XDrawLine(xDisplay, xBoardWindow, lineGC, x, y, xTo, yTo);
+  int c;
+  sscanf(col, "#%x", &c);
+  c = c >> 4*n & 255;
+  return c/255.;
 }
 
 void
-DrawSeekBackground (int left, int top, int right, int bottom)
+SetPen (cairo_t *cr, float w, char *col, int dash)
 {
-    XFillRectangle(xDisplay, xBoardWindow, lightSquareGC, left, top, right-left, bottom-top);
+  static const double dotted[] = {4.0, 4.0};
+  static int len  = sizeof(dotted) / sizeof(dotted[0]);
+  cairo_set_line_width (cr, w);
+  cairo_set_source_rgba (cr, Color(col, 4), Color(col, 2), Color(col, 0), 1.0);
+  if(dash) cairo_set_dash (cr, dotted, len, 0.0);
 }
 
-void
-DrawSeekText (char *buf, int x, int y)
+void DrawSeekAxis( int x, int y, int xTo, int yTo )
 {
-    XDrawString(xDisplay, xBoardWindow, coordGC, x, y+4, buf, strlen(buf));
+    cairo_t *cr;
+
+    /* get a cairo_t */
+    cr = cairo_create (cs);
+
+    cairo_move_to (cr, x, y);
+    cairo_line_to(cr, xTo, yTo );
+
+    SetPen(cr, 2, "#000000", 0);
+    cairo_stroke(cr);
+
+    /* free memory */
+    cairo_destroy (cr);
 }
 
-void
-DrawSeekDot (int x, int y, int colorNr)
+void DrawSeekBackground( int left, int top, int right, int bottom )
+{
+    cairo_t *cr = cairo_create (cs);
+
+    cairo_rectangle (cr, left, top, right-left, bottom-top);
+
+    cairo_set_source_rgba(cr, 0.8, 0.8, 0.4,1.0);
+    cairo_fill(cr);
+
+    /* free memory */
+    cairo_destroy (cr);
+}
+
+void DrawSeekText(char *buf, int x, int y)
 {
+    cairo_t *cr = cairo_create (cs);
+
+    cairo_select_font_face (cr, "Sans",
+                           CAIRO_FONT_SLANT_NORMAL,
+                           CAIRO_FONT_WEIGHT_NORMAL);
+
+    cairo_set_font_size (cr, 12.0);
+
+    cairo_move_to (cr, x, y+4);
+    cairo_show_text( cr, buf);
+
+    cairo_set_source_rgba(cr, 0, 0, 0,1.0);
+    cairo_stroke(cr);
+
+    /* free memory */
+    cairo_destroy (cr);
+}
+
+void DrawSeekDot(int x, int y, int colorNr)
+{
+    cairo_t *cr = cairo_create (cs);
     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);
+       cairo_rectangle (cr, 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);
+       cairo_arc(cr, x, y, squareSize/8, 0.0, 2*M_PI);
+
+    SetPen(cr, 2, "#000000", 0);
+    cairo_stroke_preserve(cr);
+    switch (colorNr) {
+      case 0: cairo_set_source_rgba(cr, 1.0, 0, 0,1.0);        break;
+      case 1: cairo_set_source_rgba (cr, 0.0, 0.7, 0.2, 1.0); break;
+      default: cairo_set_source_rgba (cr, 1.0, 1.0, 0.0, 1.0); break;
+    }
+    cairo_fill(cr);
+
+    /* free memory */
+    cairo_destroy (cr);
 }
 
 void
-DrawGrid (int second)
+DrawSeekOpen ()
 {
-         XDrawSegments(xDisplay, xBoardWindow, lineGC,
-                       second ? secondSegments : // [HGM] dual
-                       gridSegments, BOARD_HEIGHT + BOARD_WIDTH + 2);
+    int boardWidth = lineGap + BOARD_WIDTH * (squareSize + lineGap);
+    int boardHeight = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
+    cs = cairo_xlib_surface_create(xDisplay, xBoardWindow, DefaultVisual(xDisplay, 0), boardWidth, boardHeight);
 }
 
+void
+DrawSeekClose ()
+{
+    cairo_surface_destroy(cs);
+}
+
+void
+DrawGrid()
+{
+  /* draws a grid starting around Nx, Ny squares starting at x,y */
+  int i;
+  cairo_t *cr;
+
+  DrawSeekOpen();
+  /* get a cairo_t */
+  cr = cairo_create (cs);
+
+  cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+  SetPen(cr, lineGap, "#000000", 0);
+
+  /* lines in X */
+  for (i = 0; i < BOARD_WIDTH + BOARD_HEIGHT + 2; i++)
+    {
+      cairo_move_to (cr, gridSegments[i].x1, gridSegments[i].y1);
+      cairo_line_to (cr, gridSegments[i].x2, gridSegments[i].y2);
+      cairo_stroke (cr);
+    }
+
+  /* free memory */
+  cairo_destroy (cr);
+  DrawSeekClose();
+
+  return;
+}
 
 /*
  * event handler for redrawing the board
@@ -2812,29 +3083,6 @@ 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
-       if(openFP = XsraSelFile(shellWidget, label, NULL, NULL, _("could not open: "),
-                          (def[0] ? def : NULL), filter, openMode, NULL, &openName))
-         // [HGM] delay to give expose event opportunity to redraw board after browser-dialog popdown before lengthy load starts
-         ScheduleDelayedEvent(&DelayedLoad, 50);
-    }
-}
-
 
 /* Disable all user input other than deleting the window */
 static int frozen = 0;
@@ -2844,7 +3092,7 @@ FreezeUI ()
 {
   if (frozen) return;
   /* Grab by a widget that doesn't accept input */
-  XtAddGrab(optList[14].handle, TRUE, FALSE);
+  XtAddGrab(optList[W_MESSG].handle, TRUE, FALSE);
   frozen = 1;
 }
 
@@ -2853,7 +3101,7 @@ void
 ThawUI ()
 {
   if (!frozen) return;
-  XtRemoveGrab(optList[14].handle);
+  XtRemoveGrab(optList[W_MESSG].handle);
   frozen = 0;
 }
 
@@ -2879,12 +3127,12 @@ ModeHighlight ()
            Pixel oldbg, oldfg;
            XtSetArg(args[0], XtNbackground, &oldbg);
            XtSetArg(args[1], XtNforeground, &oldfg);
-           XtGetValues(optList[18].handle,
+           XtGetValues(optList[W_PAUSE].handle,
                        args, 2);
            XtSetArg(args[0], XtNbackground, oldfg);
            XtSetArg(args[1], XtNforeground, oldbg);
          }
-         XtSetValues(optList[18].handle, args, 2);
+         XtSetValues(optList[W_PAUSE].handle, args, 2);
        }
     }
 
@@ -2900,31 +3148,15 @@ 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].handle, optList[W_BLACK+1].handle);
 }
 
 
 /*
  * Button/menu procedures
  */
-int
-LoadGamePopUp (FILE *f, int gameNumber, char *title)
-{
-    cmailMsgLoaded = FALSE;
-    if (gameNumber == 0) {
-       int error = GameListBuild(f);
-       if (error) {
-           DisplayError(_("Cannot build game list"), error);
-       } else if (!ListEmpty(&gameList) &&
-                  ((ListGame *) gameList.tailPred)->number > 1) {
-           GameListPopUp(f, title);
-           return TRUE;
-       }
-       GameListDestroy();
-       gameNumber = 1;
-    }
-    return LoadGame(f, gameNumber, title, FALSE);
-}
 
 /* this variable is shared between CopyPositionProc and SendPositionSelection */
 char *selected_fen_position=NULL;
@@ -3178,6 +3410,12 @@ ManInner (Widget w, XEvent *event, String *prms, Cardinal *nprms)
 }
 
 void
+ManProc ()
+{   // called from menu
+    ManInner(NULL, NULL, NULL, NULL);
+}
+
+void
 SetWindowTitle (char *text, char *title, char *icon)
 {
     Arg args[16];
@@ -3366,11 +3604,11 @@ StartClockTimer (long millisec)
 }
 
 void
-DisplayTimerLabel (int optNr, char *color, long timer, int highlight)
+DisplayTimerLabel (Option *opt, char *color, long timer, int highlight)
 {
     char buf[MSG_SIZ];
     Arg args[16];
-    Widget w = optList[optNr].handle;
+    Widget w = (Widget) opt->handle;
 
     /* check for low time warning */
     Pixel foregroundOrWarningColor = timerForegroundPixel;
@@ -3381,7 +3619,7 @@ DisplayTimerLabel (int optNr, char *color, long timer, int highlight)
       foregroundOrWarningColor = lowTimeWarningColor;
 
     if (appData.clockMode) {
-      snprintf(buf, MSG_SIZ, "%s: %s", color, TimeString(timer));
+      snprintf(buf, MSG_SIZ, "%s:%s%s", color, appData.logoSize && !partnerUp ? "\n" : " ", TimeString(timer));
       XtSetArg(args[0], XtNlabel, buf);
     } else {
       snprintf(buf, MSG_SIZ, "%s  ", color);
@@ -3773,19 +4011,56 @@ SetDragPiece (AnimNr anr, ChessSquare piece)
 
 /* [AS] Arrow highlighting support */
 
-void
-DrawPolygon (Pnt arrow[], int nr)
-{
-    XPoint pts[10];
+void DrawPolygon(Pnt arrow[], int nr)
+{   // for now on own surface; eventually this should become a global that is only destroyed on resize
+    cairo_surface_t *boardSurface;
+    cairo_t *cr;
     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);
+    int w = lineGap + BOARD_WIDTH * (squareSize + lineGap);
+    int h = lineGap + BOARD_HEIGHT * (squareSize + lineGap);
+    boardSurface = cairo_xlib_surface_create(xDisplay, xBoardWindow, DefaultVisual(xDisplay, 0), w, h);
+    cr = cairo_create (boardSurface);
+    cairo_move_to (cr, arrow[nr-1].x, arrow[nr-1].y);
+    for (i=0;i<nr;i++) {
+        cairo_line_to(cr, arrow[i].x, arrow[i].y);
+    }
+    if(appData.monoMode) { // should we always outline arrow?
+        cairo_line_to(cr, arrow[0].x, arrow[0].y);
+        SetPen(cr, 2, "#000000", 0);
+        cairo_stroke_preserve(cr);
+    }
+    SetPen(cr, 2, appData.highlightSquareColor, 0);
+    cairo_fill(cr);
+
+    /* free memory */
+    cairo_destroy (cr);
+    cairo_surface_destroy (boardSurface);
+}
+
+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 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].handle, optList[W_BLACK+1].handle);
+    return;
 }