changes from H.G. Muller; version 4.3.14
[xboard.git] / winboard / winboard.c
index dbf3c90..139a984 100644 (file)
@@ -388,6 +388,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
@@ -1178,6 +1179,9 @@ ArgDescriptor argDescriptors[] = {
   { "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
 \r
 #ifdef ZIPPY\r
   { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },\r
@@ -1230,6 +1234,8 @@ ArgDescriptor argDescriptors[] = {
   { "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
   { NULL, ArgNone, NULL, FALSE }\r
 };\r
 \r
@@ -1913,6 +1919,10 @@ InitAppData(LPSTR lpCmdLine)
   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
+\r
 \r
 #ifdef ZIPPY\r
   appData.zippyTalk = ZIPPY_TALK;\r
@@ -3378,7 +3388,7 @@ 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_RGHT - BOARD_LEFT; i++) {\r
@@ -3959,7 +3969,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
@@ -3982,7 +3991,6 @@ DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)
       else if( column == BOARD_RGHT) /* right align */\r
             DisplayHoldingsCount(hdc, x, y, 1, (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
@@ -4026,6 +4034,15 @@ 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
@@ -4340,6 +4357,81 @@ HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)
         boardRect.right - boardRect.left,\r
         boardRect.bottom - boardRect.top,\r
         tmphdc, boardRect.left, boardRect.top, SRCCOPY);\r
+\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
@@ -4366,6 +4458,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
@@ -4853,10 +4964,10 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
               SW_SHOW : SW_HIDE);\r
     /* [HGM] Only allow C & A promotions if these pieces are defined */\r
     ShowWindow(GetDlgItem(hDlg, PB_Archbishop),\r
-       (PieceToChar(WhiteCardinal) >= 'A' &&\r
-        PieceToChar(WhiteCardinal) != '~' ||\r
-        PieceToChar(BlackCardinal) >= 'A' &&\r
-        PieceToChar(BlackCardinal) != '~'   ) ?\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
        (PieceToChar(WhiteMarshall) >= 'A' &&\r
@@ -4902,7 +5013,7 @@ Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
       promoChar = PieceToChar(BlackMarshall);\r
       break;\r
     case PB_Archbishop:\r
-      promoChar = PieceToChar(BlackCardinal);\r
+      promoChar = PieceToChar(BlackAngel);\r
       break;\r
     case PB_Knight:\r
       promoChar = gameInfo.variant == VariantShogi ? '=' : PieceToChar(BlackKnight);\r
@@ -4950,7 +5061,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
@@ -5157,7 +5268,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
@@ -5180,7 +5291,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
@@ -5191,7 +5302,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
@@ -5200,6 +5311,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
@@ -5433,6 +5555,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
@@ -6107,7 +6233,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
@@ -6139,7 +6265,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
@@ -6150,10 +6276,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
@@ -6787,6 +6913,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
@@ -7709,7 +7888,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
@@ -8542,6 +8721,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
@@ -8554,7 +8734,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
@@ -8914,6 +9094,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
@@ -9032,7 +9215,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