reverted winboard.c beofre URL commit to correct whitespace conversion
[xboard.git] / winboard / winboard.c
index 275368e..0fa4807 100644 (file)
@@ -2,9 +2,12 @@
  * WinBoard.c -- Windows NT front end to XBoard\r
  *\r
  * Copyright 1991 by Digital Equipment Corporation, Maynard,\r
- * Massachusetts.  Enhancements Copyright\r
- * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software\r
- * Foundation, Inc.\r
+ * Massachusetts. \r
+ *\r
+ * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,\r
+ * 2007, 2008, 2009 Free Software Foundation, Inc.\r
+ *\r
+ * Enhancements Copyright 2005 Alessandro Scotti\r
  *\r
  * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,\r
  * which was written and is copyrighted by Wayne Christopher.\r
 \r
 extern int whiteFlag, blackFlag;\r
 Boolean flipClock = FALSE;\r
+extern HANDLE chatHandle[];\r
+extern int ics_type;\r
 \r
 void DisplayHoldingsCount(HDC hdc, int x, int y, int align, int copyNumber);\r
 VOID NewVariantPopup(HWND hwnd);\r
@@ -105,6 +110,7 @@ int FinishMove P((ChessMove moveType, int fromX, int fromY, int toX, int toY,
 void AnimateAtomicCapture(int fromX, int fromY, int toX, int toY, int nFrames);\r
 void DisplayMove P((int moveNumber));\r
 Boolean ParseFEN P((Board board, int *blackPlaysFirst, char *fen));\r
+void ChatPopUp P(());\r
 typedef struct {\r
   ChessSquare piece;  \r
   POINT pos;      /* window coordinates of current pos */\r
@@ -219,7 +225,11 @@ static struct { int x; int y; int mode; } backTextureSquareInfo[BOARD_SIZE][BOAR
 #if __GNUC__ && !defined(_winmajor)\r
 #define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */\r
 #else\r
+#if defined(_winmajor)\r
 #define oldDialog (_winmajor < 4)\r
+#else\r
+#define oldDialog 0\r
+#endif\r
 #endif\r
 \r
 char *defaultTextAttribs[] = \r
@@ -306,7 +316,7 @@ MyButtonDesc buttonDesc[N_BUTTONS] =
 };\r
 \r
 int tinyLayout = 0, smallLayout = 0;\r
-#define MENU_BAR_ITEMS 6\r
+#define MENU_BAR_ITEMS 7\r
 char *menuBarText[2][MENU_BAR_ITEMS+1] = {\r
   { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },\r
   { "&F", "&M", "&A", "&S", "&O", "&H", NULL },\r
@@ -446,6 +456,8 @@ VOID EngineOutputPopDown();
 BOOL EngineOutputIsUp();\r
 VOID EngineOutputUpdate( FrontEndProgramStats * stats );\r
 \r
+VOID EngineOptionsPopup(); // [HGM] settings\r
+\r
 VOID GothicPopUp(char *title, VariantClass variant);\r
 /*\r
  * Setting "frozen" should disable all user input other than deleting\r
@@ -482,18 +494,21 @@ void ThawUI()
   DrawMenuBar(hwndMain);\r
 }\r
 \r
-static int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them\r
+/*static*/ int fromX = -1, fromY = -1, toX, toY; // [HGM] moved upstream, so JAWS can use them\r
 \r
 /* JAWS preparation patch (WinBoard for the sight impaired). Define required insertions as empty */\r
 #ifdef JAWS\r
 #include "jaws.c"\r
 #else\r
 #define JAWS_INIT\r
+#define JAWS_ARGS\r
 #define JAWS_ALT_INTERCEPT\r
 #define JAWS_KB_NAVIGATION\r
 #define JAWS_MENU_ITEMS\r
 #define JAWS_SILENCE\r
 #define JAWS_REPLAY\r
+#define JAWS_ACCEL\r
+#define JAWS_COPYRIGHT\r
 #define JAWS_DELETE(X) X\r
 #define SAYMACHINEMOVE()\r
 #define SAY(X)\r
@@ -565,7 +580,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
        if(msg.hwnd == e2)                 currentElement = 3; else\r
        if(msg.hwnd == moveHistoryDialog) currentElement = 4; else\r
        if(msg.hwnd == mh)                currentElement = 4; else\r
-       if(msg.hwnd == evalGraphDialog)    currentElement = 7; else\r
+       if(msg.hwnd == evalGraphDialog)    currentElement = 6; else\r
        if(msg.hwnd == hText)  currentElement = 5; else\r
        if(msg.hwnd == hInput) currentElement = 6; else\r
        for (i = 0; i < N_BUTTONS; i++) {\r
@@ -590,7 +605,7 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
                case 4:\r
                  if(!MoveHistoryIsUp()) continue;\r
                  h = mh; break;\r
-//             case 5: // input to eval graph does not seem to get here!\r
+//             case 6: // input to eval graph does not seem to get here!\r
 //               if(!EvalGraphIsUp()) continue;\r
 //               h = evalGraphDialog; break;\r
                case 5:\r
@@ -619,9 +634,15 @@ WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
          !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&\r
          !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&\r
          !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&\r
-         !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&\r
+         !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) && JAWS_ACCEL\r
           !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&\r
          !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {\r
+       int done = 0, i; // [HGM] chat: dispatch cat-box messages\r
+       for(i=0; i<MAX_CHAT; i++) \r
+           if(chatHandle[i] && IsDialogMessage(chatHandle[i], &msg)) {\r
+               done = 1; break;\r
+       }\r
+       if(done) continue; // [HGM] chat: end patch\r
        TranslateMessage(&msg); /* Translates virtual key codes */\r
        DispatchMessage(&msg);  /* Dispatches message to window */\r
       }\r
@@ -851,7 +872,7 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
   wp.rcNormalPosition.bottom = boardY + winHeight;\r
   SetWindowPlacement(hwndMain, &wp);\r
 \r
-  SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
+  if(!appData.noGUI) SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
                0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
 \r
   if (hwndConsole) {\r
@@ -861,7 +882,8 @@ InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
 #endif\r
     ShowWindow(hwndConsole, nCmdShow);\r
   }\r
-  UpdateWindow(hwnd);\r
+  if(!appData.noGUI)   UpdateWindow(hwnd);  else ShowWindow(hwnd, SW_MINIMIZE);\r
+  if(gameListDialog) SetFocus(gameListDialog); // [HGM] jaws: for if we clicked multi-game game file\r
 \r
   return TRUE;\r
 \r
@@ -903,6 +925,7 @@ ArgDescriptor argDescriptors[] = {
   { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
   { "", ArgNone, NULL },\r
   /* keyword arguments */\r
+  JAWS_ARGS\r
   { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },\r
   { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },\r
   { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },\r
@@ -1314,6 +1337,9 @@ ArgDescriptor argDescriptors[] = {
   { "secondOptions", ArgString, (LPVOID) &appData.secondOptions, FALSE },\r
   { "firstNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride1, FALSE },\r
   { "secondNeedsNoncompliantFEN", ArgString, (LPVOID) &appData.fenOverride2, FALSE },\r
+  { "keepAlive", ArgInt, (LPVOID) &appData.keepAlive, FALSE },\r
+  { "icstype", ArgInt, (LPVOID) &ics_type, FALSE },\r
+  { "forceIllegalMoves", ArgTrue, (LPVOID) &appData.forceIllegal, FALSE },\r
 \r
 #ifdef ZIPPY\r
   { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },\r
@@ -2295,7 +2321,7 @@ SaveSettings(char* name)
     return;\r
   }\r
   fprintf(f, ";\n");\r
-  fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);\r
+  fprintf(f, "; %s Save Settings file\n", PACKAGE_STRING);\r
   fprintf(f, ";\n");\r
   fprintf(f, "; You can edit the values of options that are already set in this file,\n");\r
   fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");\r
@@ -5089,19 +5115,19 @@ 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
-      { /* [HGM] <sameColor> now always do UserMoveTest(), and check colors there */\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
+        moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR, FALSE);\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(moveType != ImpossibleMove && moveType != Comment) {\r
           /* [HGM] We use PromotionToKnight in Shogi to indicate frorced promotion */\r
           if (moveType == WhitePromotionKnight || moveType == BlackPromotionKnight ||\r
             ((moveType == WhitePromotionQueen || moveType == BlackPromotionQueen) &&\r
@@ -5119,39 +5145,40 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                      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
+                   // kludge to temporarily execute move on display, without promoting 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
+                   DisplayMessage("Select piece from holdings", "");\r
                  } else\r
                   PromotionPopup(hwnd);\r
-          } else {       /* not a promotion */\r
+                 goto noClear;\r
+          } else { // not a promotion. Move can be illegal if testLegality off, and should be made then.\r
              if (appData.animate || appData.highlightLastMove) {\r
                  SetHighlights(fromX, fromY, toX, toY);\r
              } else {\r
                  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
+          fromX = fromY = -1;\r
+       noClear:\r
+         break;\r
         }\r
-      }\r
-      ClearHighlights();\r
-      DrawPosition(forceFullRepaint || FALSE, NULL);\r
+        if (gotPremove && moveType != Comment) {\r
+           SetPremoveHighlights(fromX, fromY, toX, toY);\r
+//            DrawPosition(forceFullRepaint || FALSE, NULL);\r
+       } else ClearHighlights();\r
+        fromX = fromY = -1;\r
+        DrawPosition(forceFullRepaint || FALSE, NULL);\r
+       if(moveType != Comment) break;\r
     }\r
     /* First downclick, or restart on a square with same color piece */\r
     if (!frozen && OKToStartUserMove(x, y)) {\r
@@ -5199,7 +5226,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       toY = y;\r
       saveAnimate = appData.animate; /* sorry, Hawk :) */\r
       appData.animate = appData.animate && !appData.animateDragging;\r
-      moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR);\r
+      moveType = UserMoveTest(fromX, fromY, toX, toY, NULLCHAR, TRUE);\r
       if(moveType == AmbiguousMove) { /* [HGM] Edit-Position move executed */\r
                fromX = fromY = -1; \r
                ClearHighlights();\r
@@ -5227,6 +5254,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                    boards[currentMove][fromY][fromX] = p; // take back, but display stays\r
                    boards[currentMove][toY][toX] = q;\r
                    appData.animate = saveAnimate;\r
+                   DisplayMessage("Select piece from holdings", "");\r
                    break;\r
                  } else\r
                PromotionPopup(hwnd); /* [HGM] Popup now calls FinishMove */\r
@@ -5647,7 +5675,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     \r
     JAWS_ALT_INTERCEPT\r
 \r
-    if (appData.icsActive && (isalpha((char)wParam) || wParam == '0')) { \r
+    if (appData.icsActive && (char)wParam > ' ' && !((char)wParam >= '1' && (char)wParam <= '9')) { \r
        // [HGM] movenum: for non-zero digits we always do type-in dialog\r
        HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
        if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
@@ -5858,6 +5886,10 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       GameListOptions();\r
       break;\r
 \r
+    case IDM_NewChat:\r
+      ChatPopUp();\r
+      break;\r
+\r
     case IDM_CopyPosition:\r
       CopyFENToClipboard();\r
       break;\r
@@ -6109,6 +6141,12 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       DrawPosition(FALSE, NULL);\r
       break;\r
 \r
+    case IDM_MuteSounds:\r
+      mute = !mute; // [HGM] mute: keep track of global muting variable\r
+      CheckMenuItem(GetMenu(hwndMain),IDM_MuteSounds, \r
+                               MF_BYCOMMAND|(mute?MF_CHECKED:MF_UNCHECKED));\r
+      break;\r
+\r
     case IDM_GeneralOptions:\r
       GeneralOptionsPopup(hwnd);\r
       DrawPosition(TRUE, NULL);\r
@@ -6122,6 +6160,14 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       EnginePlayOptionsPopup(hwnd);\r
       break;\r
 \r
+    case IDM_Engine1Options:\r
+      EngineOptionsPopup(hwnd, &first);\r
+      break;\r
+\r
+    case IDM_Engine2Options:\r
+      EngineOptionsPopup(hwnd, &second);\r
+      break;\r
+\r
     case IDM_OptionsUCI:\r
       UciOptionsPopup(hwnd);\r
       break;\r
@@ -6659,7 +6705,8 @@ BOOLEAN
 MyPlaySound(MySound *ms)\r
 {\r
   BOOLEAN ok = FALSE;\r
-       if(appData.debugMode) fprintf(debugFP, "make sound %s %x %d\n", ms->name, ms, ms->name[0]);\r
+\r
+  if(mute) return TRUE; // [HGM] mute: suppress all sound play when muted\r
   switch (ms->name[0]) {\r
   case NULLCHAR:\r
        if(appData.debugMode) fprintf(debugFP, "silence\n");\r
@@ -7184,6 +7231,7 @@ About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
     /* Center the dialog over the application window */\r
     CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
     SetDlgItemText(hDlg, ABOUTBOX_Version, programVersion);\r
+    JAWS_COPYRIGHT\r
     return (TRUE);\r
 \r
   case WM_COMMAND: /* message: received a command */\r
@@ -9377,6 +9425,7 @@ static GLT_Item GLT_ItemInfo[] = {
     { GLT_TIME_CONTROL,"Time Control" },\r
     { GLT_VARIANT,    "Variant" },\r
     { GLT_OUT_OF_BOOK,PGN_OUT_OF_BOOK },\r
+    { GLT_RESULT_COMMENT, "Result Comment" }, // [HGM] rescom\r
     { 0, 0 }\r
 };\r
 \r
@@ -9598,6 +9647,7 @@ CommentPopUp(char *title, char *str)
 {\r
   HWND hwnd = GetActiveWindow();\r
   EitherCommentPopUp(0, title, str, FALSE);\r
+  SAY(str);\r
   SetActiveWindow(hwnd);\r
 }\r
 \r
@@ -9833,11 +9883,12 @@ void
 ScheduleDelayedEvent(DelayedEventCallback cb, long millisec)\r
 {\r
   if (delayedTimerEvent != 0) {\r
-    if (appData.debugMode) {\r
+    if (appData.debugMode && cb != delayedTimerCallback) { // [HGM] alive: not too much debug\r
       fprintf(debugFP, "ScheduleDelayedEvent: event already scheduled\n");\r
     }\r
     KillTimer(hwndMain, delayedTimerEvent);\r
     delayedTimerEvent = 0;\r
+    if(delayedTimerCallback != cb) // [HGM] alive: do not "flush" same event, just postpone it\r
     delayedTimerCallback();\r
   }\r
   delayedTimerCallback = cb;\r