Merge branch 'v4.8.x'
[xboard.git] / winboard / winboard.c
index 2183232..ca901bf 100644 (file)
@@ -535,12 +535,12 @@ typedef struct {
 \r
 SizeInfo sizeInfo[] = \r
 {\r
-  { "tiny",     21, 0, 1, 1, 0, 0 },\r
-  { "teeny",    25, 1, 1, 1, 0, 0 },\r
-  { "dinky",    29, 1, 1, 1, 0, 0 },\r
-  { "petite",   33, 1, 1, 1, 0, 0 },\r
-  { "slim",     37, 2, 1, 0, 0, 0 },\r
-  { "small",    40, 2, 1, 0, 0, 0 },\r
+  { "tiny",     21, 0, 1, 2, 0, 0 },\r
+  { "teeny",    25, 1, 1, 2, 0, 0 },\r
+  { "dinky",    29, 1, 1, 2, 0, 0 },\r
+  { "petite",   33, 1, 1, 2, 0, 0 },\r
+  { "slim",     37, 2, 1, 1, 0, 0 },\r
+  { "small",    40, 2, 1, 1, 0, 0 },\r
   { "mediocre", 45, 2, 1, 0, 0, 0 },\r
   { "middling", 49, 2, 0, 0, 0, 0 },\r
   { "average",  54, 2, 0, 0, 0, 0 },\r
@@ -588,7 +588,7 @@ typedef struct {
   WNDPROC wndproc;\r
 } MyButtonDesc;\r
 \r
-#define BUTTON_WIDTH (tinyLayout ? 16 : 32)\r
+#define BUTTON_WIDTH (tinyLayout == 2 ? 16 : 32)\r
 #define N_BUTTONS 5\r
 \r
 MyButtonDesc buttonDesc[N_BUTTONS] =\r
@@ -602,8 +602,9 @@ MyButtonDesc buttonDesc[N_BUTTONS] =
 \r
 int tinyLayout = 0, smallLayout = 0;\r
 #define MENU_BAR_ITEMS 9\r
-char *menuBarText[2][MENU_BAR_ITEMS+1] = {\r
+char *menuBarText[3][MENU_BAR_ITEMS+1] = {\r
   { N_("&File"), N_("&Edit"), N_("&View"), N_("&Mode"), N_("&Action"), N_("E&ngine"), N_("&Options"), N_("&Help"), NULL },\r
+  { N_("&Fil"), N_("&Ed"), N_("&Vw"), N_("&Mod"), N_("&Act"), N_("E&ng"), N_("&Opt"), N_("&Hlp"), NULL },\r
   { N_("&F"), N_("&E"), N_("&V"), N_("&M"), N_("&A"), N_("&N"), N_("&O"), N_("&H"), NULL },\r
 };\r
 \r
@@ -1106,6 +1107,8 @@ InitGeometry()
   screenGeometry.bottom = screenGeometry.top + screenHeight;\r
 }\r
 \r
+ChessProgramState broadcast;\r
+\r
 BOOL\r
 InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)\r
 {\r
@@ -1138,7 +1141,18 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
     appData.ringBellAfterMoves = TRUE;\r
   }\r
   if (appData.debugMode) {\r
-    debugFP = fopen(appData.nameOfDebugFile, "w");\r
+    char *c = appData.nameOfDebugFile;\r
+    if(strstr(c, "///") == c) {\r
+      broadcast.which = "broadcaster";\r
+      broadcast.pr   = NoProc;\r
+      broadcast.isr  = NULL;\r
+      broadcast.program = c + 3;\r
+      broadcast.dir  = ".";\r
+      broadcast.host = "localhost";\r
+      StartChessProgram(&broadcast);\r
+      debugFP = (FILE*) _fdopen(_open_osfhandle((long)(((ChildProc*)(broadcast.pr))->hTo), _O_WRONLY), "w");\r
+    } else\r
+    debugFP = fopen(c, "w");\r
     setbuf(debugFP, NULL);\r
   }\r
 \r
@@ -1284,6 +1298,8 @@ LFfromMFP(LOGFONT* lf, MyFontParams *mfp)
   lf->lfCharSet = mfp->charset;\r
   lf->lfOutPrecision = OUT_DEFAULT_PRECIS;\r
 \r
+\r
+\r
   lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;\r
   lf->lfQuality = DEFAULT_QUALITY;\r
   lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
@@ -2351,13 +2367,17 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   minorSize = 0; /* [HGM] Kludge to see if demagnified pieces need to be shifted  */\r
   border = appData.useBorder && appData.border[0] ? squareSize/2 : 0;\r
 \r
+  // [HGM] decide on tininess based on total board width rather than square size\r
+  tinyLayout = squareSize * (BOARD_WIDTH);\r
+  tinyLayout = tinyLayout < 35*8 ? 2 : tinyLayout < 43*8 ? 1 : 0;\r
+\r
   if( appData.overrideLineGap >= 0 && appData.overrideLineGap <= 5 ) {\r
       lineGap = appData.overrideLineGap;\r
   }\r
 \r
   if (tinyLayout != oldTinyLayout) {\r
     long style = GetWindowLongPtr(hwndMain, GWL_STYLE);\r
-    if (tinyLayout) {\r
+    if (tinyLayout == 2) {\r
       style &= ~WS_SYSMENU;\r
       InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,\r
                 "&Minimize\tCtrl+F4");\r
@@ -2393,7 +2413,7 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   ReleaseDC(hwndMain, hdc);\r
 \r
   /* Compute where everything goes */\r
-  if((first.programLogo || second.programLogo) && !tinyLayout) {\r
+  if((first.programLogo || second.programLogo) && tinyLayout != 2) {\r
         /* [HGM] logo: if either logo is on, reserve space for it */\r
        logoHeight =  2*clockSize.cy;\r
        leftLogoRect.left   = OUTER_MARGIN;\r
@@ -2514,7 +2534,7 @@ InitDrawingSizes(BoardSize boardSize, int flags)
                     messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,\r
                     (HMENU) buttonDesc[i].id,\r
                     (HINSTANCE) GetWindowLongPtr(hwndMain, GWLP_HINSTANCE), NULL);\r
-      if (tinyLayout) {\r
+      if (tinyLayout == 2) {\r
        SendMessage(buttonDesc[i].hwnd, WM_SETFONT, \r
                    (WPARAM)font[boardSize][MESSAGE_FONT]->hf,\r
                    MAKELPARAM(FALSE, 0));\r
@@ -2583,10 +2603,12 @@ InitDrawingSizes(BoardSize boardSize, int flags)
         piece = (ChessSquare) ((int) piece + 1)) {\r
       if (pieceBitmap[i][piece] != NULL)\r
        DeleteObject(pieceBitmap[i][piece]);\r
+      pieceBitmap[i][piece] = NULL;\r
     }\r
   }\r
 \r
   fontBitmapSquareSize = 0; /* [HGM] render: make sure pieces will be recreated, as we might need others now */\r
+\r
   // Orthodox Chess pieces\r
   pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");\r
   pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");\r
@@ -2684,12 +2706,27 @@ InitDrawingSizes(BoardSize boardSize, int flags)
     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][WhiteAmazon] = DoLoadBitmap(hInst, "l", squareSize, "s");\r
+    pieceBitmap[1][WhiteAmazon] = DoLoadBitmap(hInst, "l", squareSize, "o");\r
+    pieceBitmap[2][WhiteAmazon] = 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
     pieceBitmap[0][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "s");\r
     pieceBitmap[1][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "o");\r
     pieceBitmap[2][WhiteLion] = DoLoadBitmap(hInst, "ln", squareSize, "w");\r
+    pieceBitmap[0][WhiteCub] = DoLoadBitmap(hInst, "ln", squareSize, "s");\r
+    pieceBitmap[1][WhiteCub] = DoLoadBitmap(hInst, "ln", squareSize, "o");\r
+    pieceBitmap[2][WhiteCub] = DoLoadBitmap(hInst, "ln", squareSize, "w");\r
+    pieceBitmap[0][WhiteWolf] = DoLoadBitmap(hInst, "wolf", squareSize, "s");\r
+    pieceBitmap[1][WhiteWolf] = DoLoadBitmap(hInst, "wolf", squareSize, "o");\r
+    pieceBitmap[2][WhiteWolf] = DoLoadBitmap(hInst, "wolf", squareSize, "w");\r
+    pieceBitmap[0][WhiteCamel] = DoLoadBitmap(hInst, "camel", squareSize, "s");\r
+    pieceBitmap[1][WhiteCamel] = DoLoadBitmap(hInst, "camel", squareSize, "o");\r
+    pieceBitmap[2][WhiteCamel] = DoLoadBitmap(hInst, "camel", squareSize, "w");\r
+    pieceBitmap[0][WhiteZebra] = DoLoadBitmap(hInst, "zebra", squareSize, "s");\r
+    pieceBitmap[1][WhiteZebra] = DoLoadBitmap(hInst, "zebra", squareSize, "o");\r
+    pieceBitmap[2][WhiteZebra] = DoLoadBitmap(hInst, "n", squareSize, "w");\r
 \r
     if(gameInfo.variant == VariantShogi && BOARD_HEIGHT != 7) { /* promoted Gold representations (but not in Tori!)*/\r
       pieceBitmap[0][WhiteCannon] = DoLoadBitmap(hInst, "wp", squareSize, "s");\r
@@ -2791,6 +2828,15 @@ InitDrawingSizes(BoardSize boardSize, int flags)
   pieceBitmap[2][WhiteSilver] = DoLoadBitmap(hInst, "sw", squareSize, "w");\r
   minorSize = 0;\r
   }\r
+\r
+  if(appData.pieceDirectory[0]) for(i=WhitePawn; i<BlackPawn; i++) { // try for all missing pieces with new naming convention\r
+    char buf[MSG_SIZ];\r
+    if(pieceBitmap[0][i]) continue;\r
+    snprintf(buf, MSG_SIZ, "piece%d_", i);\r
+    pieceBitmap[0][i] = DoLoadBitmap(hInst, buf, squareSize, "s");\r
+    pieceBitmap[1][i] = DoLoadBitmap(hInst, buf, squareSize, "o");\r
+    pieceBitmap[2][i] = DoLoadBitmap(hInst, buf, squareSize, "w");\r
+  }\r
 }\r
 \r
 HBITMAP\r
@@ -3991,6 +4037,7 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
   }\r
 \r
   if( appData.highlightMoveWithArrow ) {\r
+\r
     DrawArrowHighlight(hdcmem);\r
   }\r
 \r
@@ -4511,6 +4558,7 @@ static int promoStyle;
 LRESULT CALLBACK\r
 Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
+\r
   char promoChar;\r
 \r
   switch (message) {\r
@@ -4612,7 +4660,7 @@ PromotionPopup(HWND hwnd)
 void\r
 PromotionPopUp(char choice)\r
 {\r
-  promoStyle = (choice == '+');\r
+  promoStyle = (choice == '+' || IS_SHOGI(gameInfo.variant));\r
   DrawPosition(TRUE, NULL);\r
   PromotionPopup(hwndMain);\r
 }\r
@@ -5083,12 +5131,14 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       break;\r
 \r
     case IDM_Match: // [HGM] match: flows into next case, after setting Match Mode and nr of Games\r
+      if(matchMode) EnableMenuItem(GetMenu(hwndMain), IDM_Match, MF_BYCOMMAND|MF_GRAYED);\r
       MatchEvent(2); // distinguish from command-line-triggered case (matchMode=1)\r
       break;\r
 \r
     case IDM_TwoMachines:\r
       TwoMachinesEvent();\r
       /*\r
+\r
        * refresh the tags dialog only if it's visible\r
        */\r
       if (gameMode == TwoMachinesPlay && IsWindowVisible(editTagsDialog)) {\r
@@ -5688,6 +5738,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
             ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, hwndConsole, &wpConsole );\r
            wpMain.x = lpwp->x;\r
             wpMain.y = lpwp->y;\r
+\r
         }\r
     }\r
     break;\r
@@ -6705,7 +6756,7 @@ TypeInNameDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     case IDOK:\r
       GetDlgItemText(hDlg, OPT_Name, move, sizeof(move));\r
       appData.userName = strdup(move);\r
-      SetUserLogo();\r
+      SetUserLogo(); DisplayLogos();\r
       SetGameInfo();\r
       if(gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack) {\r
        snprintf(move, MSG_SIZ, "%s vs. %s", gameInfo.white, gameInfo.black);\r
@@ -7645,7 +7696,7 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight,
 \r
   if (twoBoards && partnerUp) return;\r
   if (appData.clockMode) {\r
-    if (tinyLayout)\r
+    if (tinyLayout == 2)\r
       snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%c %s %s", color[0], TimeString(timeRemaining), flagFell);\r
     else\r
       snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s:%c%s %s", color, (logoHeight>0 ? 0 : ' '), TimeString(timeRemaining), flagFell);\r
@@ -7661,6 +7712,7 @@ DisplayAClock(HDC hdc, int timeRemaining, int highlight,
     oldFg = SetTextColor(hdc, RGB(0, 0, 0)); /* black */\r
     oldBg = SetBkColor(hdc, RGB(255, 255, 255)); /* white */\r
   }\r
+\r
   oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);\r
 \r
   JAWS_SILENCE\r
@@ -7977,6 +8029,7 @@ Enables gnuEnables[] = {
   { IDM_Annotate, MF_BYCOMMAND|MF_GRAYED },\r
   { IDM_NewChat, MF_BYCOMMAND|MF_GRAYED },\r
 \r
+\r
   // Needed to switch from ncp to GNU mode on Engine Load\r
   { ACTION_POS, MF_BYPOSITION|MF_ENABLED },\r
   { IDM_MachineWhite, MF_BYCOMMAND|MF_ENABLED },\r
@@ -8206,6 +8259,8 @@ ModeHighlight()
     nowChecked = 0;\r
     break;\r
   }\r
+  if(prevChecked == IDM_TwoMachines) // [HGM] 'Machine Match' might have gotten disabled when stopping match\r
+    EnableMenuItem(GetMenu(hwndMain), IDM_Match, MF_BYCOMMAND|MF_ENABLED);\r
   CheckMark(prevChecked, MF_UNCHECKED);\r
   CheckMark(nowChecked, MF_CHECKED);\r
   CheckMark(IDM_Match, matchMode && matchGame < appData.matchGames ? MF_CHECKED : MF_UNCHECKED);\r