Merge commit 'v4.3.16'
[xboard.git] / winboard / winboard.c
index 21460fd..fb64ff7 100644 (file)
 \r
 #include "wsnap.h"\r
 \r
-void InitEngineUCI( const char * iniDir, ChessProgramState * cps );\r
+//void InitEngineUCI( const char * iniDir, ChessProgramState * cps );\r
 \r
   int myrandom(void);\r
   void mysrandom(unsigned int seed);\r
 \r
 extern int whiteFlag, blackFlag;\r
+Boolean flipClock = FALSE;\r
 \r
 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);\r
 \r
@@ -137,9 +138,10 @@ char installDir[MSG_SIZ];
 BoardSize boardSize;\r
 BOOLEAN chessProgram;\r
 static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;\r
-static int squareSize, lineGap;\r
+static int squareSize, lineGap, minorSize;\r
 static int winWidth, winHeight;\r
-static RECT messageRect, whiteRect, blackRect;\r
+static RECT messageRect, whiteRect, blackRect, leftLogoRect, rightLogoRect; // [HGM] logo\r
+static int logoHeight = 0;\r
 static char messageText[MESSAGE_TEXT_MAX];\r
 static int clockTimerEvent = 0;\r
 static int loadGameTimerEvent = 0;\r
@@ -387,6 +389,7 @@ LRESULT CALLBACK
 VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);\r
 void ParseIcsTextMenu(char *icsTextMenuString);\r
 VOID PopUpMoveDialog(char firstchar);\r
+VOID PopUpNameDialog(char firstchar);\r
 VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);\r
 \r
 /* [AS] */\r
@@ -423,7 +426,7 @@ VOID EngineOutputPopDown();
 BOOL EngineOutputIsUp();\r
 VOID EngineOutputUpdate( FrontEndProgramStats * stats );\r
 \r
-VOID GothicPopUp(char *title);\r
+VOID GothicPopUp(char *title, VariantClass variant);\r
 /*\r
  * Setting "frozen" should disable all user input other than deleting\r
  * the window.  We do this while engines are initializing themselves.\r
@@ -596,8 +599,8 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
 \r
   InitBackEnd1();\r
 \r
-  InitEngineUCI( installDir, &first );\r
-  InitEngineUCI( installDir, &second );\r
+//  InitEngineUCI( installDir, &first ); // [HGM] incorporated in InitBackEnd1()\r
+//  InitEngineUCI( installDir, &second );\r
 \r
   /* Create a main window for this application instance. */\r
   hwnd = CreateWindow(szAppName, szTitle,\r
@@ -611,6 +614,35 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
     return (FALSE);\r
   }\r
 \r
+  /* [HGM] logo: Load logos if specified (must be done before InitDrawingSizes) */\r
+  if( appData.firstLogo && appData.firstLogo[0] != NULLCHAR) {\r
+      first.programLogo = LoadImage( 0, appData.firstLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
+\r
+      if (first.programLogo == NULL && appData.debugMode) {\r
+          fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.firstLogo );\r
+      }\r
+  } else if(appData.autoLogo) {\r
+      if(appData.firstDirectory && appData.firstDirectory[0]) {\r
+       char buf[MSG_SIZ];\r
+       sprintf(buf, "%s/logo.bmp", appData.firstDirectory);\r
+       first.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );   \r
+      }\r
+  }\r
+\r
+  if( appData.secondLogo && appData.secondLogo[0] != NULLCHAR) {\r
+      second.programLogo = LoadImage( 0, appData.secondLogo, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );\r
+\r
+      if (second.programLogo == NULL && appData.debugMode) {\r
+          fprintf( debugFP, "Unable to load logo bitmap '%s'\n", appData.secondLogo );\r
+      }\r
+  } else if(appData.autoLogo) {\r
+      if(appData.secondDirectory && appData.secondDirectory[0]) {\r
+       char buf[MSG_SIZ];\r
+       sprintf(buf, "%s\\logo.bmp", appData.secondDirectory);\r
+       second.programLogo = LoadImage( 0, buf, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );  \r
+      }\r
+  }\r
+\r
   iconWhite = LoadIcon(hInstance, "icon_white");\r
   iconBlack = LoadIcon(hInstance, "icon_black");\r
   iconCurrent = iconWhite;\r
@@ -628,6 +660,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
       boardSize = (BoardSize)ibs;\r
     }\r
   }\r
+\r
   InitDrawingSizes(boardSize, 0);\r
   InitMenuChecks();\r
   buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);\r
@@ -655,11 +688,6 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
 \r
   mysrandom( (unsigned) time(NULL) );\r
 \r
-  /* Make a console window if needed */\r
-  if (appData.icsActive) {\r
-    ConsoleCreate();\r
-  }\r
-\r
   /* [AS] Restore layout */\r
   if( wpMoveHistory.visible ) {\r
       MoveHistoryPopUp();\r
@@ -690,17 +718,12 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
   SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
                0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
 \r
+#if 0\r
   /* [AS] Disable the FRC stuff if not playing the proper variant */\r
   if( gameInfo.variant != VariantFischeRandom ) {\r
       EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );\r
   }\r
-#ifdef FAIRY\r
-#ifdef GOTHIC\r
-  /* [HGM] Gothic licensing requirement */\r
-  if(gameInfo.variant == VariantGothic)\r
-      GothicPopUp(GOTHIC);\r
-#endif // GOTHIC\r
-#endif // FAIRY\r
+#endif\r
   if (hwndConsole) {\r
 #if AOT_CONSOLE\r
     SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
@@ -1171,14 +1194,30 @@ ArgDescriptor argDescriptors[] = {
   { "boardWidth", ArgInt, (LPVOID) &appData.NrFiles, TRUE },\r
   { "boardHeight", ArgInt, (LPVOID) &appData.NrRanks, TRUE },\r
   { "holdingsSize", ArgInt, (LPVOID) &appData.holdingsSize, TRUE },\r
-  { "matchPause", ArgInt, (LPVOID) &appData.matchPause, FALSE },\r
-  { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, TRUE },\r
+  { "matchPause", ArgInt, (LPVOID) &appData.matchPause, TRUE },\r
+  { "pieceToCharTable", ArgString, (LPVOID) &appData.pieceToCharTable, FALSE },\r
+  { "flipBlack", ArgBoolean, (LPVOID) &appData.upsideDown, TRUE },\r
+  { "allWhite", ArgBoolean, (LPVOID) &appData.allWhite, TRUE },\r
+  { "alphaRank", ArgBoolean, (LPVOID) &appData.alphaRank, FALSE },\r
+  { "firstAlphaRank", ArgBoolean, (LPVOID) &first.alphaRank, FALSE },\r
+  { "secondAlphaRank", ArgBoolean, (LPVOID) &second.alphaRank, FALSE },\r
   { "testClaims", ArgBoolean, (LPVOID) &appData.testClaims, TRUE },\r
   { "checkMates", ArgBoolean, (LPVOID) &appData.checkMates, TRUE },\r
   { "materialDraws", ArgBoolean, (LPVOID) &appData.materialDraws, TRUE },\r
   { "trivialDraws", ArgBoolean, (LPVOID) &appData.trivialDraws, TRUE },\r
   { "ruleMoves", ArgInt, (LPVOID) &appData.ruleMoves, TRUE },\r
   { "repeatsToDraw", ArgInt, (LPVOID) &appData.drawRepeats, TRUE },\r
+  { "autoKibitz", ArgTrue, (LPVOID) &appData.autoKibitz, FALSE },\r
+  { "engineDebugOutput", ArgInt, (LPVOID) &appData.engineComments, FALSE },\r
+  { "userName", ArgString, (LPVOID) &appData.userName, FALSE },\r
+  { "rewindIndex", ArgInt, (LPVOID) &appData.rewindIndex, FALSE },\r
+  { "sameColorGames", ArgInt, (LPVOID) &appData.sameColorGames, FALSE },\r
+  { "smpCores", ArgInt, (LPVOID) &appData.smpCores, TRUE },\r
+  { "egtFormats", ArgString, (LPVOID) &appData.egtFormats, TRUE },\r
+  { "niceEngines", ArgInt, (LPVOID) &appData.niceEngines, TRUE },\r
+  { "firstLogo", ArgFilename, (LPVOID) &appData.firstLogo, FALSE },\r
+  { "secondLogo", ArgFilename, (LPVOID) &appData.secondLogo, FALSE },\r
+  { "autoLogo", ArgBoolean, (LPVOID) &appData.autoLogo, TRUE },\r
 \r
 #ifdef ZIPPY\r
   { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },\r
@@ -1222,6 +1261,18 @@ ArgDescriptor argDescriptors[] = {
   /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */\r
   { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },\r
 #endif\r
+  /* [HGM] options for broadcasting and time odds */\r
+  { "serverMoves", ArgString, (LPVOID) &appData.serverMovesName, FALSE },\r
+  { "suppressLoadMoves", ArgBoolean, (LPVOID) &appData.suppressLoadMoves, FALSE },\r
+  { "serverPause", ArgInt, (LPVOID) &appData.serverPause, FALSE },\r
+  { "firstTimeOdds", ArgInt, (LPVOID) &appData.firstTimeOdds, FALSE },\r
+  { "secondTimeOdds", ArgInt, (LPVOID) &appData.secondTimeOdds, FALSE },\r
+  { "timeOddsMode", ArgInt, (LPVOID) &appData.timeOddsMode, TRUE },\r
+  { "firstAccumulateTC", ArgInt, (LPVOID) &appData.firstAccumulateTC, FALSE },\r
+  { "secondAccumulateTC", ArgInt, (LPVOID) &appData.secondAccumulateTC, FALSE },\r
+  { "firstNPS", ArgInt, (LPVOID) &appData.firstNPS, FALSE },\r
+  { "secondNPS", ArgInt, (LPVOID) &appData.secondNPS, FALSE },\r
+  { "noGUI", ArgTrue, (LPVOID) &appData.noGUI, FALSE },\r
   { NULL, ArgNone, NULL, FALSE }\r
 };\r
 \r
@@ -1783,6 +1834,7 @@ InitAppData(LPSTR lpCmdLine)
   appData.reuseFirst = TRUE;\r
   appData.reuseSecond = TRUE;\r
   appData.blindfold = FALSE;\r
+  appData.icsEngineAnalyze = FALSE;\r
   dcb.DCBlength = sizeof(DCB);\r
   dcb.BaudRate = 9600;\r
   dcb.fBinary = TRUE;\r
@@ -1797,7 +1849,12 @@ InitAppData(LPSTR lpCmdLine)
   dcb.fNull = FALSE;\r
   dcb.fRtsControl = RTS_CONTROL_ENABLE;\r
   dcb.fAbortOnError = FALSE;\r
-  dcb.wReserved = 0;\r
+  /* Microsoft SDK >= Feb. 2003 (MS VS >= 2002) */\r
+  #if (defined(_MSC_VER) && _MSC_VER <= 1200) \r
+       //dcb.wReserved = 0;\r
+  #else\r
+    dcb.wReserved = 0;\r
+  #endif\r
   dcb.ByteSize = 7;\r
   dcb.Parity = SPACEPARITY;\r
   dcb.StopBits = ONESTOPBIT;\r
@@ -1896,6 +1953,20 @@ InitAppData(LPSTR lpCmdLine)
   appData.drawRepeats  = 6;\r
   appData.matchPause   = 10000;\r
   appData.alphaRank    = FALSE;\r
+  appData.allWhite     = FALSE;\r
+  appData.upsideDown   = FALSE;\r
+  appData.serverPause  = 15;\r
+  appData.serverMovesName   = NULL;\r
+  appData.suppressLoadMoves = FALSE;\r
+  appData.firstTimeOdds  = 1;\r
+  appData.secondTimeOdds = 1;\r
+  appData.firstAccumulateTC  = 1; // combine previous and current sessions\r
+  appData.secondAccumulateTC = 1;\r
+  appData.firstNPS  = -1; // [HGM] nps: use wall-clock time\r
+  appData.secondNPS = -1;\r
+  appData.engineComments = 1;\r
+  appData.smpCores = 1; // [HGM] SMP: max nr of cores\r
+  appData.egtFormats = "";\r
 \r
 #ifdef ZIPPY\r
   appData.zippyTalk = ZIPPY_TALK;\r
@@ -1940,6 +2011,35 @@ InitAppData(LPSTR lpCmdLine)
      appData.NrRanks > BOARD_SIZE   )\r
       DisplayFatalError("Recompile with BOARD_SIZE > 12, to support this size", 0, 2);\r
 \r
+  /* [HGM] After parsing the options from the .ini file, and overruling them\r
+   * with options from the command line, we now make an even higher priority\r
+   * overrule by WB options attached to the engine command line. This so that\r
+   * tournament managers can use WB options (such as /timeOdds) that follow\r
+   * the engines.\r
+   */\r
+  if(appData.firstChessProgram != NULL) {\r
+      char *p = StrStr(appData.firstChessProgram, "WBopt");\r
+      static char *f = "first";\r
+      char buf[MSG_SIZ], *q = buf;\r
+      if(p != NULL) { // engine command line contains WinBoard options\r
+          sprintf(buf, p+6, f, f, f, f, f, f, f, f, f, f); // replace %s in them by "first"\r
+          ParseArgs(StringGet, &q);\r
+          p[-1] = 0; // cut them offengine command line\r
+      }\r
+  }\r
+  // now do same for second chess program\r
+  if(appData.secondChessProgram != NULL) {\r
+      char *p = StrStr(appData.secondChessProgram, "WBopt");\r
+      static char *s = "second";\r
+      char buf[MSG_SIZ], *q = buf;\r
+      if(p != NULL) { // engine command line contains WinBoard options\r
+          sprintf(buf, p+6, s, s, s, s, s, s, s, s, s, s); // replace %s in them by "first"\r
+          ParseArgs(StringGet, &q);\r
+          p[-1] = 0; // cut them offengine command line\r
+      }\r
+  }\r
+\r
+\r
   /* Propagate options that affect others */\r
   if (appData.matchMode || appData.matchGames) chessProgram = TRUE;\r
   if (appData.icsActive || appData.noChessProgram) {\r
@@ -2300,36 +2400,44 @@ enum {
     PM_WB = (int) WhiteBishop, \r
     PM_WR = (int) WhiteRook, \r
     PM_WQ = (int) WhiteQueen, \r
-#ifdef FAIRY\r
     PM_WF = (int) WhiteFerz, \r
     PM_WW = (int) WhiteWazir, \r
     PM_WE = (int) WhiteAlfil, \r
+    PM_WM = (int) WhiteMan, \r
+    PM_WO = (int) WhiteCannon, \r
+    PM_WU = (int) WhiteUnicorn, \r
     PM_WH = (int) WhiteNightrider, \r
-    PM_WA = (int) WhiteCardinal, \r
+    PM_WA = (int) WhiteAngel, \r
     PM_WC = (int) WhiteMarshall, \r
+    PM_WAB = (int) WhiteCardinal, \r
+    PM_WD = (int) WhiteDragon, \r
+    PM_WL = (int) WhiteLance, \r
+    PM_WS = (int) WhiteCobra, \r
+    PM_WV = (int) WhiteFalcon, \r
+    PM_WSG = (int) WhiteSilver, \r
     PM_WG = (int) WhiteGrasshopper, \r
-    PM_WO = (int) WhiteCannon, \r
-    PM_WM = (int) WhiteMan, \r
-    PM_WU = (int) WhiteUnicorn, \r
-#endif\r
     PM_WK = (int) WhiteKing,\r
     PM_BP = (int) BlackPawn, \r
     PM_BN = (int) BlackKnight, \r
     PM_BB = (int) BlackBishop, \r
     PM_BR = (int) BlackRook, \r
     PM_BQ = (int) BlackQueen, \r
-#ifdef FAIRY\r
     PM_BF = (int) BlackFerz, \r
     PM_BW = (int) BlackWazir, \r
     PM_BE = (int) BlackAlfil, \r
+    PM_BM = (int) BlackMan,\r
+    PM_BO = (int) BlackCannon, \r
+    PM_BU = (int) BlackUnicorn, \r
     PM_BH = (int) BlackNightrider, \r
-    PM_BA = (int) BlackCardinal, \r
+    PM_BA = (int) BlackAngel, \r
     PM_BC = (int) BlackMarshall, \r
     PM_BG = (int) BlackGrasshopper, \r
-    PM_BO = (int) BlackCannon, \r
-    PM_BM = (int) BlackMan,\r
-    PM_BU = (int) BlackUnicorn, \r
-#endif\r
+    PM_BAB = (int) BlackCardinal,\r
+    PM_BD = (int) BlackDragon,\r
+    PM_BL = (int) BlackLance,\r
+    PM_BS = (int) BlackCobra,\r
+    PM_BV = (int) BlackFalcon,\r
+    PM_BSG = (int) BlackSilver,\r
     PM_BK = (int) BlackKing\r
 };\r
 \r
@@ -2339,36 +2447,13 @@ static HBITMAP hPieceFace[(int) EmptySquare];
 static int fontBitmapSquareSize = 0;\r
 static char pieceToFontChar[(int) EmptySquare] =\r
                               { 'p', 'n', 'b', 'r', 'q', \r
-#ifdef FAIRY\r
                       'n', 'b', 'p', 'n', 'b', 'r', 'b', 'r', 'q', 'k',\r
-#endif\r
                       'k', 'o', 'm', 'v', 't', 'w', \r
-#ifdef FAIRY\r
                       'v', 't', 'o', 'm', 'v', 't', 'v', 't', 'w', 'l',\r
-#endif\r
                                                               'l' };\r
 \r
-static BOOL SetPieceToFontCharTable( const char * map )\r
-{\r
-    BOOL result = FALSE; int NrPieces;\r
-\r
-    if( map != NULL && (NrPieces=strlen(map)) <= (int) EmptySquare \r
-                    && NrPieces >= 12 && !(NrPieces&1)) {\r
-        int i; /* [HGM] Accept even length from 12 to 32 */\r
-\r
-        for( i=0; i<(int) EmptySquare; i++ ) pieceToFontChar[i] = 0;\r
-        for( i=0; i<NrPieces/2-1; i++ ) {\r
-            pieceToFontChar[i] = map[i];\r
-            pieceToFontChar[i + (int)BlackPawn - (int) WhitePawn] = map[i+NrPieces/2];\r
-        }\r
-        pieceToFontChar[(int) WhiteKing]  = map[NrPieces/2-1];\r
-        pieceToFontChar[(int) BlackKing]  = map[NrPieces-1];\r
-\r
-        result = TRUE;\r
-    }\r
-\r
-    return result;\r
-}\r
+extern BOOL SetCharTable( char *table, const char * map );\r
+/* [HGM] moved to backend.c */\r
 \r
 static void SetPieceBackground( HDC hdc, COLORREF color, int mode )\r
 {\r
@@ -2451,13 +2536,12 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
     POINT pt;\r
     int backColor = whitePieceColor; \r
     int foreColor = blackPieceColor;\r
-    int shapeIndex = index < 6 ? index+6 : index;\r
     \r
-    if( index < 6 && appData.fontBackColorWhite != appData.fontForeColorWhite ) {\r
+    if( index < (int)BlackPawn && appData.fontBackColorWhite != appData.fontForeColorWhite ) {\r
         backColor = appData.fontBackColorWhite;\r
         foreColor = appData.fontForeColorWhite;\r
     }\r
-    else if( index >= 6 && appData.fontBackColorBlack != appData.fontForeColorBlack ) {\r
+    else if( index >= (int)BlackPawn && appData.fontBackColorBlack != appData.fontForeColorBlack ) {\r
         backColor = appData.fontBackColorBlack;\r
         foreColor = appData.fontForeColorBlack;\r
     }\r
@@ -2483,11 +2567,15 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
     SetBkMode( hdc, TRANSPARENT );\r
     SetTextColor( hdc, chroma );\r
     /* Step 2: the piece has been drawn in purple, there are now black and purple in this bitmap */\r
-    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 );\r
+    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
 \r
     SelectObject( hdc, GetStockObject(WHITE_BRUSH) );\r
     /* Step 3: the area outside the piece is filled with white */\r
-    FloodFill( hdc, 0, 0, chroma );\r
+//    FloodFill( hdc, 0, 0, chroma );\r
+    ExtFloodFill( hdc, 0, 0, 0, FLOODFILLSURFACE );\r
+    ExtFloodFill( hdc, 0, squareSize-1, 0, FLOODFILLSURFACE ); // [HGM] fill from all 4 corners, for if piece too big\r
+    ExtFloodFill( hdc, squareSize-1, 0, 0, FLOODFILLSURFACE );\r
+    ExtFloodFill( hdc, squareSize-1, squareSize-1, 0, FLOODFILLSURFACE );\r
     SelectObject( hdc, GetStockObject(BLACK_BRUSH) );\r
     /* \r
         Step 4: this is the tricky part, the area inside the piece is filled with black,\r
@@ -2495,14 +2583,30 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
         There should be a better way to do this... if we could create a region or path\r
         from the fill operation we would be fine for example.\r
     */\r
-    FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );\r
+//    FloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF) );\r
+    ExtFloodFill( hdc, squareSize / 2, squareSize / 2, RGB(0xFF,0xFF,0xFF), FLOODFILLBORDER );\r
+\r
+    {   /* [HGM] shave off edges of mask, in an attempt to correct for the fact that FloodFill does not work correctly under Win XP */\r
+        HDC dc2 = CreateCompatibleDC( hdc_window );\r
+        HBITMAP bm2 = CreateCompatibleBitmap( hdc_window, squareSize, squareSize );\r
+\r
+        SelectObject( dc2, bm2 );\r
+        BitBlt( dc2, 0, 0, squareSize, squareSize, hdc, 0, 0, SRCCOPY ); // make copy\r
+        BitBlt( hdc, 0, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
+        BitBlt( hdc, 2, 1, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
+        BitBlt( hdc, 1, 0, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
+        BitBlt( hdc, 1, 2, squareSize-2, squareSize-2, dc2, 1, 1, SRCPAINT );\r
+\r
+        DeleteDC( dc2 );\r
+        DeleteObject( bm2 );\r
+    }\r
 \r
     SetTextColor( hdc, 0 );\r
     /* \r
         Step 5: some fonts have "disconnected" areas that are skipped by the fill:\r
         draw the piece again in black for safety.\r
     */\r
-    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 );\r
+    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
 \r
     SelectObject( hdc, hbm_old );\r
 \r
@@ -2543,7 +2647,7 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
     }\r
 \r
     SetTextColor( hdc, foreColor );\r
-    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[index], 1 );\r
+    TextOut( hdc, pt.x, pt.y, &pieceToFontChar[appData.allWhite && index >= (int)BlackPawn ? index - (int)BlackPawn : index], 1 );\r
 \r
     SelectObject( hdc, hbm_old );\r
 \r
@@ -2581,8 +2685,8 @@ static int TranslatePieceToFontPiece( int piece )
         return PM_WQ;\r
     case WhiteKing:\r
         return PM_WK;\r
-#ifdef FAIRY\r
-    case BlackCardinal:\r
+\r
+    case BlackAngel:\r
         return PM_BA;\r
     case BlackMarshall:\r
         return PM_BC;\r
@@ -2602,7 +2706,20 @@ static int TranslatePieceToFontPiece( int piece )
         return PM_BG;\r
     case BlackMan:\r
         return PM_BM;\r
-    case WhiteCardinal:\r
+    case BlackSilver:\r
+        return PM_BSG;\r
+    case BlackLance:\r
+        return PM_BL;\r
+    case BlackFalcon:\r
+        return PM_BV;\r
+    case BlackCobra:\r
+        return PM_BS;\r
+    case BlackCardinal:\r
+        return PM_BAB;\r
+    case BlackDragon:\r
+        return PM_BD;\r
+\r
+    case WhiteAngel:\r
         return PM_WA;\r
     case WhiteMarshall:\r
         return PM_WC;\r
@@ -2622,7 +2739,18 @@ static int TranslatePieceToFontPiece( int piece )
         return PM_WG;\r
     case WhiteMan:\r
         return PM_WM;\r
-#endif\r
+    case WhiteSilver:\r
+        return PM_WSG;\r
+    case WhiteLance:\r
+        return PM_WL;\r
+    case WhiteFalcon:\r
+        return PM_WV;\r
+    case WhiteCobra:\r
+        return PM_WS;\r
+    case WhiteCardinal:\r
+        return PM_WAB;\r
+    case WhiteDragon:\r
+        return PM_WD;\r
     }\r
 \r
     return 0;\r
@@ -2655,7 +2783,7 @@ void CreatePiecesFromFont()
             DeleteObject( hPieceFont );\r
         }\r
         else {\r
-            for( i=0; i<12; i++ ) {\r
+            for( i=0; i<=(int)BlackKing; i++ ) {\r
                 hPieceMask[i] = NULL;\r
                 hPieceFace[i] = NULL;\r
             }\r
@@ -2692,37 +2820,35 @@ void CreatePiecesFromFont()
         }\r
         else {\r
             /* Setup font-to-piece character table */\r
-            if( ! SetPieceToFontCharTable(appData.fontToPieceTable) ) {\r
+            if( ! SetCharTable(pieceToFontChar, appData.fontToPieceTable) ) {\r
                 /* No (or wrong) global settings, try to detect the font */\r
                 if( strstr(lf.lfFaceName,"Alpha") != NULL ) {\r
                     /* Alpha */\r
-                    SetPieceToFontCharTable("phbrqkojntwl");\r
+                    SetCharTable(pieceToFontChar, "phbrqkojntwl");\r
                 }\r
                 else if( strstr(lf.lfFaceName,"DiagramTT") != NULL ) {\r
                     /* DiagramTT* family */\r
-                    SetPieceToFontCharTable("PNLRQKpnlrqk");\r
+                    SetCharTable(pieceToFontChar, "PNLRQKpnlrqk");\r
                 }\r
-#ifdef FAIRY\r
                 else if( strstr(lf.lfFaceName,"WinboardF") != NULL ) {\r
                     /* Fairy symbols */\r
-                        SetPieceToFontCharTable("PNBRACFHEWUOGMQKpnbracfewuogmqk");\r
+                     SetCharTable(pieceToFontChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk");\r
                 }\r
-#endif\r
                 else if( strstr(lf.lfFaceName,"GC2004D") != NULL ) {\r
                     /* Good Companion (Some characters get warped as literal :-( */\r
                     char s[] = "1cmWG0ñueOS¯®oYI23wgQU";\r
                     s[0]=0xB9; s[1]=0xA9; s[6]=0xB1; s[11]=0xBB; s[12]=0xAB; s[17]=0xB3;\r
-                    SetPieceToFontCharTable(s);\r
+                    SetCharTable(pieceToFontChar, s);\r
                 }\r
                 else {\r
                     /* Cases, Condal, Leipzig, Lucena, Marroquin, Merida, Usual */\r
-                    SetPieceToFontCharTable("pnbrqkomvtwl");\r
+                    SetCharTable(pieceToFontChar, "pnbrqkomvtwl");\r
                 }\r
             }\r
 \r
             /* Create bitmaps */\r
             hfont_old = SelectObject( hdc, hPieceFont );\r
-\r
+#if 0\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_WP );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_WN );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_WB );\r
@@ -2735,7 +2861,7 @@ void CreatePiecesFromFont()
             CreatePieceMaskFromFont( hdc_window, hdc, PM_BR );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_BQ );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_BK );\r
-#ifdef FAIRY\r
+\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_WA );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_WC );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_WF );\r
@@ -2746,6 +2872,12 @@ void CreatePiecesFromFont()
             CreatePieceMaskFromFont( hdc_window, hdc, PM_WO );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_WG );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_WM );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_WSG );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_WV );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_WAB );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_WD );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_WL );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_WS );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_BA );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_BC );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_BF );\r
@@ -2756,8 +2888,17 @@ void CreatePiecesFromFont()
             CreatePieceMaskFromFont( hdc_window, hdc, PM_BO );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_BG );\r
             CreatePieceMaskFromFont( hdc_window, hdc, PM_BM );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_BSG );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_BV );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_BAB );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_BD );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_BL );\r
+            CreatePieceMaskFromFont( hdc_window, hdc, PM_BS );\r
+#else\r
+           for(i=(int)WhitePawn; i<(int)EmptySquare; i++) /* [HGM] made a loop for this */\r
+               if(PieceToChar((ChessSquare)i) != '.')     /* skip unused pieces         */\r
+                   CreatePieceMaskFromFont( hdc_window, hdc, i );\r
 #endif\r
-\r
             SelectObject( hdc, hfont_old );\r
 \r
             fontBitmapSquareSize = squareSize;\r
@@ -2875,9 +3016,10 @@ ResizeBoard(int newSizeX, int newSizeY, int flags)
   if (IsIconic(hwndMain)) return;\r
   if (recurse > 0) return;\r
   recurse++;\r
-  while (newSize > 0 &&\r
-        (newSizeX < sizeInfo[newSize].cliWidth ||\r
-         newSizeY < sizeInfo[newSize].cliHeight)) {\r
+  while (newSize > 0) {\r
+       InitDrawingSizes(newSize, 0);\r
+       if(newSizeX >= sizeInfo[newSize].cliWidth ||\r
+          newSizeY >= sizeInfo[newSize].cliHeight) break;\r
     newSize--;\r
   } \r
   boardSize = newSize;\r
@@ -2904,12 +3046,13 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   LOGBRUSH logbrush;\r
 \r
   /* [HGM] call with -1 uses old size (for if nr of files, ranks changes) */\r
-  if(boardSize == (BoardSize)(-1) ) boardSize = oldBoardSize;\r
+  if(boardSize == (BoardSize)(-2) ) boardSize = oldBoardSize;\r
 \r
   tinyLayout = sizeInfo[boardSize].tinyLayout;\r
   smallLayout = sizeInfo[boardSize].smallLayout;\r
   squareSize = sizeInfo[boardSize].squareSize;\r
   lineGap = sizeInfo[boardSize].lineGap;\r
+  minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted  */\r
 \r
   if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {\r
       lineGap = appData.overrideLineGap;\r
@@ -2953,27 +3096,52 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   ReleaseDC(hwndMain, hdc);\r
 \r
   /* Compute where everything goes */\r
-  whiteRect.left = OUTER_MARGIN;\r
-  whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;\r
-  whiteRect.top = OUTER_MARGIN;\r
-  whiteRect.bottom = whiteRect.top + clockSize.cy;\r
+  if(first.programLogo || second.programLogo) {\r
+        /* [HGM] logo: if either logo is on, reserve space for it */\r
+       logoHeight =  2*clockSize.cy;\r
+       leftLogoRect.left   = OUTER_MARGIN;\r
+       leftLogoRect.right  = leftLogoRect.left + 4*clockSize.cy;\r
+       leftLogoRect.top    = OUTER_MARGIN;\r
+       leftLogoRect.bottom = OUTER_MARGIN + logoHeight;\r
+\r
+       rightLogoRect.right  = OUTER_MARGIN + boardWidth;\r
+       rightLogoRect.left   = rightLogoRect.right - 4*clockSize.cy;\r
+       rightLogoRect.top    = OUTER_MARGIN;\r
+       rightLogoRect.bottom = OUTER_MARGIN + logoHeight;\r
+\r
+\r
+    blackRect.left = leftLogoRect.right;\r
+    blackRect.right = rightLogoRect.left;\r
+    blackRect.top = OUTER_MARGIN;\r
+    blackRect.bottom = blackRect.top + clockSize.cy;\r
+\r
+    whiteRect.left = blackRect.left ;\r
+    whiteRect.right = blackRect.right;\r
+    whiteRect.top = blackRect.bottom;\r
+    whiteRect.bottom = leftLogoRect.bottom;\r
+  } else {\r
+    whiteRect.left = OUTER_MARGIN;\r
+    whiteRect.right = whiteRect.left + boardWidth/2 - INNER_MARGIN/2;\r
+    whiteRect.top = OUTER_MARGIN + logoHeight;\r
+    whiteRect.bottom = whiteRect.top + clockSize.cy;\r
 \r
-  blackRect.left = whiteRect.right + INNER_MARGIN;\r
-  blackRect.right = blackRect.left + boardWidth/2 - 1;\r
-  blackRect.top = whiteRect.top;\r
-  blackRect.bottom = whiteRect.bottom;\r
+    blackRect.left = whiteRect.right + INNER_MARGIN;\r
+    blackRect.right = blackRect.left + boardWidth/2 - 1;\r
+    blackRect.top = whiteRect.top;\r
+    blackRect.bottom = whiteRect.bottom;\r
+  }\r
 \r
-  messageRect.left = whiteRect.left + MESSAGE_LINE_LEFTMARGIN;\r
+  messageRect.left = OUTER_MARGIN + MESSAGE_LINE_LEFTMARGIN;\r
   if (appData.showButtonBar) {\r
-    messageRect.right = blackRect.right\r
+    messageRect.right = OUTER_MARGIN + boardWidth         // [HGM] logo: expressed independent of clock placement\r
       - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;\r
   } else {\r
-    messageRect.right = blackRect.right;\r
+    messageRect.right = OUTER_MARGIN + boardWidth;\r
   }\r
   messageRect.top = whiteRect.bottom + INNER_MARGIN;\r
   messageRect.bottom = messageRect.top + messageSize.cy;\r
 \r
-  boardRect.left = whiteRect.left;\r
+  boardRect.left = OUTER_MARGIN;\r
   boardRect.right = boardRect.left + boardWidth;\r
   boardRect.top = messageRect.bottom + INNER_MARGIN;\r
   boardRect.bottom = boardRect.top + boardHeight;\r
@@ -3085,7 +3253,17 @@ InitDrawingSizes(BoardSize boardSize, int flags)
     }\r
   }\r
 \r
-  if (boardSize == oldBoardSize) return;\r
+  /* [HGM] Licensing requirement */\r
+#ifdef GOTHIC\r
+  if(gameInfo.variant == VariantGothic) GothicPopUp( GOTHIC, VariantGothic); else\r
+#endif\r
+#ifdef FALCON\r
+  if(gameInfo.variant == VariantFalcon) GothicPopUp( FALCON, VariantFalcon); else\r
+#endif\r
+  GothicPopUp( "", VariantNormal);\r
+\r
+\r
+/*  if (boardSize == oldBoardSize) return; [HGM] variant might have changed */\r
   oldBoardSize = boardSize;\r
   oldTinyLayout = tinyLayout;\r
 \r
@@ -3099,88 +3277,198 @@ InitDrawingSizes(BoardSize boardSize, int flags)
     }\r
   }\r
 \r
+  fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */\r
+  // Orthodox Chess pieces\r
   pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");\r
   pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");\r
   pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");\r
   pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");\r
-  pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");\r
   pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");\r
   pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");\r
   pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");\r
   pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");\r
   pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");\r
-  pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");\r
   pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");\r
   pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");\r
   pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");\r
   pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");\r
   pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");\r
-  pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");\r
   pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");\r
-#ifdef FAIRY\r
-  if(squareSize==72 || squareSize==49) { /* experiment with some home-made bitmaps */\r
-  pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");\r
-  pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");\r
-  pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");\r
-  pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");\r
-  pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");\r
-  pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  if(!strcmp(appData.variant, "shogi")) { /* promoted Gold represemtations */\r
-  pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "wp", squareSize, "s");\r
-  pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "wp", squareSize, "o");\r
-  pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");\r
-  pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");\r
-  pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wl", squareSize, "s");\r
-  pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wl", squareSize, "o");\r
-  pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "ws", squareSize, "s");\r
-  pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "ws", squareSize, "o");\r
-  pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
-  } else {\r
-  pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");\r
-  pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");\r
-  pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");\r
-  pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");\r
-  pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");\r
-  pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");\r
-  pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");\r
-  pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");\r
-  pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");\r
-  pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");\r
-  pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");\r
-  pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");\r
-  pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");\r
-  pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");\r
-  pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");\r
-  }\r
-  pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");\r
-  pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");\r
-  pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");\r
-  pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");\r
-  pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");\r
-  pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");\r
-  if(strcmp(appData.variant, "crazyhouse") && strcmp(appData.variant, "shogi")) {\r
-  pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");\r
-  pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");\r
-  pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");\r
+  if( !strcmp(appData.variant, "shogi") && (squareSize==72 || squareSize==49)) {\r
+    // in Shogi, Hijack the unused Queen for Lance\r
+    pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
+    pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
+    pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
   } else {\r
-  pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "s");\r
-  pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "o");\r
-  pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "dk", squareSize, "w");\r
-  }\r
-  if(!strcmp(appData.variant, "xiangqi") || !strcmp(appData.variant, "shogi")) {\r
-      for(i=0; i<2; i++)\r
-      if (pieceBitmap[i][WhiteQueen] != NULL)\r
-        DeleteObject(pieceBitmap[i][WhiteQueen]);\r
-  pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "o", squareSize, "s");\r
-  pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "o", squareSize, "o");\r
-  pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "o", squareSize, "w");\r
-  }\r
+    pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");\r
+    pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");\r
+    pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");\r
+  }\r
+\r
+  if(squareSize <= 72 && squareSize >= 33) { \r
+    /* A & C are available in most sizes now */\r
+    if(squareSize != 49 && squareSize != 72 && squareSize != 33) { // Vortex-like\r
+      pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "s");\r
+      pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "o");\r
+      pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "a", squareSize, "w");\r
+      pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
+      pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
+      pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
+      pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
+      pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
+      pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
+      pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
+      pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
+      pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
+    } else { // Smirf-like\r
+      pieceBitmap[0][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "s");\r
+      pieceBitmap[1][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "o");\r
+      pieceBitmap[2][WhiteAngel] = DoLoadBitmap(hInst, "aa", squareSize, "w");\r
+    }\r
+    if(gameInfo.variant == VariantGothic) { // Vortex-like\r
+      pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
+      pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
+      pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
+    } else { // WinBoard standard\r
+      pieceBitmap[0][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "s");\r
+      pieceBitmap[1][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "o");\r
+      pieceBitmap[2][WhiteMarshall] = DoLoadBitmap(hInst, "c", squareSize, "w");\r
+    }\r
+  }\r
+\r
+\r
+  if(squareSize==72 || squareSize==49 || squareSize==33) { /* experiment with some home-made bitmaps */\r
+    pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "s");\r
+    pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "o");\r
+    pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "f", squareSize, "w");\r
+    pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "s");\r
+    pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "o");\r
+    pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+    pieceBitmap[0][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "s");\r
+    pieceBitmap[1][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "o");\r
+    pieceBitmap[2][WhiteAlfil] = DoLoadBitmap(hInst, "e", squareSize, "w");\r
+    pieceBitmap[0][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "s");\r
+    pieceBitmap[1][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "o");\r
+    pieceBitmap[2][WhiteMan] = DoLoadBitmap(hInst, "m", squareSize, "w");\r
+    pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "s");\r
+    pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "o");\r
+    pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "a", squareSize, "w");\r
+    pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "s");\r
+    pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "o");\r
+    pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "dk", squareSize, "w");\r
+    pieceBitmap[0][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "s");\r
+    pieceBitmap[1][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "o");\r
+    pieceBitmap[2][WhiteFalcon] = DoLoadBitmap(hInst, "v", squareSize, "w");\r
+    pieceBitmap[0][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "s");\r
+    pieceBitmap[1][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "o");\r
+    pieceBitmap[2][WhiteCobra] = DoLoadBitmap(hInst, "s", squareSize, "w");\r
+    pieceBitmap[0][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
+    pieceBitmap[1][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
+    pieceBitmap[2][WhiteLance] = DoLoadBitmap(hInst, "l", squareSize, "w");\r
+    pieceBitmap[0][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "s");\r
+    pieceBitmap[1][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "o");\r
+    pieceBitmap[2][WhiteUnicorn] = DoLoadBitmap(hInst, "u", squareSize, "w");\r
+\r
+    if(gameInfo.variant == VariantShogi) { /* promoted Gold represemtations */\r
+      pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");\r
+      pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "o");\r
+      pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+      pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "s");\r
+      pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "wn", squareSize, "o");\r
+      pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+      pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "s");\r
+      pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ws", squareSize, "o");\r
+      pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+      pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "s");\r
+      pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "wl", squareSize, "o");\r
+      pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "w", squareSize, "w");\r
+    } else {\r
+      pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "s");\r
+      pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "o");\r
+      pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "o", squareSize, "w");\r
+      pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "s");\r
+      pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "o");\r
+      pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "h", squareSize, "w");\r
+      pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "s");\r
+      pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "o");\r
+      pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "cv", squareSize, "w");\r
+      pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "s");\r
+      pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "o");\r
+      pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "g", squareSize, "w");\r
+    }\r
+\r
+  } else { /* other size, no special bitmaps available. Use smaller symbols */\r
+    if((int)boardSize < 2) minorSize = sizeInfo[0].squareSize;\r
+    else  minorSize = sizeInfo[(int)boardSize - 2].squareSize;\r
+    pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "s");\r
+    pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "o");\r
+    pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "n", minorSize, "w");\r
+    pieceBitmap[0][WhiteCardinal]   = DoLoadBitmap(hInst, "b", minorSize, "s");\r
+    pieceBitmap[1][WhiteCardinal]   = DoLoadBitmap(hInst, "b", minorSize, "o");\r
+    pieceBitmap[2][WhiteCardinal]   = DoLoadBitmap(hInst, "b", minorSize, "w");\r
+    pieceBitmap[0][WhiteDragon]   = DoLoadBitmap(hInst, "r", minorSize, "s");\r
+    pieceBitmap[1][WhiteDragon]   = DoLoadBitmap(hInst, "r", minorSize, "o");\r
+    pieceBitmap[2][WhiteDragon]   = DoLoadBitmap(hInst, "r", minorSize, "w");\r
+    pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "s");\r
+    pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "o");\r
+    pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "q", minorSize, "w");\r
+  }\r
+\r
+\r
+  if(gameInfo.variant == VariantShogi && squareSize == 58)\r
+  /* special Shogi support in this size */\r
+  { for (i=0; i<=2; i++) { /* replace all bitmaps */\r
+      for (piece = WhitePawn;\r
+           (int) piece < (int) BlackPawn;\r
+           piece = (ChessSquare) ((int) piece + 1)) {\r
+        if (pieceBitmap[i][piece] != NULL)\r
+          DeleteObject(pieceBitmap[i][piece]);\r
+      }\r
+    }\r
+  pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");\r
+  pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");\r
+  pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");\r
+  pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");\r
+  pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");\r
+  pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");\r
+  pieceBitmap[0][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");\r
+  pieceBitmap[0][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");\r
+  pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");\r
+  pieceBitmap[0][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");\r
+  pieceBitmap[0][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");\r
+  pieceBitmap[0][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");\r
+  pieceBitmap[0][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");\r
+  pieceBitmap[0][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");\r
+  pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "o");\r
+  pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "o");\r
+  pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "sb", squareSize, "o");\r
+  pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "o");\r
+  pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "o");\r
+  pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "o");\r
+  pieceBitmap[1][WhiteFerz] = DoLoadBitmap(hInst, "sf", squareSize, "o");\r
+  pieceBitmap[1][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "o");\r
+  pieceBitmap[1][WhiteCannon] = DoLoadBitmap(hInst, "su", squareSize, "o");\r
+  pieceBitmap[1][WhiteNightrider] = DoLoadBitmap(hInst, "sh", squareSize, "o");\r
+  pieceBitmap[1][WhiteCardinal] = DoLoadBitmap(hInst, "sa", squareSize, "o");\r
+  pieceBitmap[1][WhiteDragon] = DoLoadBitmap(hInst, "sc", squareSize, "o");\r
+  pieceBitmap[1][WhiteGrasshopper] = DoLoadBitmap(hInst, "sg", squareSize, "o");\r
+  pieceBitmap[1][WhiteSilver] = DoLoadBitmap(hInst, "ss", squareSize, "o");\r
+  pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "sp", squareSize, "w");\r
+  pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "sn", squareSize, "w");\r
+  pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
+  pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
+  pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "sl", squareSize, "w");\r
+  pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "sk", squareSize, "w");\r
+  pieceBitmap[2][WhiteFerz] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
+  pieceBitmap[2][WhiteWazir] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
+  pieceBitmap[2][WhiteCannon] = DoLoadBitmap(hInst, "sp", squareSize, "w");\r
+  pieceBitmap[2][WhiteNightrider] = DoLoadBitmap(hInst, "sn", squareSize, "w");\r
+  pieceBitmap[2][WhiteCardinal] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
+  pieceBitmap[2][WhiteDragon] = DoLoadBitmap(hInst, "sr", squareSize, "w");\r
+  pieceBitmap[2][WhiteGrasshopper] = DoLoadBitmap(hInst, "sl", squareSize, "w");\r
+  pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
+  minorSize = 0;\r
   }\r
-#endif\r
-\r
 }\r
 \r
 HBITMAP\r
@@ -3234,7 +3522,7 @@ DrawCoordsOnDC(HDC hdc)
   oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf);\r
 \r
   y = boardRect.top + lineGap;\r
-  x = boardRect.left + lineGap;\r
+  x = boardRect.left + lineGap + gameInfo.holdingsWidth*(squareSize + lineGap);\r
 \r
   SetTextAlign(hdc, TA_LEFT|TA_TOP);\r
   for (i = 0; i < BOARD_HEIGHT; i++) {\r
@@ -3243,10 +3531,10 @@ DrawCoordsOnDC(HDC hdc)
     y += squareSize + lineGap;\r
   }\r
 \r
-  start = flipView ? 12-BOARD_WIDTH : 12;\r
+  start = flipView ? 12-(BOARD_RGHT-BOARD_LEFT) : 12;\r
 \r
   SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);\r
-  for (i = 0; i < BOARD_WIDTH; i++) {\r
+  for (i = 0; i < BOARD_RGHT - BOARD_LEFT; i++) {\r
     str[0] = ranks[start + i];\r
     ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL);\r
     x += squareSize + lineGap;\r
@@ -3329,6 +3617,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
 {\r
   HBITMAP oldBitmap;\r
   HBRUSH oldBrush;\r
+  int tmpSize;\r
 \r
   if (appData.blindfold) return;\r
 \r
@@ -3338,7 +3627,7 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
     CreatePiecesFromFont();\r
 \r
     if( fontBitmapSquareSize == squareSize ) {\r
-        int index = TranslatePieceToFontPiece( piece );\r
+        int index = TranslatePieceToFontPiece(piece);\r
 \r
         SelectObject( tmphdc, hPieceMask[ index ] );\r
 \r
@@ -3368,21 +3657,39 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
     BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0,\r
           sqcolor ? SRCCOPY : NOTSRCCOPY);\r
   } else {\r
-    if (color) {\r
+    tmpSize = squareSize;\r
+    if(minorSize &&\r
+        (piece >= (int)WhiteNightrider && piece <= WhiteGrasshopper ||\r
+         piece >= (int)BlackNightrider && piece <= BlackGrasshopper)  ) {\r
+      /* [HGM] no bitmap available for promoted pieces in Crazyhouse        */\r
+      /* Bitmaps of smaller size are substituted, but we have to align them */\r
+      x += (squareSize - minorSize)>>1;\r
+      y += squareSize - minorSize - 2;\r
+      tmpSize = minorSize;\r
+    }\r
+    if (color || appData.allWhite ) {\r
       oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE));\r
-      oldBrush = SelectObject(hdc, whitePieceBrush);\r
-      BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
+      if( color )\r
+              oldBrush = SelectObject(hdc, whitePieceBrush);\r
+      else    oldBrush = SelectObject(hdc, blackPieceBrush);\r
+      if(appData.upsideDown && color==flipView)\r
+        StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
+      else\r
+        BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
 #if 0\r
       /* Use black piece color for outline of white pieces */\r
       /* Not sure this looks really good (though xboard does it).\r
         Maybe better to have another selectable color, default black */\r
       SelectObject(hdc, blackPieceBrush); /* could have own brush */\r
       SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));\r
-      BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
+      BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
 #else\r
       /* Use black for outline of white pieces */\r
       SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));\r
-      BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, SRCAND);\r
+      if(appData.upsideDown && color==flipView)\r
+        StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, SRCAND);\r
+      else\r
+        BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, SRCAND);\r
 #endif\r
     } else {\r
 #if 0\r
@@ -3393,15 +3700,18 @@ DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y,
         Maybe better to have another selectable color, default medium gray? */\r
       oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, BLACK_PIECE));\r
       oldBrush = SelectObject(hdc, whitePieceBrush); /* could have own brush */\r
-      BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
+      BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
       SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
       SelectObject(hdc, blackPieceBrush);\r
-      BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
+      BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
 #else\r
       /* Use square color for details of black pieces */\r
       oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
       oldBrush = SelectObject(hdc, blackPieceBrush);\r
-      BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
+      if(appData.upsideDown && !flipView)\r
+        StretchBlt(hdc, x+tmpSize, y+tmpSize, -tmpSize, -tmpSize, tmphdc, 0, 0, tmpSize, tmpSize, 0x00B8074A);\r
+      else\r
+        BitBlt(hdc, x, y, tmpSize, tmpSize, tmphdc, 0, 0, 0x00B8074A);\r
 #endif\r
     }\r
     SelectObject(hdc, oldBrush);\r
@@ -3462,16 +3772,16 @@ VOID RebuildTextureSquareInfo()
             if( (col + row) & 1 ) {\r
                 /* Lite square */\r
                 if( lite_w >= squareSize && lite_h >= squareSize ) {\r
-                    backTextureSquareInfo[row][col].x = col * (lite_w - squareSize) / BOARD_WIDTH;\r
-                    backTextureSquareInfo[row][col].y = row * (lite_h - squareSize) / BOARD_HEIGHT;\r
+                    backTextureSquareInfo[row][col].x = col * (lite_w - squareSize) / (BOARD_WIDTH-1);  /* [HGM] divide by size-1 in stead of size! */\r
+                    backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (lite_h - squareSize) / (BOARD_HEIGHT-1);\r
                     backTextureSquareInfo[row][col].mode = GetBackTextureMode(liteBackTextureMode);\r
                 }\r
             }\r
             else {\r
                 /* Dark square */\r
                 if( dark_w >= squareSize && dark_h >= squareSize ) {\r
-                    backTextureSquareInfo[row][col].x = col * (dark_w - squareSize) / BOARD_WIDTH;\r
-                    backTextureSquareInfo[row][col].y = row * (dark_h - squareSize) / BOARD_HEIGHT;\r
+                    backTextureSquareInfo[row][col].x = col * (dark_w - squareSize) / (BOARD_WIDTH-1);\r
+                    backTextureSquareInfo[row][col].y = (BOARD_HEIGHT-1-row) * (dark_h - squareSize) / (BOARD_HEIGHT-1);\r
                     backTextureSquareInfo[row][col].mode = GetBackTextureMode(darkBackTextureMode);\r
                 }\r
             }\r
@@ -3778,7 +4088,10 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
 \r
   /* [AS] Initialize background textures if needed */\r
   if( liteBackTexture != NULL || darkBackTexture != NULL ) {\r
-      if( backTextureSquareSize != squareSize ) {\r
+      static int backTextureBoardSize; /* [HGM] boardsize: also new texture if board format changed */\r
+      if( backTextureSquareSize != squareSize \r
+       || backTextureBoardSize != BOARD_WIDTH+BOARD_SIZE*BOARD_HEIGHT) {\r
+         backTextureBoardSize = BOARD_WIDTH+BOARD_SIZE*BOARD_HEIGHT;\r
           backTextureSquareSize = squareSize;\r
           RebuildTextureSquareInfo();\r
       }\r
@@ -3794,7 +4107,7 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
       piece = board[row][column];\r
 \r
       square_color = ((column + row) % 2) == 1;\r
-      if(!strcmp(appData.variant, "xiangqi") ) {\r
+      if( gameInfo.variant == VariantXiangqi ) {\r
           square_color = !InPalace(row, column);\r
           if(BOARD_HEIGHT&1) { if(row==BOARD_HEIGHT/2) square_color ^= 1; }\r
           else if(row < BOARD_HEIGHT/2) square_color ^= 1;\r
@@ -3802,7 +4115,6 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
       piece_color = (int) piece < (int) BlackPawn;\r
 \r
 \r
-#ifdef FAIRY\r
       /* [HGM] holdings file: light square or black */\r
       if(column == BOARD_LEFT-2) {\r
             if( row > BOARD_HEIGHT - gameInfo.holdingsSize - 1 )\r
@@ -3821,11 +4133,10 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
             }\r
       }\r
       if(column == BOARD_LEFT-1 ) /* left align */\r
-            DisplayHoldingsCount(hdc, x, y, 0, (int) board[row][column]);\r
+            DisplayHoldingsCount(hdc, x, y, flipView, (int) board[row][column]);\r
       else if( column == BOARD_RGHT) /* right align */\r
-            DisplayHoldingsCount(hdc, x, y, 1, (int) board[row][column]);\r
+            DisplayHoldingsCount(hdc, x, y, !flipView, (int) board[row][column]);\r
       else\r
-#endif\r
       if (appData.monoMode) {\r
         if (piece == EmptySquare) {\r
           BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0,\r
@@ -3837,14 +4148,16 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
       else if( backTextureSquareInfo[row][column].mode > 0 ) {\r
           /* [AS] Draw the square using a texture bitmap */\r
           HBITMAP hbm = SelectObject( texture_hdc, square_color ? liteBackTexture : darkBackTexture );\r
+         int r = row, c = column; // [HGM] do not flip board in flipView\r
+         if(flipView) { r = BOARD_HEIGHT-1 - r; c = BOARD_WIDTH-1 - c; }\r
 \r
           DrawTile( x, y, \r
               squareSize, squareSize, \r
               hdc, \r
               texture_hdc,\r
-              backTextureSquareInfo[row][column].mode,\r
-              backTextureSquareInfo[row][column].x,\r
-              backTextureSquareInfo[row][column].y );\r
+              backTextureSquareInfo[r][c].mode,\r
+              backTextureSquareInfo[r][c].x,\r
+              backTextureSquareInfo[r][c].y );\r
 \r
           SelectObject( texture_hdc, hbm );\r
 \r
@@ -3869,9 +4182,44 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
   }\r
 }\r
 \r
+int saveDiagFlag = 0; FILE *diagFile; // [HGM] diag\r
+void fputDW(FILE *f, int x)\r
+{\r
+       fputc(x     & 255, f);\r
+       fputc(x>>8  & 255, f);\r
+       fputc(x>>16 & 255, f);\r
+       fputc(x>>24 & 255, f);\r
+}\r
+\r
 #define MAX_CLIPS 200   /* more than enough */\r
 \r
 VOID\r
+DrawLogoOnDC(HDC hdc, RECT logoRect, ChessProgramState *cps)\r
+{\r
+  HBITMAP bufferBitmap;\r
+  BITMAP bi;\r
+  RECT Rect;\r
+  HDC tmphdc;\r
+  HBITMAP hbm;\r
+  int w = 100, h = 50;\r
+\r
+  if(cps->programLogo == NULL) return;\r
+//  GetClientRect(hwndMain, &Rect);\r
+//  bufferBitmap = CreateCompatibleBitmap(hdc, Rect.right-Rect.left+1,\r
+//                                     Rect.bottom-Rect.top+1);\r
+  tmphdc = CreateCompatibleDC(hdc);\r
+  hbm = SelectObject(tmphdc, (HBITMAP) cps->programLogo);\r
+  if( GetObject( cps->programLogo, sizeof(bi), &bi ) > 0 ) {\r
+            w = bi.bmWidth;\r
+            h = bi.bmHeight;\r
+  }\r
+  StretchBlt(hdc, logoRect.left, logoRect.top, logoRect.right - logoRect.left, \r
+                  logoRect.bottom - logoRect.top, tmphdc, 0, 0, w, h, SRCCOPY);\r
+  SelectObject(tmphdc, hbm);\r
+  DeleteDC(tmphdc);\r
+}\r
+\r
+VOID\r
 HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)\r
 {\r
   static Board lastReq, lastDrawn;\r
@@ -4125,6 +4473,11 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
   DrawHighlightsOnDC(hdcmem);\r
   DrawBoardOnDC(hdcmem, board, tmphdc);\r
 \r
+  if(logoHeight) {\r
+       DrawLogoOnDC(hdc, leftLogoRect, flipClock ? &second : &first);\r
+       DrawLogoOnDC(hdc, rightLogoRect, flipClock ? &first : &second);\r
+  }\r
+\r
   if( appData.highlightMoveWithArrow ) {\r
     DrawArrowHighlight(hdcmem);\r
   }\r
@@ -4183,6 +4536,80 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
         boardRect.right - boardRect.left,\r
         boardRect.bottom - boardRect.top,\r
         tmphdc, boardRect.left, boardRect.top, SRCCOPY);\r
+  if(saveDiagFlag) { \r
+    BITMAP b; int i, j, m, w, wb, fac=0; char pData[1000000]; \r
+    BITMAPINFOHEADER bih; int color[16], nrColors=0;\r
+\r
+    GetObject(bufferBitmap, sizeof(b), &b);\r
+    if(b.bmWidthBytes*b.bmHeight <= 990000) {\r
+       bih.biSize = sizeof(BITMAPINFOHEADER);\r
+       bih.biWidth = b.bmWidth;\r
+       bih.biHeight = b.bmHeight;\r
+       bih.biPlanes = 1;\r
+       bih.biBitCount = b.bmBitsPixel;\r
+       bih.biCompression = 0;\r
+       bih.biSizeImage = b.bmWidthBytes*b.bmHeight;\r
+       bih.biXPelsPerMeter = 0;\r
+       bih.biYPelsPerMeter = 0;\r
+       bih.biClrUsed = 0;\r
+       bih.biClrImportant = 0;\r
+//     fprintf(diagFile, "t=%d\nw=%d\nh=%d\nB=%d\nP=%d\nX=%d\n", \r
+//             b.bmType,  b.bmWidth,  b.bmHeight, b.bmWidthBytes,  b.bmPlanes,  b.bmBitsPixel);\r
+       GetDIBits(tmphdc,bufferBitmap,0,b.bmHeight,pData,(BITMAPINFO*)&bih,DIB_RGB_COLORS);\r
+//     fprintf(diagFile, "%8x\n", (int) pData);\r
+\r
+#if 1\r
+       wb = b.bmWidthBytes;\r
+       // count colors\r
+       for(i=0; i<wb*(b.bmHeight - boardRect.top + OUTER_MARGIN)>>2; i++) {\r
+               int k = ((int*) pData)[i];\r
+               for(j=0; j<nrColors; j++) if(color[j] == k) break;\r
+               if(j >= 16) break;\r
+               color[j] = k;\r
+               if(j >= nrColors) nrColors = j+1;\r
+       }\r
+       if(j<16) { // 16 colors is enough. Compress to 4 bits per pixel\r
+               INT p = 0;\r
+               for(i=0; i<b.bmHeight - boardRect.top + OUTER_MARGIN; i++) {\r
+                   for(w=0; w<(wb>>2); w+=2) {\r
+                       int k = ((int*) pData)[(wb*i>>2) + w];\r
+                       for(j=0; j<nrColors; j++) if(color[j] == k) break;\r
+                       k = ((int*) pData)[(wb*i>>2) + w + 1];\r
+                       for(m=0; m<nrColors; m++) if(color[m] == k) break;\r
+                       pData[p++] = m | j<<4;\r
+                   }\r
+                   while(p&3) pData[p++] = 0;\r
+               }\r
+               fac = 3;\r
+               wb = (wb+31>>5)<<2;\r
+       }\r
+       // write BITMAPFILEHEADER\r
+       fprintf(diagFile, "BM");\r
+        fputDW(diagFile, wb*(b.bmHeight - boardRect.top + OUTER_MARGIN)+0x36 + (fac?64:0));\r
+        fputDW(diagFile, 0);\r
+        fputDW(diagFile, 0x36 + (fac?64:0));\r
+       // write BITMAPINFOHEADER\r
+        fputDW(diagFile, 40);\r
+        fputDW(diagFile, b.bmWidth);\r
+        fputDW(diagFile, b.bmHeight - boardRect.top + OUTER_MARGIN);\r
+       if(fac) fputDW(diagFile, 0x040001);   // planes and bits/pixel\r
+        else    fputDW(diagFile, 0x200001);   // planes and bits/pixel\r
+        fputDW(diagFile, 0);\r
+        fputDW(diagFile, 0);\r
+        fputDW(diagFile, 0);\r
+        fputDW(diagFile, 0);\r
+        fputDW(diagFile, 0);\r
+        fputDW(diagFile, 0);\r
+       // write color table\r
+       if(fac)\r
+       for(i=0; i<16; i++) fputDW(diagFile, color[i]);\r
+       // write bitmap data\r
+       for(i=0; i<wb*(b.bmHeight - boardRect.top + OUTER_MARGIN); i++) \r
+               fputc(pData[i], diagFile);\r
+#endif\r
+     }\r
+  }\r
+\r
   SelectObject(tmphdc, oldBitmap);\r
 \r
   /* Massive cleanup */\r
@@ -4209,6 +4636,25 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
   lastDrawnValid = 1;\r
 }\r
 \r
+/* [HGM] diag: Save the current board display to the given open file and close the file */\r
+int\r
+SaveDiagram(f)\r
+     FILE *f;\r
+{\r
+    time_t tm;\r
+    char *fen;\r
+\r
+    saveDiagFlag = 1; diagFile = f;\r
+    HDCDrawPosition(NULL, TRUE, NULL);\r
+\r
+    saveDiagFlag = 0;\r
+\r
+//    if(f != NULL) fprintf(f, "Sorry, but this feature is still in preparation\n");\r
+    \r
+    fclose(f);\r
+    return TRUE;\r
+}\r
+\r
 \r
 /*---------------------------------------------------------------------------*\\r
 | CLIENT PAINT PROCEDURE\r
@@ -4318,7 +4764,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   BOOLEAN needsRedraw = FALSE;\r
   BOOLEAN saveAnimate;\r
   BOOLEAN forceFullRepaint = IsFullRepaintPreferrable(); /* [AS] */\r
-  static BOOLEAN sameAgain = FALSE;\r
+  static BOOLEAN sameAgain = FALSE, promotionChoice = FALSE;\r
   ChessMove moveType;\r
 \r
   if (recursive) {\r
@@ -4346,23 +4792,46 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
   switch (message) {\r
   case WM_LBUTTONDOWN:\r
+    if(promotionChoice) { // we are waiting for a click to indicate promotion piece\r
+       promotionChoice = FALSE; // only one chance: if click not OK it is interpreted as cancel\r
+       if(appData.debugMode) fprintf(debugFP, "promotion click, x=%d, y=%d\n", x, y);\r
+       if(gameInfo.holdingsWidth && \r
+               (WhiteOnMove(currentMove) \r
+                       ? x == BOARD_WIDTH-1 && y < gameInfo.holdingsSize && y > 0\r
+                       : x == 0 && y >= BOARD_HEIGHT - gameInfo.holdingsSize && y < BOARD_HEIGHT-1) ) {\r
+           // click in right holdings, for determining promotion piece\r
+           ChessSquare p = boards[currentMove][y][x];\r
+           if(appData.debugMode) fprintf(debugFP, "square contains %d\n", (int)p);\r
+           if(p != EmptySquare) {\r
+               FinishMove(WhitePromotionQueen, fromX, fromY, toX, toY, ToLower(PieceToChar(p)));\r
+               fromX = fromY = -1;\r
+               break;\r
+           }\r
+       }\r
+       DrawPosition(FALSE, boards[currentMove]);\r
+       break;\r
+    }\r
     ErrorPopDown();\r
     sameAgain = FALSE;\r
     if (y == -2) {\r
       /* Downclick vertically off board; check if on clock */\r
       if (PtInRect((LPRECT) &whiteRect, pt)) {\r
-       if (gameMode == EditPosition) {\r
+        if (gameMode == EditPosition) {\r
          SetWhiteToPlayEvent();\r
        } else if (gameMode == IcsPlayingBlack ||\r
                   gameMode == MachinePlaysWhite) {\r
          CallFlagEvent();\r
-       }\r
+        } else if (gameMode == EditGame) {\r
+          AdjustClock((logoHeight > 0 ? flipView: flipClock), -1);\r
+        }\r
       } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
        if (gameMode == EditPosition) {\r
          SetBlackToPlayEvent();\r
        } else if (gameMode == IcsPlayingWhite ||\r
                   gameMode == MachinePlaysBlack) {\r
          CallFlagEvent();\r
+        } else if (gameMode == EditGame) {\r
+          AdjustClock(!(logoHeight > 0 ? flipView: flipClock), -1);\r
        }\r
       }\r
       if (!appData.highlightLastMove) {\r
@@ -4378,6 +4847,8 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
               || x == BOARD_LEFT-1 || x == BOARD_RGHT\r
               || x == BOARD_LEFT-2 && y < BOARD_HEIGHT-gameInfo.holdingsSize\r
               || x == BOARD_RGHT+1 && y >= gameInfo.holdingsSize\r
+       /* EditPosition, empty square, or different color piece;\r
+          click-click move is possible */\r
                                ) {\r
       break;\r
     } else if (fromX == x && fromY == y) {\r
@@ -4390,37 +4861,45 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                                                                         ) {\r
       /* Downclick on different square. */\r
       /* [HGM] if on holdings file, should count as new first click ! */\r
-       \r
-      ChessSquare pdown, pup;\r
-      pdown = boards[currentMove][fromY][fromX];\r
-      pup = boards[currentMove][y][x];\r
-      if (gameMode == EditPosition || /* [HGM] max piece > King! */\r
-          !((WhitePawn <= pdown && pdown < BlackPawn &&\r
-             WhitePawn <= pup && pup < BlackPawn) ||\r
-            (BlackPawn <= pdown && pdown < EmptySquare &&\r
-             BlackPawn <= pup && pup < EmptySquare))) {\r
-       /* EditPosition, empty square, or different color piece;\r
-          click-click move is possible */\r
+      { /* [HGM] <sameColor> now always do UserMoveTest(), and check colors there */\r
        toX = x;\r
        toY = y;\r
+        /* [HGM] <popupFix> UserMoveEvent requires two calls now,\r
+           to make sure move is legal before showing promotion popup */\r
         moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR);\r
+       if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */\r
+               fromX = fromY = -1; \r
+               ClearHighlights();\r
+               DrawPosition(FALSE, boards[currentMove]);\r
+               break; \r
+       } else \r
         if(moveType != ImpossibleMove) {\r
-          if (IsPromotion(fromX, fromY, toX, toY)) {\r
-             /* [HGM] <popupFix> UserMoveEvent requires two calls now,\r
-                to make sure move is legal before showing promotion popup */\r
-             if (appData.alwaysPromoteToQueen) {\r
+          /* [HGM] We use PromotionToKnight in Shogi to indicate frorced promotion */\r
+          if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||\r
+             (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&\r
+              appData.alwaysPromoteToQueen) {\r
                   FinishMove(moveType, fromX, fromY, toX, toY, 'q');\r
                   if (!appData.highlightLastMove) {\r
                       ClearHighlights();\r
                       DrawPosition(forceFullRepaint || FALSE, NULL);\r
                   }\r
-             } else {\r
+          } else\r
+          if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {\r
                   SetHighlights(fromX, fromY, toX, toY);\r
                   DrawPosition(forceFullRepaint || FALSE, NULL);\r
                   /* [HGM] <popupFix> Popup calls FinishMove now.\r
                      If promotion to Q is legal, all are legal! */\r
+                 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)\r
+                 { ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];\r
+                   // kludge to temporarily execute move on display, wthout promotng yet\r
+                   promotionChoice = TRUE;\r
+                   boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank\r
+                   boards[currentMove][toY][toX] = p;\r
+                   DrawPosition(FALSE, boards[currentMove]);\r
+                   boards[currentMove][fromY][fromX] = p; // take back, but display stays\r
+                   boards[currentMove][toY][toX] = q;\r
+                 } else\r
                   PromotionPopup(hwnd);\r
-             }\r
           } else {       /* not a promotion */\r
              if (appData.animate || appData.highlightLastMove) {\r
                  SetHighlights(fromX, fromY, toX, toY);\r
@@ -4428,15 +4907,20 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                  ClearHighlights();\r
              }\r
              FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);\r
+            fromX = fromY = -1;\r
              if (appData.animate && !appData.highlightLastMove) {\r
                   ClearHighlights();\r
                   DrawPosition(forceFullRepaint || FALSE, NULL);\r
              }\r
           }\r
+          break;\r
+        }\r
+        if (gotPremove) {\r
+            /* [HGM] it seemed that braces were missing here */\r
+            SetPremoveHighlights(fromX, fromY, toX, toY);\r
+            fromX = fromY = -1;\r
+            break;\r
         }\r
-       if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
-       fromX = fromY = -1;\r
-       break;\r
       }\r
       ClearHighlights();\r
       DrawPosition(forceFullRepaint || FALSE, NULL);\r
@@ -4462,6 +4946,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     ReleaseCapture();\r
     if (fromX == -1) break;\r
     if (x == fromX && y == fromY) {\r
+      dragInfo.from.x = dragInfo.from.y = -1;\r
       /* Upclick on same square */\r
       if (sameAgain) {\r
        /* Clicked same square twice: abort click-click move */\r
@@ -4472,7 +4957,6 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        /* First square clicked: start click-click move */\r
        SetHighlights(fromX, fromY, -1, -1);\r
       }\r
-      dragInfo.from.x = dragInfo.from.y = -1;\r
       DrawPosition(forceFullRepaint || FALSE, NULL);\r
     } else if (dragInfo.from.x < 0 || dragInfo.from.y < 0) {\r
       /* Errant click; ignore */\r
@@ -4488,14 +4972,34 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       saveAnimate = appData.animate; /* sorry, Hawk :) */\r
       appData.animate = appData.animate && !appData.animateDragging;\r
       moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR);\r
+      if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */\r
+               fromX = fromY = -1; \r
+               ClearHighlights();\r
+               DrawPosition(FALSE, boards[currentMove]);\r
+               break; \r
+      } else \r
       if(moveType != ImpossibleMove) {\r
-        if (IsPromotion(fromX, fromY, toX, toY)) {\r
-          if (appData.alwaysPromoteToQueen)\r
-                  FinishMove(moveType, fromX, fromY, toX, toY, 'q');\r
-          else {\r
-            DrawPosition(forceFullRepaint || FALSE, NULL);\r
-            PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */\r
-          }\r
+          /* [HGM] use move type to determine if move is promotion.\r
+             Knight is Shogi kludge for mandatory promotion, Queen means choice */\r
+          if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||\r
+             (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&\r
+              appData.alwaysPromoteToQueen) \r
+               FinishMove(moveType, fromX, fromY, toX, toY, 'q');\r
+          else \r
+          if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {\r
+               DrawPosition(forceFullRepaint || FALSE, NULL);\r
+                 if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)\r
+                 { ChessSquare p = boards[currentMove][fromY][fromX], q = boards[currentMove][toY][toX];\r
+                   // kludge to temporarily execute move on display, wthout promotng yet\r
+                   promotionChoice = TRUE;\r
+                   boards[currentMove][fromY][fromX] = EmptySquare; // move Pawn to 8th rank\r
+                   boards[currentMove][toY][toX] = p;\r
+                   DrawPosition(FALSE, boards[currentMove]);\r
+                   boards[currentMove][fromY][fromX] = p; // take back, but display stays\r
+                   boards[currentMove][toY][toX] = q;\r
+                   break;\r
+                 } else\r
+               PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */\r
         } else FinishMove(moveType, fromX, fromY, toX, toY, NULLCHAR);\r
       }\r
       if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
@@ -4537,6 +5041,17 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     }\r
     break;\r
 \r
+  case WM_MOUSEWHEEL: // [DM]\r
+       /* Mouse Wheel is being rolled forward\r
+        * Play moves forward\r
+        */\r
+       if((short)HIWORD(wParam) > 0 && currentMove < forwardMostMove) ForwardEvent();\r
+       /* Mouse Wheel is being rolled backward\r
+        * Play moves backward\r
+        */\r
+       if((short)HIWORD(wParam) < 0 && currentMove > backwardMostMove) BackwardEvent();\r
+       break;\r
+\r
   case WM_MBUTTONDOWN:\r
   case WM_RBUTTONDOWN:\r
     ErrorPopDown();\r
@@ -4549,6 +5064,14 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     if (appData.highlightDragging) {\r
       ClearHighlights();\r
     }\r
+    if(y == -2) {\r
+      /* [HGM] right mouse button in clock area edit-game mode ups clock */\r
+      if (PtInRect((LPRECT) &whiteRect, pt)) {\r
+          if (gameMode == EditGame) AdjustClock((logoHeight > 0 ? flipView: flipClock), 1);\r
+      } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
+          if (gameMode == EditGame) AdjustClock(!(logoHeight > 0 ? flipView: flipClock), 1);\r
+      }\r
+    }\r
     DrawPosition(TRUE, NULL);\r
 \r
     switch (gameMode) {\r
@@ -4577,7 +5100,10 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
        /* Just have one menu, on the right button.  Windows users don't\r
           think to try the middle one, and sometimes other software steals\r
           it, or it doesn't really exist. */\r
-       MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\r
+        if(gameInfo.variant != VariantShogi)\r
+            MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\r
+        else\r
+            MenuPopup(hwnd, pt, LoadMenu(hInst, "ShogiPieceMenu"), -1);\r
 #endif\r
       }\r
       break;\r
@@ -4676,19 +5202,37 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
     ShowWindow(GetDlgItem(hDlg, PB_King), \r
       (!appData.testLegality || gameInfo.variant == VariantSuicide ||\r
-       gameInfo.variant == VariantGiveaway) ?\r
+       gameInfo.variant == VariantGiveaway || gameInfo.variant == VariantSuper ) ?\r
               SW_SHOW : SW_HIDE);\r
-#ifdef FAIRY\r
-    /* [HGM] Only allow C & A promotions in Capablanca Chess */\r
+    /* [HGM] Only allow C & A promotions if these pieces are defined */\r
     ShowWindow(GetDlgItem(hDlg, PB_Archbishop),\r
-      (gameInfo.variant == VariantCapablanca || \r
-       gameInfo.variant == VariantGothic) ?\r
+       (PieceToChar(WhiteAngel) >= 'A' &&\r
+        PieceToChar(WhiteAngel) != '~' ||\r
+        PieceToChar(BlackAngel) >= 'A' &&\r
+        PieceToChar(BlackAngel) != '~'   ) ?\r
               SW_SHOW : SW_HIDE);\r
     ShowWindow(GetDlgItem(hDlg, PB_Chancellor), \r
-      (gameInfo.variant == VariantCapablanca || \r
-       gameInfo.variant == VariantGothic) ?\r
+       (PieceToChar(WhiteMarshall) >= 'A' &&\r
+        PieceToChar(WhiteMarshall) != '~' ||\r
+        PieceToChar(BlackMarshall) >= 'A' &&\r
+        PieceToChar(BlackMarshall) != '~'   ) ?\r
+              SW_SHOW : SW_HIDE);\r
+    /* [HGM] Hide B & R button in Shogi, use Q as promote, N as defer */\r
+    ShowWindow(GetDlgItem(hDlg, PB_Rook),\r
+       gameInfo.variant != VariantShogi ?\r
+              SW_SHOW : SW_HIDE);\r
+    ShowWindow(GetDlgItem(hDlg, PB_Bishop), \r
+       gameInfo.variant != VariantShogi ?\r
+              SW_SHOW : SW_HIDE);\r
+    ShowWindow(GetDlgItem(hDlg, IDC_Yes), \r
+       gameInfo.variant == VariantShogi ?\r
+              SW_SHOW : SW_HIDE);\r
+    ShowWindow(GetDlgItem(hDlg, IDC_No), \r
+       gameInfo.variant == VariantShogi ?\r
+              SW_SHOW : SW_HIDE);\r
+    ShowWindow(GetDlgItem(hDlg, IDC_Centaur), \r
+       gameInfo.variant == VariantSuper ?\r
               SW_SHOW : SW_HIDE);\r
-#endif\r
     return TRUE;\r
 \r
   case WM_COMMAND: /* message: received a command */\r
@@ -4699,27 +5243,25 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       DrawPosition(FALSE, NULL);\r
       return TRUE;\r
     case PB_King:\r
-      promoChar = 'k';\r
+      promoChar = gameInfo.variant == VariantSuper ? PieceToChar(BlackSilver) : PieceToChar(BlackKing);\r
       break;\r
     case PB_Queen:\r
-      promoChar = 'q';\r
+      promoChar = gameInfo.variant == VariantShogi ? '+' : PieceToChar(BlackQueen);\r
       break;\r
     case PB_Rook:\r
-      promoChar = 'r';\r
+      promoChar = PieceToChar(BlackRook);\r
       break;\r
     case PB_Bishop:\r
-      promoChar = 'b';\r
+      promoChar = PieceToChar(BlackBishop);\r
       break;\r
-#ifdef FAIRY\r
     case PB_Chancellor:\r
-      promoChar = 'c';\r
+      promoChar = PieceToChar(BlackMarshall);\r
       break;\r
     case PB_Archbishop:\r
-      promoChar = 'a';\r
+      promoChar = PieceToChar(BlackAngel);\r
       break;\r
-#endif\r
     case PB_Knight:\r
-      promoChar = 'n';\r
+      promoChar = gameInfo.variant == VariantShogi ? '=' : PieceToChar(BlackKnight);\r
       break;\r
     default:\r
       return FALSE;\r
@@ -4755,7 +5297,8 @@ PromotionPopup(HWND hwnd)
 VOID\r
 ToggleShowThinking()\r
 {\r
-  ShowThinkingEvent(!appData.showThinking);\r
+  appData.showThinking = !appData.showThinking;\r
+  ShowThinkingEvent();\r
 }\r
 \r
 VOID\r
@@ -4764,7 +5307,7 @@ LoadGameDialog(HWND hwnd, char* title)
   UINT number = 0;\r
   FILE *f;\r
   char fileTitle[MSG_SIZ];\r
-  f = OpenFileDialog(hwnd, FALSE, "",\r
+  f = OpenFileDialog(hwnd, "rb", "",\r
                     appData.oldSaveStyle ? "gam" : "pgn",\r
                     GAME_FILT,\r
                     title, &number, fileTitle, NULL);\r
@@ -4843,6 +5386,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   FILE *f;\r
   UINT number;\r
   char fileTitle[MSG_SIZ];\r
+  char buf[MSG_SIZ];\r
   static SnapData sd;\r
 \r
   switch (message) {\r
@@ -4867,6 +5411,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
   case WM_MBUTTONUP:\r
   case WM_RBUTTONUP:\r
   case WM_MOUSEMOVE:\r
+  case WM_MOUSEWHEEL:\r
     MouseEvent(hwnd, message, wParam, lParam);\r
     break;\r
 \r
@@ -4971,7 +5516,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
         Reset(FALSE, TRUE);\r
       }\r
       number = 1;\r
-      f = OpenFileDialog(hwnd, FALSE, "",\r
+      f = OpenFileDialog(hwnd, "rb", "",\r
                         appData.oldSaveStyle ? "pos" : "fen",\r
                         POSITION_FILT,\r
                         "Load Position from File", &number, fileTitle, NULL);\r
@@ -4994,7 +5539,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
     case IDM_SaveGame:\r
       defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn");\r
-      f = OpenFileDialog(hwnd, TRUE, defName,\r
+      f = OpenFileDialog(hwnd, "a", defName,\r
                         appData.oldSaveStyle ? "gam" : "pgn",\r
                         GAME_FILT,\r
                         "Save Game to File", NULL, fileTitle, NULL);\r
@@ -5005,7 +5550,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
     case IDM_SavePosition:\r
       defName = DefaultFileName(appData.oldSaveStyle ? "pos" : "fen");\r
-      f = OpenFileDialog(hwnd, TRUE, defName,\r
+      f = OpenFileDialog(hwnd, "a", defName,\r
                         appData.oldSaveStyle ? "pos" : "fen",\r
                         POSITION_FILT,\r
                         "Save Position to File", NULL, fileTitle, NULL);\r
@@ -5014,6 +5559,17 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       }\r
       break;\r
 \r
+    case IDM_SaveDiagram:\r
+      defName = "diagram";\r
+      f = OpenFileDialog(hwnd, "wb", defName,\r
+                        "bmp",\r
+                        DIAGRAM_FILT,\r
+                        "Save Diagram to File", NULL, fileTitle, NULL);\r
+      if (f != NULL) {\r
+       SaveDiagram(f);\r
+      }\r
+      break;\r
+\r
     case IDM_CopyGame:\r
       CopyGameToClipboard();\r
       break;\r
@@ -5145,10 +5701,34 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
     case IDM_AnalysisMode:\r
       if (!first.analysisSupport) {\r
-        char buf[MSG_SIZ];\r
         sprintf(buf, "%s does not support analysis", first.tidy);\r
         DisplayError(buf, 0);\r
       } else {\r
+        /* [DM] icsEngineAnlyze [HGM] Why is this front-end??? */\r
+        if (appData.icsActive) {\r
+               if (gameMode != IcsObserving) {\r
+                       sprintf(buf, "You are not observing a game");\r
+                       DisplayError(buf, 0);\r
+                       /* secure check */\r
+                       if (appData.icsEngineAnalyze) {\r
+                               if (appData.debugMode) \r
+                                       fprintf(debugFP, "Found unexpected active ICS engine analyze \n");\r
+                               ExitAnalyzeMode();\r
+                               ModeHighlight();\r
+                               break;\r
+                       }\r
+                       break;\r
+               } else {\r
+                       /* if enable, user want disable icsEngineAnalyze */\r
+                       if (appData.icsEngineAnalyze) {\r
+                               ExitAnalyzeMode();\r
+                               ModeHighlight();\r
+                               break;\r
+                       }\r
+                       appData.icsEngineAnalyze = TRUE;\r
+                       if (appData.debugMode) fprintf(debugFP, "ICS engine analyze starting...\n");\r
+               }\r
+        } \r
        if (!appData.showThinking) ToggleShowThinking();\r
        AnalyzeModeEvent();\r
       }\r
@@ -5247,6 +5827,10 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       PopUpMoveDialog('\000');\r
       break;\r
 \r
+    case IDM_TypeInName:\r
+      PopUpNameDialog('\000');\r
+      break;\r
+\r
     case IDM_Backward:\r
       BackwardEvent();\r
       SetFocus(hwndMain);\r
@@ -5288,6 +5872,11 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       DrawPosition(FALSE, NULL);\r
       break;\r
 \r
+    case IDM_FlipClock:\r
+      flipClock = !flipClock;\r
+      DisplayBothClocks();\r
+      break;\r
+\r
     case IDM_GeneralOptions:\r
       GeneralOptionsPopup(hwnd);\r
       DrawPosition(TRUE, NULL);\r
@@ -5437,6 +6026,36 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       fromX = fromY = -1;\r
       break;\r
 \r
+    case EP_WhiteFerz:\r
+      EditPositionMenuEvent(WhiteFerz, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_WhiteWazir:\r
+      EditPositionMenuEvent(WhiteWazir, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_WhiteAlfil:\r
+      EditPositionMenuEvent(WhiteAlfil, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_WhiteCannon:\r
+      EditPositionMenuEvent(WhiteCannon, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_WhiteCardinal:\r
+      EditPositionMenuEvent(WhiteAngel, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_WhiteMarshall:\r
+      EditPositionMenuEvent(WhiteMarshall, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
     case EP_WhiteKing:\r
       EditPositionMenuEvent(WhiteKing, fromX, fromY);\r
       fromX = fromY = -1;\r
@@ -5467,6 +6086,36 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       fromX = fromY = -1;\r
       break;\r
 \r
+    case EP_BlackFerz:\r
+      EditPositionMenuEvent(BlackFerz, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_BlackWazir:\r
+      EditPositionMenuEvent(BlackWazir, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_BlackAlfil:\r
+      EditPositionMenuEvent(BlackAlfil, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_BlackCannon:\r
+      EditPositionMenuEvent(BlackCannon, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_BlackCardinal:\r
+      EditPositionMenuEvent(BlackAngel, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_BlackMarshall:\r
+      EditPositionMenuEvent(BlackMarshall, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
     case EP_BlackKing:\r
       EditPositionMenuEvent(BlackKing, fromX, fromY);\r
       fromX = fromY = -1;\r
@@ -5492,6 +6141,16 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       fromX = fromY = -1;\r
       break;\r
 \r
+    case EP_Promote:\r
+      EditPositionMenuEvent(PromotePiece, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
+    case EP_Demote:\r
+      EditPositionMenuEvent(DemotePiece, fromX, fromY);\r
+      fromX = fromY = -1;\r
+      break;\r
+\r
     case DP_Pawn:\r
       DropMenuEvent(WhitePawn, fromX, fromY);\r
       fromX = fromY = -1;\r
@@ -5535,8 +6194,8 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       AutoPlayGameLoop(); /* call into back end */\r
       break;\r
     case ANALYSIS_TIMER_ID:\r
-      if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) && \r
-         appData.periodicUpdates) {\r
+      if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile\r
+                 || appData.icsEngineAnalyze) && appData.periodicUpdates) {\r
        AnalysisPeriodicEvent(0);\r
       } else {\r
        KillTimer(hwnd, analysisTimerEvent);\r
@@ -5575,6 +6234,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 \r
   /* [AS] Snapping */\r
   case WM_ENTERSIZEMOVE:\r
+    if(appData.debugMode) { fprintf(debugFP, "size-move\n"); }\r
     if (hwnd == hwndMain) {\r
       doingSizing = TRUE;\r
       lastSizing = 0;\r
@@ -5583,15 +6243,18 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     break;\r
 \r
   case WM_SIZING:\r
+    if(appData.debugMode) { fprintf(debugFP, "sizing\n"); }\r
     if (hwnd == hwndMain) {\r
       lastSizing = wParam;\r
     }\r
     break;\r
 \r
   case WM_MOVING:\r
+    if(appData.debugMode) { fprintf(debugFP, "moving\n"); }\r
       return OnMoving( &sd, hwnd, wParam, lParam );\r
 \r
   case WM_EXITSIZEMOVE:\r
+    if(appData.debugMode) { fprintf(debugFP, "exit size-move, size = %d\n", squareSize); }\r
     if (hwnd == hwndMain) {\r
       RECT client;\r
       doingSizing = FALSE;\r
@@ -5599,6 +6262,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       GetClientRect(hwnd, &client);\r
       ResizeBoard(client.right, client.bottom, lastSizing);\r
       lastSizing = 0;\r
+      if(appData.debugMode) { fprintf(debugFP, "square size = %d\n", squareSize); }\r
     }\r
     return OnExitSizeMove( &sd, hwnd, wParam, lParam );\r
     break;\r
@@ -5846,7 +6510,7 @@ OpenFileHook(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)
 \r
 \r
 FILE *\r
-OpenFileDialog(HWND hwnd, BOOL write, char *defName, char *defExt,\r
+OpenFileDialog(HWND hwnd, char *write, char *defName, char *defExt, // [HGM] diag: type of 'write' now string\r
               char *nameFilt, char *dlgTitle, UINT *number,\r
               char fileTitle[MSG_SIZ], char fileName[MSG_SIZ])\r
 {\r
@@ -5878,7 +6542,7 @@ OpenFileDialog(HWND hwnd, BOOL write, char *defName, char *defExt,
   openFileName.lpstrInitialDir   = NULL;\r
   openFileName.lpstrTitle        = dlgTitle;\r
   openFileName.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY \r
-    | (write ? 0 : OFN_FILEMUSTEXIST) \r
+    | (write[0] != 'r' ? 0 : OFN_FILEMUSTEXIST) \r
     | (number ? OFN_ENABLETEMPLATE | OFN_ENABLEHOOK: 0)\r
     | (oldDialog ? 0 : OFN_EXPLORER);\r
   openFileName.nFileOffset       = 0;\r
@@ -5889,10 +6553,10 @@ OpenFileDialog(HWND hwnd, BOOL write, char *defName, char *defExt,
     (LPOFNHOOKPROC) OldOpenFileHook : (LPOFNHOOKPROC) OpenFileHook;\r
   openFileName.lpTemplateName    = (LPSTR)(oldDialog ? 1536 : DLG_IndexNumber);\r
 \r
-  if (write ? GetSaveFileName(&openFileName) : \r
-              GetOpenFileName(&openFileName)) {\r
+  if (write[0] != 'r' ? GetSaveFileName(&openFileName) : \r
+                        GetOpenFileName(&openFileName)) {\r
     /* open the file */\r
-    f = fopen(openFileName.lpstrFile, write ? "a" : "rb");\r
+    f = fopen(openFileName.lpstrFile, write);\r
     if (f == NULL) {\r
       MessageBox(hwnd, "File open failed", NULL,\r
                 MB_OK|MB_ICONEXCLAMATION);\r
@@ -6526,6 +7190,59 @@ PopUpMoveDialog(char firstchar)
 \r
 /*---------------------------------------------------------------------------*\\r
  *\r
+ * Type-in name dialog functions\r
+ * \r
+\*---------------------------------------------------------------------------*/\r
+\r
+LRESULT CALLBACK\r
+TypeInNameDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
+{\r
+  char move[MSG_SIZ];\r
+  HWND hInput;\r
+\r
+  switch (message) {\r
+  case WM_INITDIALOG:\r
+    move[0] = (char) lParam;\r
+    move[1] = NULLCHAR;\r
+    CenterWindowEx(hDlg, GetWindow(hDlg, GW_OWNER), 1 );\r
+    hInput = GetDlgItem(hDlg, OPT_Name);\r
+    SetWindowText(hInput, move);\r
+    SetFocus(hInput);\r
+    SendMessage(hInput, EM_SETSEL, (WPARAM)9999, (LPARAM)9999);\r
+    return FALSE;\r
+\r
+  case WM_COMMAND:\r
+    switch (LOWORD(wParam)) {\r
+    case IDOK:\r
+      GetDlgItemText(hDlg, OPT_Name, move, sizeof(move));\r
+      appData.userName = strdup(move);\r
+\r
+      EndDialog(hDlg, TRUE);\r
+      return TRUE;\r
+    case IDCANCEL:\r
+      EndDialog(hDlg, FALSE);\r
+      return TRUE;\r
+    default:\r
+      break;\r
+    }\r
+    break;\r
+  }\r
+  return FALSE;\r
+}\r
+\r
+VOID\r
+PopUpNameDialog(char firstchar)\r
+{\r
+    FARPROC lpProc;\r
+    \r
+      lpProc = MakeProcInstance((FARPROC)TypeInNameDialog, hInst);\r
+      DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_TypeInName),\r
+       hwndMain, (DLGPROC)lpProc, (LPARAM)firstchar);\r
+      FreeProcInstance(lpProc);\r
+}\r
+\r
+/*---------------------------------------------------------------------------*\\r
+ *\r
  *  Error dialogs\r
  * \r
 \*---------------------------------------------------------------------------*/\r
@@ -6626,6 +7343,8 @@ ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
 }\r
 \r
 #ifdef GOTHIC\r
+HWND gothicDialog = NULL;\r
+\r
 LRESULT CALLBACK\r
 GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
@@ -6646,7 +7365,7 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
         and it doesn't work when you resize the dialog.\r
         For now, just give it a default position.\r
     */\r
-\r
+    gothicDialog = hDlg;\r
     SetWindowText(hDlg, errorTitle);\r
     hwndText = GetDlgItem(hDlg, OPT_ErrorText);\r
     SetDlgItemText(hDlg, OPT_ErrorText, errorMessage);\r
@@ -6669,19 +7388,27 @@ GothicDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
 }\r
 \r
 VOID\r
-GothicPopUp(char *title)\r
+GothicPopUp(char *title, VariantClass variant)\r
 {\r
   FARPROC lpProc;\r
   char *p, *q;\r
   BOOLEAN modal = hwndMain == NULL;\r
+  static char *lastTitle;\r
 \r
   strncpy(errorTitle, title, sizeof(errorTitle));\r
   errorTitle[sizeof(errorTitle) - 1] = '\0';\r
-  \r
+\r
+  if(lastTitle != title && gothicDialog != NULL) {\r
+    DestroyWindow(gothicDialog);\r
+    gothicDialog = NULL;\r
+  }\r
+  if(variant != VariantNormal && gothicDialog == NULL) {\r
+    title = lastTitle;\r
     lpProc = MakeProcInstance((FARPROC)GothicDialog, hInst);\r
     CreateDialog(hInst, MAKEINTRESOURCE(DLG_Error),\r
                 hwndMain, (DLGPROC)lpProc);\r
     FreeProcInstance(lpProc);\r
+  }\r
 }\r
 #endif\r
 \r
@@ -7228,6 +7955,26 @@ ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       wp.rcNormalPosition.bottom = consoleY + consoleH;\r
       SetWindowPlacement(hDlg, &wp);\r
     }\r
+#if 0 \r
+   // [HGM] Chessknight's change 2004-07-13\r
+   else { /* Determine Defaults */\r
+       WINDOWPLACEMENT wp;\r
+       consoleX = winWidth + 1;\r
+       consoleY = boardY;\r
+       consoleW = screenWidth -  winWidth;\r
+       consoleH = winHeight;\r
+       EnsureOnScreen(&consoleX, &consoleY);\r
+       wp.length = sizeof(WINDOWPLACEMENT);\r
+       wp.flags = 0;\r
+       wp.showCmd = SW_SHOW;\r
+       wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
+       wp.rcNormalPosition.left = consoleX;\r
+       wp.rcNormalPosition.right = consoleX + consoleW;\r
+       wp.rcNormalPosition.top = consoleY;\r
+       wp.rcNormalPosition.bottom = consoleY + consoleH;\r
+       SetWindowPlacement(hDlg, &wp);\r
+    }\r
+#endif\r
     return FALSE;\r
 \r
   case WM_SETFOCUS:\r
@@ -7438,7 +8185,7 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight,
 \r
   if (appData.clockMode) {\r
     if (tinyLayout)\r
-      sprintf(buf, "%c %s %s %s", color[0], TimeString(timeRemaining), flagFell);\r
+      sprintf(buf, "%c %s %s", color[0], TimeString(timeRemaining), flagFell);\r
     else\r
       sprintf(buf, "%s: %s %s", color, TimeString(timeRemaining), flagFell);\r
     str = buf;\r
@@ -7753,7 +8500,7 @@ Enables icsEnables[] = {
   { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED },\r
-  { IDM_AnalysisMode, MF_BYCOMMAND|MF_GRAYED },\r
+  { IDM_AnalysisMode, MF_BYCOMMAND|MF_ENABLED },\r
   { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED },\r
@@ -7948,6 +8695,17 @@ ModeHighlight()
   }\r
 \r
   prevChecked = nowChecked;\r
+\r
+  /* [DM] icsEngineAnalyze - Do a sceure check too */\r
+  if (appData.icsActive) {\r
+       if (appData.icsEngineAnalyze) {\r
+               (void) CheckMenuItem(GetMenu(hwndMain), IDM_AnalysisMode,\r
+                       MF_BYCOMMAND|MF_CHECKED);\r
+       } else {\r
+               (void) CheckMenuItem(GetMenu(hwndMain), IDM_AnalysisMode,\r
+                       MF_BYCOMMAND|MF_UNCHECKED);\r
+       }\r
+  }\r
 }\r
 \r
 VOID\r
@@ -7960,6 +8718,9 @@ SetICSMode()
 #ifdef ZIPPY\r
   if (appData.zippyPlay) {\r
     SetMenuEnables(hmenu, zippyEnables);\r
+    if (!appData.noChessProgram)     /* [DM] icsEngineAnalyze */\r
+         (void) EnableMenuItem(GetMenu(hwndMain), IDM_AnalysisMode,\r
+          MF_BYCOMMAND|MF_ENABLED);\r
   }\r
 #endif\r
 }\r
@@ -8271,6 +9032,7 @@ LRESULT CALLBACK NewGameFRC_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM
         case IDOK:\r
             *lpIndexFRC = GetDlgItemInt(hDlg, IDC_NFG_Edit, &index_is_ok, TRUE );\r
             EndDialog( hDlg, 0 );\r
+           shuffleOpenings = TRUE; /* [HGM] shuffle: switch shuffling on for as long as we stay in current variant */\r
             return TRUE;\r
         case IDCANCEL:\r
             EndDialog( hDlg, 1 );   \r
@@ -8283,7 +9045,7 @@ LRESULT CALLBACK NewGameFRC_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM
             }\r
             return TRUE;\r
         case IDC_NFG_Random:\r
-            sprintf( buf, "%d", myrandom() % 960 );\r
+            sprintf( buf, "%d", myrandom() ); /* [HGM] shuffle: no longer limit to 960 */\r
             SetDlgItemText(hDlg, IDC_NFG_Edit, buf );\r
             return TRUE;\r
         }\r
@@ -8643,6 +9405,9 @@ UserName()
   static char buf[MSG_SIZ];\r
   DWORD bufsiz = MSG_SIZ;\r
 \r
+  if(appData.userName != NULL && appData.userName[0] != 0) { \r
+       return appData.userName; /* [HGM] username: prefer name selected by user over his system login */\r
+  }\r
   if (!GetUserName(buf, &bufsiz)) {\r
     /*DisplayError("Error getting user name", GetLastError());*/\r
     strcpy(buf, "User");\r
@@ -8690,11 +9455,13 @@ void
 DisplayWhiteClock(long timeRemaining, int highlight)\r
 {\r
   HDC hdc;\r
-  hdc = GetDC(hwndMain);\r
   char *flag = whiteFlag && gameMode == TwoMachinesPlay ? "(!)" : "";\r
 \r
+  if(appData.noGUI) return;\r
+  hdc = GetDC(hwndMain);\r
   if (!IsIconic(hwndMain)) {\r
-    DisplayAClock(hdc, timeRemaining, highlight, &whiteRect, "White", flag);\r
+    DisplayAClock(hdc, timeRemaining, highlight, \r
+                       (logoHeight > 0 ? flipView: flipClock) ? &blackRect : &whiteRect, "White", flag);\r
   }\r
   if (highlight && iconCurrent == iconBlack) {\r
     iconCurrent = iconWhite;\r
@@ -8714,9 +9481,11 @@ DisplayBlackClock(long timeRemaining, int highlight)
   HDC hdc;\r
   char *flag = blackFlag && gameMode == TwoMachinesPlay ? "(!)" : "";\r
 \r
+  if(appData.noGUI) return;\r
   hdc = GetDC(hwndMain);\r
   if (!IsIconic(hwndMain)) {\r
-    DisplayAClock(hdc, timeRemaining, highlight, &blackRect, "Black", flag);\r
+    DisplayAClock(hdc, timeRemaining, highlight, \r
+                       (logoHeight > 0 ? flipView: flipClock) ? &whiteRect : &blackRect, "Black", flag);\r
   }\r
   if (highlight && iconCurrent == iconWhite) {\r
     iconCurrent = iconBlack;\r
@@ -8761,7 +9530,7 @@ AutoSaveGame()
   char fileTitle[MSG_SIZ];\r
 \r
   defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn");\r
-  f = OpenFileDialog(hwndMain, TRUE, defName,\r
+  f = OpenFileDialog(hwndMain, "a", defName,\r
                     appData.oldSaveStyle ? "gam" : "pgn",\r
                     GAME_FILT, \r
                     "Save Game to File", NULL, fileTitle, NULL);\r
@@ -8807,6 +9576,23 @@ CancelDelayedEvent()
   }\r
 }\r
 \r
+DWORD GetWin32Priority(int nice)\r
+{ // [HGM] nice: translate Unix nice() value to indows priority class. (Code stolen from Polyglot 1.4w11)\r
+/*\r
+REALTIME_PRIORITY_CLASS     0x00000100\r
+HIGH_PRIORITY_CLASS         0x00000080\r
+ABOVE_NORMAL_PRIORITY_CLASS 0x00008000\r
+NORMAL_PRIORITY_CLASS       0x00000020\r
+BELOW_NORMAL_PRIORITY_CLASS 0x00004000\r
+IDLE_PRIORITY_CLASS         0x00000040\r
+*/\r
+        if (nice < -15) return 0x00000080;\r
+        if (nice < 0)   return 0x00008000;\r
+        if (nice == 0)  return 0x00000020;\r
+        if (nice < 15)  return 0x00004000;\r
+        return 0x00000040;\r
+}\r
+\r
 /* Start a child process running the given program.\r
    The process's standard output can be read from "from", and its\r
    standard input can be written to "to".\r
@@ -8922,6 +9708,11 @@ StartChildProcess(char *cmdLine, char *dir, ProcRef *pr)
     return err;\r
   }\r
 \r
+  if (appData.niceEngines){ // [HGM] nice: adjust engine proc priority\r
+    if(appData.debugMode) fprintf(debugFP, "nice engine proc to %d\n", appData.niceEngines);\r
+    SetPriorityClass(piProcInfo.hProcess, GetWin32Priority(appData.niceEngines));\r
+  }\r
+\r
   /* Close the handles we don't need in the parent */\r
   CloseHandle(piProcInfo.hThread);\r
   CloseHandle(hChildStdinRd);\r
@@ -8952,7 +9743,7 @@ StartChildProcess(char *cmdLine, char *dir, ProcRef *pr)
 void\r
 DestroyChildProcess(ProcRef pr, int/*boolean*/ signal)\r
 {\r
-  ChildProc *cp;\r
+  ChildProc *cp; int result;\r
 \r
   cp = (ChildProc *) pr;\r
   if (cp == NULL) return;\r
@@ -8969,22 +9760,23 @@ DestroyChildProcess(ProcRef pr, int/*boolean*/ signal)
     /*!!if (signal) GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, cp->pid);*/\r
 \r
     /* [AS] Special termination modes for misbehaving programs... */\r
-    if( signal == 9 ) {\r
+    if( signal == 9 ) { \r
+        result = TerminateProcess( cp->hProcess, 0 );\r
+\r
         if ( appData.debugMode) {\r
-            fprintf( debugFP, "Terminating process %u\n", cp->pid );\r
+            fprintf( debugFP, "Terminating process %u, result=%d\n", cp->pid, result );\r
         }\r
-\r
-        TerminateProcess( cp->hProcess, 0 );\r
     }\r
     else if( signal == 10 ) {\r
         DWORD dw = WaitForSingleObject( cp->hProcess, 3*1000 ); // Wait 3 seconds at most\r
 \r
         if( dw != WAIT_OBJECT_0 ) {\r
+            result = TerminateProcess( cp->hProcess, 0 );\r
+\r
             if ( appData.debugMode) {\r
-                fprintf( debugFP, "Process %u still alive after timeout, killing...\n", cp->pid );\r
+                fprintf( debugFP, "Process %u still alive after timeout, killing... result=%d\n", cp->pid, result );\r
             }\r
 \r
-            TerminateProcess( cp->hProcess, 0 );\r
         }\r
     }\r
 \r
@@ -9605,6 +10397,11 @@ AnalysisDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
   case WM_COMMAND: /* message: received a command */\r
     switch (LOWORD(wParam)) {\r
     case IDCANCEL:\r
+      if (appData.icsActive && appData.icsEngineAnalyze) { /* [DM] icsEngineAnalyze */\r
+          ExitAnalyzeMode();\r
+          ModeHighlight();\r
+          return TRUE;\r
+      }\r
       EditGameEvent();\r
       return TRUE;\r
     default:\r