changes from H.G. Muller; version 4.3.16 v4.3.16
authorH.G. Muller <h.g.muller@hccnet.nl>
Sat, 2 May 2009 17:55:39 +0000 (10:55 -0700)
committerArun Persaud <arun@nubati.net>
Sat, 2 May 2009 17:58:36 +0000 (10:58 -0700)
20 files changed:
backend.c
backend.h
common.h
configure [changed mode: 0644->0755]
engine-intf.html
moves.c
parser.c
parser.l [changed mode: 0644->0755]
texi2man [changed mode: 0644->0755]
winboard/config.h
winboard/cygwin.mak
winboard/readme.txt
winboard/wengineo.c
winboard/wengineoutput.c
winboard/winboard.c
winboard/woptions.c
xboard.c
xengineoutput.c
xoptions.c
zippy.c

index 5496797..25ee4c0 100644 (file)
--- a/backend.c
+++ b/backend.c
@@ -55,7 +55,7 @@
 \r
 #else\r
 \r
-#define DoSleep( n )\r
+#define DoSleep( n ) if( (n) >= 0) sleep(n)\r
 \r
 #endif\r
 \r
@@ -127,23 +127,6 @@ typedef struct {
     int ms;    /* Assuming this is >= 16 bits */\r
 } TimeMark;\r
 \r
-/* Search stats from chessprogram */\r
-typedef struct {\r
-  char movelist[2*MSG_SIZ]; /* Last PV we were sent */\r
-  int depth;              /* Current search depth */\r
-  int nr_moves;           /* Total nr of root moves */\r
-  int moves_left;         /* Moves remaining to be searched */\r
-  char move_name[MOVE_LEN];  /* Current move being searched, if provided */\r
-  unsigned long nodes;    /* # of nodes searched */\r
-  int time;               /* Search time (centiseconds) */\r
-  int score;              /* Score (centipawns) */\r
-  int got_only_move;      /* If last msg was "(only move)" */\r
-  int got_fail;           /* 0 - nothing, 1 - got "--", 2 - got "++" */\r
-  int ok_to_send;         /* handshaking between send & recv */\r
-  int line_is_book;       /* 1 if movelist is book moves */\r
-  int seen_stat;          /* 1 if we've seen the stat01: line */\r
-} ChessProgramStats;\r
-\r
 int establish P((void));\r
 void read_from_player P((InputSourceRef isr, VOIDSTAR closure,\r
                         char *buf, int count, int error));\r
@@ -216,6 +199,8 @@ void InitBackEnd3 P((void));
 void FeatureDone P((ChessProgramState* cps, int val));\r
 void InitChessProgram P((ChessProgramState *cps, int setup));\r
 ChessProgramState *WhitePlayer();\r
+void InsertIntoMemo P((int which, char *text)); // [HGM] kibitz: in engineo.c\r
+int VerifyDisplayMode P(());\r
 \r
 char *GetInfoFromComment( int, char * ); // [HGM] PV time: returns stripped comment\r
 void InitEngineUCI( const char * iniDir, ChessProgramState * cps ); // [HGM] moved here from winboard.c\r
@@ -224,7 +209,7 @@ char *SendMoveToBookUser P((int nr, ChessProgramState *cps, int initial)); // [H
 extern char installDir[MSG_SIZ];\r
 \r
 extern int tinyLayout, smallLayout;\r
-static ChessProgramStats programStats;\r
+ChessProgramStats programStats;\r
 static int exiting = 0; /* [HGM] moved to top */\r
 static int setboardSpoiledMachineBlack = 0, errorExitFlag = 0;\r
 extern int startedFromPositionFile;\r
@@ -233,6 +218,7 @@ char endingGame = 0;    /* [HGM] crash: flag to prevent recursion of GameEnds()
 int whiteNPS, blackNPS; /* [HGM] nps: for easily making clocks aware of NPS     */\r
 VariantClass currentlyInitializedVariant; /* [HGM] variantswitch */\r
 int lastIndex = 0;      /* [HGM] autoinc: last game/position used in match mode */\r
+int opponentKibitzes;\r
 \r
 /* States for ics_getting_history */\r
 #define H_FALSE 0\r
@@ -318,9 +304,9 @@ PosFlags(index)
   if ((index % 2) == 0) flags |= F_WHITE_ON_MOVE;\r
   switch (gameInfo.variant) {\r
   case VariantSuicide:\r
-  case VariantGiveaway:\r
-    flags |= F_IGNORE_CHECK;\r
     flags &= ~F_ALL_CASTLE_OK;\r
+  case VariantGiveaway:                // [HGM] moved this case label one down: seems Giveaway does have castling on ICC!\r
+    flags |= F_IGNORE_CHECK;\r
     break;\r
   case VariantAtomic:\r
     flags |= F_IGNORE_CHECK | F_ATOMIC_CAPTURE;\r
@@ -495,6 +481,13 @@ ChessSquare CapablancaArray[2][BOARD_SIZE] = {
         BlackKing, BlackBishop, BlackMarshall, BlackKnight, BlackRook }\r
 };\r
 \r
+ChessSquare GreatArray[2][BOARD_SIZE] = {\r
+    { WhiteDragon, WhiteKnight, WhiteAlfil, WhiteGrasshopper, WhiteKing, \r
+        WhiteSilver, WhiteCardinal, WhiteAlfil, WhiteKnight, WhiteDragon },\r
+    { BlackDragon, BlackKnight, BlackAlfil, BlackGrasshopper, BlackKing, \r
+        BlackSilver, BlackCardinal, BlackAlfil, BlackKnight, BlackDragon },\r
+};\r
+\r
 ChessSquare JanusArray[2][BOARD_SIZE] = {\r
     { WhiteRook, WhiteAngel, WhiteKnight, WhiteBishop, WhiteKing, \r
         WhiteQueen, WhiteBishop, WhiteKnight, WhiteAngel, WhiteRook },\r
@@ -528,6 +521,7 @@ ChessSquare FalconArray[2][BOARD_SIZE] = {
 #define XiangqiPosition FIDEArray\r
 #define CapablancaArray FIDEArray\r
 #define GothicArray FIDEArray\r
+#define GreatArray FIDEArray\r
 #endif // !(BOARD_SIZE>=10)\r
 \r
 #if (BOARD_SIZE>=12)\r
@@ -860,6 +854,7 @@ InitBackEnd1()
       case VariantCapaRandom: /* should work */\r
       case VariantJanus:      /* should work */\r
       case VariantSuper:      /* experimental */\r
+      case VariantGreat:      /* experimental, requires legality testing to be off */\r
        break;\r
       }\r
     }\r
@@ -1531,7 +1526,8 @@ StringToVariant(e)
 \r
     if (!found) {\r
       if ((StrCaseStr(e, "fischer") && StrCaseStr(e, "random"))\r
-         || StrCaseStr(e, "wild/fr")) {\r
+         || StrCaseStr(e, "wild/fr") \r
+         || StrCaseStr(e, "frc") || StrCaseStr(e, "960")) {\r
         v = VariantFischeRandom;\r
       } else if ((i = 4, p = StrCaseStr(e, "wild")) ||\r
                 (i = 1, p = StrCaseStr(e, "w"))) {\r
@@ -1673,6 +1669,9 @@ StringToVariant(e)
         case 49:\r
           v = VariantSuper;\r
          break;\r
+        case 50:\r
+          v = VariantGreat;\r
+         break;\r
        case -1:\r
          /* Found "wild" or "w" in the string but no number;\r
             must assume it's normal chess. */\r
@@ -1889,7 +1888,7 @@ CopyHoldings(Board board, char *holdings, ChessSquare lowestPiece)
         j = PieceToNumber(piece);\r
         if(j >= gameInfo.holdingsSize) continue; /* ignore pieces that do not fit */\r
         if(j < 0) continue;               /* should not happen */\r
-        piece = (ChessSquare) ( j + (int)lowestPiece );\r
+        piece = (ChessSquare) ( (int)piece + (int)lowestPiece );\r
         board[holdingsStartRow+j*direction][holdingsColumn] = piece;\r
         board[holdingsStartRow+j*direction][countsColumn]++;\r
     }\r
@@ -1996,6 +1995,7 @@ static int player2Rating = -1;
 /*----------------------------*/\r
 \r
 ColorClass curColor = ColorNormal;\r
+int suppressKibitz = 0;\r
 \r
 void\r
 read_from_ics(isr, closure, data, count, error)\r
@@ -2208,7 +2208,28 @@ read_from_ics(isr, closure, data, count, error)
                parse[parse_pos++] = buf[i];\r
                if (buf[i] == '\n') {\r
                    parse[parse_pos] = NULLCHAR;\r
-                   AppendComment(forwardMostMove, StripHighlight(parse));\r
+                   if(!suppressKibitz) // [HGM] kibitz\r
+                       AppendComment(forwardMostMove, StripHighlight(parse));\r
+                   else { // [HGM kibitz: divert memorized engine kibitz to engine-output window\r
+                       int nrDigit = 0, nrAlph = 0, i;\r
+                       if(parse_pos > MSG_SIZ - 30) // defuse unreasonably long input\r
+                       { parse_pos = MSG_SIZ-30; parse[parse_pos - 1] = '\n'; }\r
+                       parse[parse_pos] = NULLCHAR;\r
+                       // try to be smart: if it does not look like search info, it should go to\r
+                       // ICS interaction window after all, not to engine-output window.\r
+                       for(i=0; i<parse_pos; i++) { // count letters and digits\r
+                           nrDigit += (parse[i] >= '0' && parse[i] <= '9');\r
+                           nrAlph  += (parse[i] >= 'a' && parse[i] <= 'z');\r
+                           nrAlph  += (parse[i] >= 'A' && parse[i] <= 'Z');\r
+                       }\r
+                       if(nrAlph < 9*nrDigit) { // if more than 10% digit we assume search info\r
+                           OutputKibitz(suppressKibitz, parse);\r
+                       } else {\r
+                           char tmp[MSG_SIZ];\r
+                           sprintf(tmp, "your opponent kibitzes: %s", parse);\r
+                           SendToPlayer(tmp, strlen(tmp));\r
+                       }\r
+                   }\r
                    started = STARTED_NONE;\r
                } else {\r
                    /* Don't match patterns against characters in chatter */\r
@@ -2289,6 +2310,33 @@ read_from_ics(isr, closure, data, count, error)
            }\r
 \r
            oldi = i;\r
+           // [HGM] kibitz: try to recognize opponent engine-score kibitzes, to divert them to engine-output window\r
+           if (appData.autoKibitz && started == STARTED_NONE && \r
+               (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack || gameMode == IcsObserving)) {\r
+               if(looking_at(buf, &i, "* kibitzes: ") &&\r
+                  (StrStr(star_match[0], gameInfo.white) == star_match[0] || \r
+                   StrStr(star_match[0], gameInfo.black) == star_match[0]   )) { // kibitz of self or opponent\r
+                       suppressKibitz = TRUE;\r
+                       if((StrStr(star_match[0], gameInfo.white) == star_match[0])\r
+                               && (gameMode == IcsPlayingWhite) ||\r
+                          (StrStr(star_match[0], gameInfo.black) == star_match[0])\r
+                               && (gameMode == IcsPlayingBlack)   ) // opponent kibitz\r
+                           started = STARTED_CHATTER; // own kibitz we simply discard\r
+                       else {\r
+                           started = STARTED_COMMENT; // make sure it will be collected in parse[]\r
+                           parse_pos = 0; parse[0] = NULLCHAR;\r
+                           savingComment = TRUE;\r
+                           suppressKibitz = gameMode != IcsObserving ? 2 :\r
+                               (StrStr(star_match[0], gameInfo.white) == NULL) + 1;\r
+                       } \r
+                       continue;\r
+               } else\r
+               if(looking_at(buf, &i, "kibitzed to")) { // suppress the acknowledgements of our own autoKibitz\r
+                   started = STARTED_CHATTER;\r
+                   suppressKibitz = TRUE;\r
+               }\r
+           } // [HGM] kibitz: end of patch\r
+\r
            if (appData.zippyTalk || appData.zippyPlay) {\r
 #if ZIPPY\r
                if (ZippyControl(buf, &i) ||\r
@@ -2637,7 +2685,7 @@ read_from_ics(isr, closure, data, count, error)
            \r
            if (looking_at(buf, &i, "% ") ||\r
                ((started == STARTED_MOVES || started == STARTED_MOVES_NOHIDE)\r
-                && looking_at(buf, &i, "}*"))) {\r
+                && looking_at(buf, &i, "}*"))) { char *bookHit = NULL; // [HGM] book\r
                savingComment = FALSE;\r
                switch (started) {\r
                  case STARTED_MOVES:\r
@@ -2656,11 +2704,18 @@ read_from_ics(isr, closure, data, count, error)
                                  }\r
                                  SendTimeRemaining(&first, TRUE);\r
                                }\r
+#if 0\r
                                if (first.useColors) {\r
                                  SendToProgram("white\ngo\n", &first);\r
                                } else {\r
                                  SendToProgram("go\n", &first);\r
                                }\r
+#else\r
+                               if (first.useColors) {\r
+                                 SendToProgram("white\n", &first); // [HGM] book: made sending of "go\n" book dependent\r
+                               }\r
+                               bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: probe book for initial pos\r
+#endif\r
                                first.maybeThinking = TRUE;\r
                            } else {\r
                                if (first.usePlayother) {\r
@@ -2681,11 +2736,18 @@ read_from_ics(isr, closure, data, count, error)
                                  }\r
                                  SendTimeRemaining(&first, FALSE);\r
                                }\r
+#if 0\r
                                if (first.useColors) {\r
                                  SendToProgram("black\ngo\n", &first);\r
                                } else {\r
                                  SendToProgram("go\n", &first);\r
                                }\r
+#else\r
+                               if (first.useColors) {\r
+                                 SendToProgram("black\n", &first);\r
+                               }\r
+                               bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE);\r
+#endif\r
                                first.maybeThinking = TRUE;\r
                            } else {\r
                                if (first.usePlayother) {\r
@@ -2738,6 +2800,17 @@ read_from_ics(isr, closure, data, count, error)
                  default:\r
                    break;\r
                }\r
+               if(bookHit) { // [HGM] book: simulate book reply\r
+                   static char bookMove[MSG_SIZ]; // a bit generous?\r
+\r
+                   programStats.depth = programStats.nodes = programStats.time = \r
+                   programStats.score = programStats.got_only_move = 0;\r
+                   sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
+\r
+                   strcpy(bookMove, "move ");\r
+                   strcat(bookMove, bookHit);\r
+                   HandleMachineMove(bookMove, &first);\r
+               }\r
                continue;\r
            }\r
            \r
@@ -3120,11 +3193,12 @@ read_from_ics(isr, closure, data, count, error)
            i++;                /* skip unparsed character and loop back */\r
        }\r
        \r
-       if (started != STARTED_MOVES && started != STARTED_BOARD &&\r
+       if (started != STARTED_MOVES && started != STARTED_BOARD && !suppressKibitz && // [HGM] kibitz suppress printing in ICS interaction window\r
            started != STARTED_HOLDINGS && i > next_out) {\r
            SendToPlayer(&buf[next_out], i - next_out);\r
            next_out = i;\r
        }\r
+       suppressKibitz = FALSE; // [HGM] kibitz: has done its duty in if-statement above\r
        \r
        leftover_len = buf_len - leftover_start;\r
        /* if buffer ends with something we couldn't parse,\r
@@ -3548,8 +3622,37 @@ ParseBoard12(string)
            strcat(parseList[moveNum - 1], " ");\r
            strcat(parseList[moveNum - 1], elapsed_time);\r
            moveList[moveNum - 1][0] = NULLCHAR;\r
-       } else if (ParseOneMove(move_str, moveNum - 1, &moveType,\r
-                               &fromX, &fromY, &toX, &toY, &promoChar)) {\r
+       } else if (strcmp(move_str, "none") == 0) {\r
+           // [HGM] long SAN: swapped order; test for 'none' before parsing move\r
+           /* Again, we don't know what the board looked like;\r
+              this is really the start of the game. */\r
+           parseList[moveNum - 1][0] = NULLCHAR;\r
+           moveList[moveNum - 1][0] = NULLCHAR;\r
+           backwardMostMove = moveNum;\r
+           startedFromSetupPosition = TRUE;\r
+           fromX = fromY = toX = toY = -1;\r
+       } else {\r
+         // [HGM] long SAN: if legality-testing is off, disambiguation might not work or give wrong move. \r
+         //                 So we parse the long-algebraic move string in stead of the SAN move\r
+         int valid; char buf[MSG_SIZ], *prom;\r
+\r
+         // str looks something like "Q/a1-a2"; kill the slash\r
+         if(str[1] == '/') \r
+               sprintf(buf, "%c%s", str[0], str+2);\r
+         else  strcpy(buf, str); // might be castling\r
+         if((prom = strstr(move_str, "=")) && !strstr(buf, "=")) \r
+               strcat(buf, prom); // long move lacks promo specification!\r
+         if(!appData.testLegality) {\r
+               if(appData.debugMode) \r
+                       fprintf(debugFP, "replaced ICS move '%s' by '%s'\n", move_str, buf);\r
+               strcpy(move_str, buf);\r
+          }\r
+         valid = ParseOneMove(move_str, moveNum - 1, &moveType,\r
+                               &fromX, &fromY, &toX, &toY, &promoChar)\r
+              || ParseOneMove(buf, moveNum - 1, &moveType,\r
+                               &fromX, &fromY, &toX, &toY, &promoChar);\r
+         // end of long SAN patch\r
+         if (valid) {\r
            (void) CoordsToAlgebraic(boards[moveNum - 1],\r
                                     PosFlags(moveNum - 1), EP_UNKNOWN,\r
                                     fromY, fromX, toY, toX, promoChar,\r
@@ -3573,15 +3676,7 @@ ParseBoard12(string)
            /* currentMoveString is set as a side-effect of ParseOneMove */\r
            strcpy(moveList[moveNum - 1], currentMoveString);\r
            strcat(moveList[moveNum - 1], "\n");\r
-       } else if (strcmp(move_str, "none") == 0) {\r
-           /* Again, we don't know what the board looked like;\r
-              this is really the start of the game. */\r
-           parseList[moveNum - 1][0] = NULLCHAR;\r
-           moveList[moveNum - 1][0] = NULLCHAR;\r
-           backwardMostMove = moveNum;\r
-           startedFromSetupPosition = TRUE;\r
-           fromX = fromY = toX = toY = -1;\r
-       } else {\r
+         } else {\r
            /* Move from ICS was illegal!?  Punt. */\r
   if (appData.debugMode) {\r
     fprintf(debugFP, "Illegal move from ICS '%s'\n", move_str);\r
@@ -3598,6 +3693,7 @@ ParseBoard12(string)
            strcat(parseList[moveNum - 1], elapsed_time);\r
            moveList[moveNum - 1][0] = NULLCHAR;\r
            fromX = fromY = toX = toY = -1;\r
+         }\r
        }\r
   if (appData.debugMode) {\r
     fprintf(debugFP, "Move parsed to '%s'\n", parseList[moveNum - 1]);\r
@@ -3724,7 +3820,7 @@ ParseBoard12(string)
 \r
        programStats.depth = programStats.nodes = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
-       sprintf(programStats.movelist, "%s (xbook)", bookMove);\r
+       sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
        strcpy(bookMove, "move ");\r
        strcat(bookMove, bookHit);\r
@@ -3874,10 +3970,14 @@ SendMoveToICS(moveType, fromX, fromY, toX, toY)
       case BlackPromotionChancellor:\r
       case WhitePromotionArchbishop:\r
       case BlackPromotionArchbishop:\r
-        if(gameInfo.variant == VariantShatranj)\r
+        if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)\r
             sprintf(user_move, "%c%c%c%c=%c\n",\r
                 AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,\r
                PieceToChar(WhiteFerz));\r
+        else if(gameInfo.variant == VariantGreat)\r
+            sprintf(user_move, "%c%c%c%c=%c\n",\r
+                AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,\r
+               PieceToChar(WhiteMan));\r
         else\r
             sprintf(user_move, "%c%c%c%c=%c\n",\r
                 AAA + fromX, ONE + fromY, AAA + toX, ONE + toY,\r
@@ -4521,6 +4621,12 @@ InitPosition(redraw)
       pieces = fairyArray;\r
       SetCharTable(pieceToChar, "PNBRQFEACWMOHIJGDVSLUKpnbrqfeacwmohijgdvsluk"); \r
       break;\r
+    case VariantGreat:\r
+      pieces = GreatArray;\r
+      gameInfo.boardWidth = 10;\r
+      SetCharTable(pieceToChar, "PN....E...S..HWGMKpn....e...s..hwgmk");\r
+      gameInfo.holdingsSize = 8;\r
+      break;\r
     case VariantSuper:\r
       pieces = FIDEArray;\r
       SetCharTable(pieceToChar, "PNBRQ..SE.......V.AKpnbrq..se.......v.ak");\r
@@ -4619,6 +4725,12 @@ InitPosition(redraw)
      }\r
 \r
      if(gameInfo.variant == VariantSuper) Prelude(initialPosition);\r
+     if(gameInfo.variant == VariantGreat) { // promotion commoners\r
+       initialPosition[PieceToNumber(WhiteMan)][BOARD_RGHT-1] = WhiteMan;\r
+       initialPosition[PieceToNumber(WhiteMan)][BOARD_RGHT-2] = 9;\r
+       initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][0] = BlackMan;\r
+       initialPosition[BOARD_HEIGHT-1-PieceToNumber(WhiteMan)][1] = 9;\r
+     }\r
 #if 0\r
     if(gameInfo.variant == VariantFischeRandom) {\r
       if( appData.defaultFrcPosition < 0 ) {\r
@@ -5077,7 +5189,7 @@ UserMoveTest(fromX, fromY, toX, toY, promoChar)
             return ImpossibleMove;\r
        }\r
     }\r
-\r
+if(appData.debugMode) fprintf(debugFP, "moveType 3 = %d, promochar = %x\n", moveType, promoChar);\r
     return moveType;\r
     /* [HGM] <popupFix> in stead of calling FinishMove directly, this\r
        function is made into one that returns an OK move type if FinishMove\r
@@ -5096,8 +5208,8 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
      /*char*/int promoChar;\r
 {\r
     char *bookHit = 0;\r
-\r
-    if(gameInfo.variant == VariantSuper && promoChar != NULLCHAR) { \r
+if(appData.debugMode) fprintf(debugFP, "moveType 5 = %d, promochar = %x\n", moveType, promoChar);\r
+    if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) && promoChar != NULLCHAR) { \r
        // [HGM] superchess: suppress promotions to non-available piece\r
        int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));\r
        if(WhiteOnMove(currentMove)) {\r
@@ -5111,7 +5223,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
        move type in caller when we know the move is a legal promotion */\r
     if(moveType == NormalMove && promoChar)\r
         moveType = PromoCharToMoveType(WhiteOnMove(currentMove), promoChar);\r
-\r
+if(appData.debugMode) fprintf(debugFP, "moveType 1 = %d, promochar = %x\n", moveType, promoChar);\r
     /* [HGM] convert drag-and-drop piece drops to standard form */\r
     if( fromX == BOARD_LEFT-2 || fromX == BOARD_RGHT+1) {\r
          moveType = WhiteOnMove(currentMove) ? WhiteDrop : BlackDrop;\r
@@ -5175,7 +5287,8 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
 \r
   MakeMove(fromX, fromY, toX, toY, promoChar); /*updates forwardMostMove*/\r
 \r
-    if(gameInfo.variant == VariantSuper && promoChar != NULLCHAR && gameInfo.holdingsSize) { \r
+    if((gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) \r
+               && promoChar != NULLCHAR && gameInfo.holdingsSize) { \r
        // [HGM] superchess: take promotion piece out of holdings\r
        int k = PieceToNumber(CharToPiece(ToUpper(promoChar)));\r
        if(WhiteOnMove(forwardMostMove-1)) {\r
@@ -5206,7 +5319,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
     }\r
     ModeHighlight();\r
   }\r
-\r
+if(appData.debugMode) fprintf(debugFP, "moveType 2 = %d, promochar = %x\n", moveType, promoChar);\r
   /* Relay move to ICS or chess engine */\r
   if (appData.icsActive) {\r
     if (gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||\r
@@ -5267,7 +5380,7 @@ FinishMove(moveType, fromX, fromY, toX, toY, promoChar)
 \r
        programStats.depth = programStats.nodes = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
-       sprintf(programStats.movelist, "%s (xbook)", bookMove);\r
+       sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
        strcpy(bookMove, "move ");\r
        strcat(bookMove, bookHit);\r
@@ -5291,7 +5404,7 @@ UserMoveEvent(fromX, fromY, toX, toY, promoChar)
        to do anything in between, can call this routine the old way. \r
     */\r
     ChessMove moveType = UserMoveTest(fromX, fromY, toX, toY, promoChar);\r
-\r
+if(appData.debugMode) fprintf(debugFP, "moveType 4 = %d, promochar = %x\n", moveType, promoChar);\r
     if(moveType != ImpossibleMove)\r
         FinishMove(moveType, fromX, fromY, toX, toY, promoChar);\r
 }\r
@@ -5327,7 +5440,7 @@ char *SendMoveToBookUser(int moveNr, ChessProgramState *cps, int initial)
     //first determine if the incoming move brings opponent into his book\r
     if(appData.usePolyglotBook && (cps == &first ? !appData.firstHasOwnBookUCI : !appData.secondHasOwnBookUCI))\r
        bookHit = ProbeBook(moveNr+1, appData.polyglotBook); // returns move\r
-    if(appData.debugMode && bookHit) fprintf(debugFP, "book hit = %s\n", bookHit);\r
+    if(appData.debugMode) fprintf(debugFP, "book hit = %s\n", bookHit ? bookHit : "(NULL)");\r
     if(bookHit != NULL && !cps->bookSuspend) {\r
        // make sure opponent is not going to reply after receiving move to book position\r
        SendToProgram("force\n", cps);\r
@@ -5614,7 +5727,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
        if( gameMode == TwoMachinesPlay ) {\r
          // [HGM] some adjudications useful with buggy engines\r
             int k, count = 0, epFile = epStatus[forwardMostMove]; static int bare = 1;\r
-         if(gameInfo.holdingsSize == 0 || gameInfo.variant == VariantSuper) {\r
+         if(gameInfo.holdingsSize == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) {\r
 \r
             if(appData.testLegality)\r
             // don't wait for engine to announce game end if we can judge ourselves\r
@@ -5628,6 +5741,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
              case MT_STALEMATE:\r
                epStatus[forwardMostMove] = EP_STALEMATE;\r
                 if(appData.checkMates) {\r
+                   SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
                    ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
                    GameEnds( GameIsDrawn, "Xboard adjudication: Stalemate",\r
                        GE_XBOARD );\r
@@ -5636,6 +5750,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
              case MT_CHECKMATE:\r
                epStatus[forwardMostMove] = EP_CHECKMATE;\r
                 if(appData.checkMates) {\r
+                   SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
                    ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
                    GameEnds( WhiteOnMove(forwardMostMove) ? BlackWins : WhiteWins, \r
                    "Xboard adjudication: Checkmate", \r
@@ -5661,11 +5776,13 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                         case WhiteKnight:\r
                              NrWN++; break;\r
                         case WhiteBishop:\r
+                        case WhiteFerz:    // [HGM] shatranj: kludge to mke it work in shatranj\r
                              bishopsColor |= 1 << ((i^j)&1);\r
                              NrWB++; break;\r
                         case BlackKnight:\r
                              NrBN++; break;\r
                         case BlackBishop:\r
+                        case BlackFerz:    // [HGM] shatranj: kludge to mke it work in shatranj\r
                              bishopsColor |= 1 << ((i^j)&1);\r
                              NrBB++; break;\r
                         case WhiteRook:\r
@@ -5685,10 +5802,16 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                     }\r
                     NrPieces += (p != EmptySquare);\r
                     NrW += ((int)p < (int)BlackPawn);\r
+                   if(gameInfo.variant == VariantXiangqi && \r
+                     (p == WhiteFerz || p == WhiteAlfil || p == BlackFerz || p == BlackAlfil)) {\r
+                       NrPieces--; // [HGM] XQ: do not count purely defensive pieces\r
+                        NrW -= ((int)p < (int)BlackPawn);\r
+                   }\r
                 }\r
 \r
-                if( NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 || NrPieces == 2\r
-                 || NrPieces == 4 && NrBB+NrWB == NrPieces-2 && bishopsColor != 3)\r
+                if( NrPieces == 2 || gameInfo.variant != VariantXiangqi &&\r
+                       (NrPieces == 3 && NrWN+NrBN+NrWB+NrBB == 1 ||\r
+                        NrPieces == NrBB+NrWB+2 && bishopsColor != 3)) // [HGM] all Bishops (Ferz!) same color\r
                 {    /* KBK, KNK, KK of KBKB with like Bishops */\r
 \r
                      /* always flag draws, for judging claims */\r
@@ -5696,6 +5819,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
 \r
                      if(appData.materialDraws) {\r
                          /* but only adjudicate them if adjudication enabled */\r
+                        SendToProgram("force\n", cps->other); // suppress reply\r
+                        SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see last move */\r
                          ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
                          GameEnds( GameIsDrawn, "Xboard adjudication: Insufficient mating material", GE_XBOARD );\r
                          return;\r
@@ -5708,6 +5833,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
 \r
                      if(--bare < 0 && appData.checkMates) {\r
                          /* but only adjudicate them if adjudication enabled */\r
+                        SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
                          ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
                          GameEnds( NrW > 1 ? WhiteWins : NrPieces - NrW > 1 ? BlackWins : GameIsDrawn, \r
                                                        "Xboard adjudication: Bare king", GE_XBOARD );\r
@@ -5724,6 +5850,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                   ) ) {\r
                      if(--moveCount < 0 && appData.trivialDraws)\r
                      {    /* if the first 3 moves do not show a tactical win, declare draw */\r
+                         SendToProgram("force\n", cps->other); // suppress reply\r
+                         SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
                           ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
                           GameEnds( GameIsDrawn, "Xboard adjudication: Trivial draw", GE_XBOARD );\r
                           return;\r
@@ -5790,7 +5918,30 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                         if( rights == 0 && ++count > appData.drawRepeats-2\r
                             && appData.drawRepeats > 1) {\r
                              /* adjudicate after user-specified nr of repeats */\r
+                            SendToProgram("force\n", cps->other); // suppress reply\r
+                            SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
                              ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+                            if(gameInfo.variant == VariantXiangqi && appData.testLegality) { \r
+                               // [HGM] xiangqi: check for forbidden perpetuals\r
+                               int m, ourPerpetual = 1, hisPerpetual = 1;\r
+                               for(m=forwardMostMove; m>k; m-=2) {\r
+                                   if(MateTest(boards[m], PosFlags(m), \r
+                                                       EP_NONE, castlingRights[m]) != MT_CHECK)\r
+                                       ourPerpetual = 0; // the current mover did not always check\r
+                                   if(MateTest(boards[m-1], PosFlags(m-1), \r
+                                                       EP_NONE, castlingRights[m-1]) != MT_CHECK)\r
+                                       hisPerpetual = 0; // the opponent did not always check\r
+                               }\r
+                               if(ourPerpetual && !hisPerpetual) { // we are actively checking him: forfeit\r
+                                   GameEnds( WhiteOnMove(forwardMostMove) ? WhiteWins : BlackWins, \r
+                                          "Xboard adjudication: perpetual checking", GE_XBOARD );\r
+                                   return;\r
+                               }\r
+                               if(hisPerpetual && !ourPerpetual)   // he is checking us, but did not repeat yet\r
+                                   break; // (or we would have caught him before). Abort repetition-checking loop.\r
+                               // if neither of us is checking all the time, or both are, it is draw\r
+                               // (illegal-chase forfeits not implemented yet!)\r
+                            }\r
                              GameEnds( GameIsDrawn, "Xboard adjudication: repetition draw", GE_XBOARD );\r
                              return;\r
                         }\r
@@ -5812,6 +5963,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                          epStatus[forwardMostMove] = EP_RULE_DRAW;\r
                          /* this is used to judge if draw claims are legal */\r
                 if(appData.ruleMoves > 0 && count >= 2*appData.ruleMoves) {\r
+                        SendToProgram("force\n", cps->other); // suppress reply\r
+                        SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
                          ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
                          GameEnds( GameIsDrawn, "Xboard adjudication: 50-move rule", GE_XBOARD );\r
                          return;\r
@@ -5831,6 +5984,8 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                          if(epStatus[forwardMostMove] == EP_INSUF_DRAW)\r
                              p = "Draw claim: insufficient mating material";\r
                          if( p != NULL ) {\r
+                            SendToProgram("force\n", cps->other); // suppress reply\r
+                            SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
                              GameEnds( GameIsDrawn, p, GE_XBOARD );\r
                              ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
                              return;\r
@@ -5838,14 +5993,15 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                 }\r
 \r
 \r
-        }\r
-\r
-        if( appData.adjudicateDrawMoves > 0 && forwardMostMove > (2*appData.adjudicateDrawMoves) ) {\r
-           ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
+               if( appData.adjudicateDrawMoves > 0 && forwardMostMove > (2*appData.adjudicateDrawMoves) ) {\r
+                   SendToProgram("force\n", cps->other); // suppress reply\r
+                   SendMoveToProgram(forwardMostMove-1, cps->other); /* make sure opponent gets to see move */\r
+                   ShowMove(fromX, fromY, toX, toY); /*updates currentMove*/\r
 \r
-            GameEnds( GameIsDrawn, "Xboard adjudication: long game", GE_XBOARD );\r
+                   GameEnds( GameIsDrawn, "Xboard adjudication: long game", GE_XBOARD );\r
 \r
-            return;\r
+                   return;\r
+               }\r
         }\r
 \r
        bookHit = NULL;\r
@@ -5895,7 +6051,7 @@ FakeBookMove: // [HGM] book: we jump here to simulate machine moves after book h
                cps = cps->other;\r
                programStats.depth = programStats.nodes = programStats.time = \r
                programStats.score = programStats.got_only_move = 0;\r
-               sprintf(programStats.movelist, "%s (xbook)", bookMove);\r
+               sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
                if(cps->lastPing != cps->lastPong) {\r
                    savedMessage = message; // args for deferred call\r
@@ -6836,24 +6992,28 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
            epStatus[p] = EP_CAPTURE;  \r
 \r
       if( board[fromY][fromX] == WhitePawn ) {\r
-           epStatus[p] = EP_PAWN_MOVE; \r
-           if( toY-fromY==2)\r
+           if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers\r
+              epStatus[p] = EP_PAWN_MOVE;\r
+           if( toY-fromY==2) {\r
                if(toX>BOARD_LEFT   && board[toY][toX-1] == BlackPawn &&\r
                        gameInfo.variant != VariantBerolina || toX < fromX)\r
                      epStatus[p] = toX | berolina;\r
                if(toX<BOARD_RGHT-1 && board[toY][toX+1] == BlackPawn &&\r
                        gameInfo.variant != VariantBerolina || toX > fromX) \r
                      epStatus[p] = toX;\r
+          }\r
       } else \r
       if( board[fromY][fromX] == BlackPawn ) {\r
-           epStatus[p] = EP_PAWN_MOVE; \r
-           if( toY-fromY== -2)\r
+           if(fromY != toY) // [HGM] Xiangqi sideway Pawn moves should not count as 50-move breakers\r
+              epStatus[p] = EP_PAWN_MOVE; \r
+           if( toY-fromY== -2) {\r
                if(toX>BOARD_LEFT   && board[toY][toX-1] == WhitePawn &&\r
                        gameInfo.variant != VariantBerolina || toX < fromX)\r
                      epStatus[p] = toX | berolina;\r
                if(toX<BOARD_RGHT-1 && board[toY][toX+1] == WhitePawn &&\r
                        gameInfo.variant != VariantBerolina || toX > fromX) \r
                      epStatus[p] = toX;\r
+          }\r
        }\r
 \r
        for(i=0; i<nrCastlingRights; i++) {\r
@@ -7051,7 +7211,7 @@ ApplyMove(fromX, fromY, toX, toY, promoChar, board)
       if (captured != EmptySquare && gameInfo.holdingsSize > 0\r
           && gameInfo.variant != VariantBughouse        ) {\r
         /* [HGM] holdings: Add to holdings, if holdings exist */\r
-       if(gameInfo.variant == VariantSuper) { \r
+       if(gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) { \r
                // [HGM] superchess: suppress flipping color of captured pieces by reverse pre-flip\r
                captured = (int) captured >= (int) BlackPawn ? BLACK_TO_WHITE captured : WHITE_TO_BLACK captured;\r
        }\r
@@ -7308,6 +7468,8 @@ InitChessProgram(cps, setup)
            overruled = gameInfo.boardWidth != 12 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 0;\r
       if( gameInfo.variant == VariantSuper )\r
            overruled = gameInfo.boardWidth != 8 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8;\r
+      if( gameInfo.variant == VariantGreat )\r
+           overruled = gameInfo.boardWidth != 10 || gameInfo.boardHeight != 8 || gameInfo.holdingsSize != 8;\r
 \r
       if(overruled) {\r
            sprintf(b, "%dx%d+%d_%s", gameInfo.boardWidth, gameInfo.boardHeight, \r
@@ -7408,6 +7570,8 @@ StartChessProgram(cps)
     cps->isr = AddInputSource(cps->pr, TRUE, ReceiveFromProgram, cps);\r
     if (cps->protocolVersion > 1) {\r
       sprintf(buf, "xboard\nprotover %d\n", cps->protocolVersion);\r
+      cps->nrOptions = 0; // [HGM] options: clear all engine-specific options\r
+      cps->comboCnt = 0;  //                and values of combo boxes\r
       SendToProgram(buf, cps);\r
     } else {\r
       SendToProgram("xboard\n", cps);\r
@@ -7545,7 +7709,7 @@ GameEnds(result, resultDetails, whosays)
                 claimer = whosays == GE_ENGINE1 ?      /* color of claimer */\r
                                             first.twoMachinesColor[0] :\r
                                             second.twoMachinesColor[0] ;\r
-                if( (gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper) &&\r
+                if( (gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat) &&\r
                     (result == WhiteWins && claimer == 'w' ||\r
                      result == BlackWins && claimer == 'b'   ) ) {\r
                if (appData.debugMode) {\r
@@ -7573,7 +7737,8 @@ GameEnds(result, resultDetails, whosays)
                 /* (Claiming a loss is accepted no questions asked!) */\r
            }\r
            /* [HGM] bare: don't allow bare King to win */\r
-           if((gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper) && result != GameIsDrawn)\r
+           if((gameInfo.holdingsWidth == 0 || gameInfo.variant == VariantSuper || gameInfo.variant == VariantGreat)\r
+                        && result != GameIsDrawn)\r
            {   int i, j, k=0, color = (result==WhiteWins ? (int)WhitePawn : (int)BlackPawn);\r
                for(j=BOARD_LEFT; j<BOARD_RGHT; j++) for(i=0; i<BOARD_HEIGHT; i++) {\r
                        int p = (int)boards[forwardMostMove][i][j] - color;\r
@@ -7905,6 +8070,7 @@ Reset(redraw, init)
     ics_gamenum = -1;\r
     white_holding[0] = black_holding[0] = NULLCHAR;\r
     ClearProgramStats();\r
+    opponentKibitzes = FALSE; // [HGM] kibitz: do not reserve space in engine-output window in zippy mode\r
     \r
     ResetFrontEnd();\r
     ClearHighlights();\r
@@ -10184,6 +10350,7 @@ MachineWhiteEvent()
     if (appData.autoFlipView && !flipView) {\r
       flipView = !flipView;\r
       DrawPosition(FALSE, NULL);\r
+      DisplayBothClocks();       // [HGM] logo: clocks might have to be exchanged;\r
     }\r
 \r
     if(bookHit) { // [HGM] book: simulate book reply\r
@@ -10191,7 +10358,7 @@ MachineWhiteEvent()
 \r
        programStats.depth = programStats.nodes = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
-       sprintf(programStats.movelist, "%s (xbook)", bookMove);\r
+       sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
        strcpy(bookMove, "move ");\r
        strcat(bookMove, bookHit);\r
@@ -10259,13 +10426,14 @@ MachineBlackEvent()
     if (appData.autoFlipView && flipView) {\r
       flipView = !flipView;\r
       DrawPosition(FALSE, NULL);\r
+      DisplayBothClocks();       // [HGM] logo: clocks might have to be exchanged;\r
     }\r
     if(bookHit) { // [HGM] book: simulate book reply\r
        static char bookMove[MSG_SIZ]; // a bit generous?\r
 \r
        programStats.depth = programStats.nodes = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
-       sprintf(programStats.movelist, "%s (xbook)", bookMove);\r
+       sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
        strcpy(bookMove, "move ");\r
        strcat(bookMove, bookHit);\r
@@ -10411,7 +10579,7 @@ TwoMachinesEvent P((void))
 \r
        programStats.depth = programStats.nodes = programStats.time = \r
        programStats.score = programStats.got_only_move = 0;\r
-       sprintf(programStats.movelist, "%s (xbook)", bookMove);\r
+       sprintf(programStats.movelist, "%s (xbook)", bookHit);\r
 \r
        strcpy(bookMove, "move ");\r
        strcat(bookMove, bookHit);\r
@@ -12082,6 +12250,55 @@ StringFeature(p, name, loc, cps)
   return FALSE;\r
 }\r
 \r
+int \r
+ParseOption(Option *opt, ChessProgramState *cps)\r
+// [HGM] options: process the string that defines an engine option, and determine\r
+// name, type, default value, and allowed value range\r
+{\r
+       char *p, *q, buf[MSG_SIZ];\r
+       int n, min = (-1)<<31, max = 1<<31, def;\r
+\r
+       if(p = strstr(opt->name, " -spin ")) {\r
+           if((n = sscanf(p, " -spin %d %d %d", &def, &min, &max)) < 3 ) return FALSE;\r
+           if(max < min) max = min; // enforce consistency\r
+           if(def < min) def = min;\r
+           if(def > max) def = max;\r
+           opt->value = def;\r
+           opt->min = min;\r
+           opt->max = max;\r
+           opt->type = Spin;\r
+       } else if(p = strstr(opt->name, " -string ")) {\r
+           opt->textValue = p+9;\r
+           opt->type = TextBox;\r
+       } else if(p = strstr(opt->name, " -check ")) {\r
+           if(sscanf(p, " -check %d", &def) < 1) return FALSE;\r
+           opt->value = (def != 0);\r
+           opt->type = CheckBox;\r
+       } else if(p = strstr(opt->name, " -combo ")) {\r
+           opt->textValue = (char*) (&cps->comboList[cps->comboCnt]); // cheat with pointer type\r
+           cps->comboList[cps->comboCnt++] = q = p+8; // holds possible choices\r
+           opt->value = n = 0;\r
+           while(q = StrStr(q, " /// ")) {\r
+               n++; *q = 0;    // count choices, and null-terminate each of them\r
+               q += 5;\r
+               if(*q == '*') { // remember default, which is marked with * prefix\r
+                   q++;\r
+                   opt->value = n;\r
+               }\r
+               cps->comboList[cps->comboCnt++] = q;\r
+           }\r
+           cps->comboList[cps->comboCnt++] = NULL;\r
+           opt->max = n + 1;\r
+           opt->type = ComboBox;\r
+       } else if(p = strstr(opt->name, " -button")) {\r
+           opt->type = Button;\r
+       } else if(p = strstr(opt->name, " -save")) {\r
+           opt->type = SaveButton;\r
+       } else return FALSE;\r
+       *p = 0; // terminate option name\r
+       return TRUE;\r
+}\r
+\r
 void\r
 FeatureDone(cps, val)\r
      ChessProgramState* cps;\r
@@ -12155,6 +12372,16 @@ ParseFeatures(args, cps)
     if (BoolFeature(&p, "memory", &cps->memSize, cps)) continue;\r
     if (BoolFeature(&p, "smp", &cps->maxCores, cps)) continue;\r
     if (StringFeature(&p, "egt", &cps->egtFormats, cps)) continue;\r
+    if (StringFeature(&p, "option", &(cps->option[cps->nrOptions].name), cps)) {\r
+       ParseOption(&(cps->option[cps->nrOptions++]), cps); // [HGM] options: add option feature\r
+       if(cps->nrOptions >= MAX_OPTIONS) {\r
+           cps->nrOptions--;\r
+           sprintf(buf, "%s engine has too many options\n", cps->which);\r
+           DisplayError(buf, 0);\r
+       }\r
+       continue;\r
+    }\r
+    if (BoolFeature(&p, "smp", &cps->maxCores, cps)) continue;\r
     /* End of additions by HGM */\r
 \r
     /* unknown feature: complain and skip */\r
index 995890d..eba5366 100644 (file)
--- a/backend.h
+++ b/backend.h
@@ -206,6 +206,19 @@ char * GameListLineFull P(( int, GameInfo *));
 extern char* StripHighlight P((char *));  /* returns static data */\r
 extern char* StripHighlightAndTitle P((char *));  /* returns static data */\r
 \r
+typedef enum { CheckBox, ComboBox, TextBox, Button, Spin, SaveButton } Control;\r
+\r
+typedef struct _OPT {   // [HGM] options: descriptor of UCI-style option\r
+    int value;          // current setting, starts as default\r
+    int min;\r
+    int max;\r
+    void *handle;       // for use by front end\r
+    char *textValue;    // points to beginning of text value in name field\r
+    char **choice;      // points to array of combo choices in cps->combo\r
+    Control type;\r
+    char name[MSG_SIZ]; // holds both option name and text value\r
+} Option;\r
+\r
 typedef struct _CPS {\r
     char *which;\r
     int maybeThinking;\r
@@ -263,8 +276,14 @@ typedef struct _CPS {
     int alphaRank;    /* [HGM] shogi: engine uses shogi-type coordinates    */\r
     int maxCores;     /* [HGM] SMP: engine understands cores command        */\r
     int memSize;      /* [HGM] memsize: engine understands memory command   */\r
-    char egtFormats[MSG_SIZ];     /* [HGM] EGT: supported tablebase formats */
-    int bookSuspend;  /* HGM book: go was deferred bcause of book hit       */\r
+    char egtFormats[MSG_SIZ];     /* [HGM] EGT: supported tablebase formats */\r
+    int bookSuspend;  /* [HGM] book: go was deferred because of book hit    */\r
+    int nrOptions;    /* [HGM] options: remembered option="..." features    */\r
+#define MAX_OPTIONS 50\r
+    Option option[MAX_OPTIONS];\r
+    int comboCnt;\r
+    char *comboList[10*MAX_OPTIONS];\r
+    void *programLogo; /* [HGM] logo: bitmap of the logo                    */\r
 } ChessProgramState;\r
 \r
 extern ChessProgramState first, second;\r
@@ -276,7 +295,25 @@ typedef struct {
     int time;   /* Milliseconds */\r
 } ChessProgramStats_Move;\r
 \r
+/* Search stats from chessprogram */\r
+typedef struct {\r
+  char movelist[2*MSG_SIZ]; /* Last PV we were sent */\r
+  int depth;              /* Current search depth */\r
+  int nr_moves;           /* Total nr of root moves */\r
+  int moves_left;         /* Moves remaining to be searched */\r
+  char move_name[MOVE_LEN];  /* Current move being searched, if provided */\r
+  unsigned long nodes;    /* # of nodes searched */\r
+  int time;               /* Search time (centiseconds) */\r
+  int score;              /* Score (centipawns) */\r
+  int got_only_move;      /* If last msg was "(only move)" */\r
+  int got_fail;           /* 0 - nothing, 1 - got "--", 2 - got "++" */\r
+  int ok_to_send;         /* handshaking between send & recv */\r
+  int line_is_book;       /* 1 if movelist is book moves */\r
+  int seen_stat;          /* 1 if we've seen the stat01: line */\r
+} ChessProgramStats;\r
+\r
 extern ChessProgramStats_Move pvInfoList[MAX_MOVES];\r
 extern shuffleOpenings;\r
+extern ChessProgramStats programStats;\r
 \r
 #endif /* _BACKEND */\r
index 6d8a6ec..8263d63 100644 (file)
--- a/common.h
+++ b/common.h
@@ -286,6 +286,7 @@ typedef enum {
     VariantBerolina,\r
     VariantJanus,\r
     VariantSuper,\r
+    VariantGreat,\r
     VariantUnknown       /* Catchall for other unknown variants */\r
 } VariantClass;\r
 \r
@@ -326,6 +327,7 @@ typedef enum {
   "berolina",\\r
   "janus",\\r
   "super",\\r
+  "great",\\r
   "unknown" \\r
 }\r
 \r
@@ -575,8 +577,12 @@ typedef struct {
     char *userName;\r
     int rewindIndex;    /* [HGM] autoinc   */\r
     int sameColorGames; /* [HGM] alternate */\r
-    int smpCores;\r
+    int smpCores;       /* [HGM] SMP       */\r
     char *egtFormats;\r
+    int niceEngines;    /* [HGM] nice      */\r
+    char *firstLogo;    /* [HGM] logo      */\r
+    char *secondLogo;\r
+    Boolean autoLogo;\r
 } AppData, *AppDataPtr;\r
 \r
 /* [AS] PGN tags (for showing in the game list) */\r
old mode 100644 (file)
new mode 100755 (executable)
index 631b067..335b730
--- a/configure
+++ b/configure
@@ -4673,7 +4673,7 @@ fi
 
 PRODUCT=xboard
 #VERSION=4.3  # version is already defined
-PATCHLEVEL=15
+PATCHLEVEL=16
 
 
 if test -z "$CFLAGS" ; then
index b2cd121..13e1719 100644 (file)
@@ -1019,8 +1019,8 @@ the engine has to decide for itself
 how to divide up the available memory between the various tables it wants to use \r
 (e.g. main hash, pawn hash, tablebase cache, bitbases).\r
 This command will only be sent to engines that have requested it through the memory feature,\r
-and only at the beginning of a game\r
-(before any moves have been done).\r
+and only at the start of a game,\r
+as the first of the commands to relay engine option settings just before each "new" command.\r
 </font>\r
 <p>\r
 \r
@@ -1032,7 +1032,9 @@ This could be interpreted as the number of search threads for SMP engines.
 This command will only be sent to engines that have requested it through the smp feature.\r
 The engine should be able to respond to the "cores" command any time during a game,\r
 but it is allowed to finish a search in progress before procesing the command.\r
-(Reaction during ponder time should be immediate, though.)\r
+(Obeying the command should take priority over finishing a ponder search, though.)\r
+In any case it will be sent at the start of every game\r
+as the last command to relay engine option settings before the "new" command.\r
 </font>\r
 <p>\r
 \r
@@ -1052,6 +1054,7 @@ but could also be the name of a file, or in fact anything the particular EGT typ
 It is upto the developer of the EGT format to specify the syntax of this parameter.\r
 This command will only be sent to engines that have told the GUI they support EGTs of the given TYPE\r
 through the egt feature.\r
+It will be sent at the start of each game, before the "new" command.\r
 </font>\r
 </dl>\r
 \r
@@ -1391,6 +1394,8 @@ will be set by the GUI through the "memory" command.
 </font>\r
 <dd><font color=blue>\r
 If smp=1, the GUI will send the "cores" command to the engine to inform it how many CPU cores it can use.\r
+Note that sending smp=1 does not imply the engine can use more than one CPU;\r
+just that it wants to receive the "cores" command.\r
 </font>\r
 \r
 <dt><font color=blue>\r
diff --git a/moves.c b/moves.c
index 0def075..58cbfc0 100644 (file)
--- a/moves.c
+++ b/moves.c
@@ -169,7 +169,8 @@ ChessMove PromoCharToMoveType(whiteOnMove, promoChar)
      int whiteOnMove;\r
      int promoChar;\r
 {      /* [HGM] made dependent on CharToPiece to alow alternate piece letters */\r
-       ChessSquare piece = CharToPiece(whiteOnMove ? ToUpper(promoChar) : ToLower(promoChar) );\r
+       ChessSquare piece = CharToPiece(whiteOnMove ? ToUpper(promoChar) : ToLower(promoChar) );
+       if(promoChar == NULLCHAR) return NormalMove;\r
 \r
        switch(piece) {\r
                case WhiteQueen:\r
@@ -577,7 +578,7 @@ void GenPseudoLegal(board, flags, epfile, callback, closure)
                      if (board[rt][ft] != EmptySquare) break;\r
                  }\r
                 if(m==1) goto mounted;\r
-                if(m==2) goto walking;\r
+                if(m==2) goto finishGold;\r
              break;\r
 \r
            case WhiteQueen:\r
@@ -1265,7 +1266,7 @@ void Disambiguate(board, flags, epfile, closure)
 #endif\r
     /* [HGM] returns 'q' for optional promotion, 'n' for mandatory */\r
     if(closure->promoCharIn != '=')\r
-        closure->promoChar = ToLower(PieceToChar(PromoPiece(closure->kind)));\r
+        closure->promoChar = ToLower(closure->promoCharIn);\r
     else closure->promoChar = '=';\r
     if (closure->promoChar == 'x') closure->promoChar = NULLCHAR;\r
     if (closure->count > 1) {\r
@@ -1280,7 +1281,7 @@ void Disambiguate(board, flags, epfile, closure)
     }\r
     if(closure->kind == IllegalMove)\r
     /* [HGM] might be a variant we don't understand, pass on promotion info */\r
-        closure->promoChar = closure->promoCharIn;\r
+        closure->promoChar = ToLower(closure->promoCharIn);\r
     if (appData.debugMode) {\r
         fprintf(debugFP, "Disambiguate out: %d(%d,%d)-(%d,%d) = %d (%c)\n",\r
         closure->piece,closure->ff,closure->rf,closure->ft,closure->rt,closure->promoChar,\r
index 58282bd..27d1a13 100644 (file)
--- a/parser.c
+++ b/parser.c
@@ -2278,6 +2278,8 @@ YY_RULE_SETUP
          result == WhitePromotionQueen  || result == BlackPromotionQueen)) {
         if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)
             currentMoveString[4] = PieceToChar(BlackFerz);
+        else if(gameInfo.variant == VariantGreat)
+            currentMoveString[4] = PieceToChar(BlackMan);
         else
             currentMoveString[4] = PieceToChar(BlackQueen);
        currentMoveString[5] = NULLCHAR;
@@ -2427,7 +2429,6 @@ YY_RULE_SETUP
 
     if (gameInfo.variant == VariantXiangqi && /* [HGM] In Xiangqi rank stays same */
          currentMoveString[0] != currentMoveString[2] ) {
-        if (yytext[2+skip] == ONE) return (int) ImpossibleMove;
         currentMoveString[1] = yytext[2+skip];
     } else 
     if (WhiteOnMove(yyboardindex)) {
@@ -2462,6 +2463,11 @@ YY_RULE_SETUP
         (result == WhitePromotionQueen  || result == BlackPromotionQueen ||
          result == WhitePromotionKnight || result == BlackPromotionKnight)) {
         currentMoveString[4] = PieceToChar(BlackQueen);
+       // [HGM] shatranj: take care of variants without Queen
+       if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)
+            currentMoveString[4] = PieceToChar(BlackFerz);
+       if(gameInfo.variant == VariantGreat)
+            currentMoveString[4] = PieceToChar(BlackMan);
        currentMoveString[5] = NULLCHAR;
     }
 
old mode 100644 (file)
new mode 100755 (executable)
index 41feced..48e78f3
--- a/parser.l
+++ b/parser.l
@@ -304,6 +304,8 @@ extern void CopyBoard P((Board to, Board from));
          result == WhitePromotionQueen  || result == BlackPromotionQueen)) {\r
         if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)\r
             currentMoveString[4] = PieceToChar(BlackFerz);\r
+        else if(gameInfo.variant == VariantGreat)\r
+            currentMoveString[4] = PieceToChar(BlackMan);\r
         else\r
             currentMoveString[4] = PieceToChar(BlackQueen);\r
        currentMoveString[5] = NULLCHAR;\r
@@ -448,7 +450,6 @@ extern void CopyBoard P((Board to, Board from));
 \r
     if (gameInfo.variant == VariantXiangqi && /* [HGM] In Xiangqi rank stays same */\r
          currentMoveString[0] != currentMoveString[2] ) {\r
-        if (yytext[2+skip] == ONE) return (int) ImpossibleMove;\r
         currentMoveString[1] = yytext[2+skip];\r
     } else \r
     if (WhiteOnMove(yyboardindex)) {\r
@@ -483,6 +484,11 @@ extern void CopyBoard P((Board to, Board from));
         (result == WhitePromotionQueen  || result == BlackPromotionQueen ||\r
          result == WhitePromotionKnight || result == BlackPromotionKnight)) {\r
         currentMoveString[4] = PieceToChar(BlackQueen);\r
+       // [HGM] shatranj: take care of variants without Queen\r
+       if(gameInfo.variant == VariantShatranj || gameInfo.variant == VariantCourier)\r
+            currentMoveString[4] = PieceToChar(BlackFerz);\r
+       if(gameInfo.variant == VariantGreat)\r
+            currentMoveString[4] = PieceToChar(BlackMan);\r
        currentMoveString[5] = NULLCHAR;\r
     }\r
 \r
old mode 100644 (file)
new mode 100755 (executable)
index bc657f5..32aceb1 100644 (file)
@@ -36,7 +36,7 @@
 \r
 #define LAST_PTY_LETTER 'q'\r
 \r
-#define PATCHLEVEL "15m"\r
+#define PATCHLEVEL "15k"\r
 \r
 #define PRODUCT "WinBoard"\r
 \r
index cb4781e..833d169 100644 (file)
@@ -1,97 +1,96 @@
-#\r
-# Makefile for WinBoard, using the GNU Cygwin toolset\r
-#\r
-\r
-# Uncomment both lines to turn on debugging symbols #######\r
-cdebug= -g\r
-linkdebug= -g\r
-#######################################################\r
-\r
-proj=winboard\r
-allobj=  winboard.o backend.o parser.o moves.o lists.o \\r
-        gamelist.o pgntags.o wedittags.o wgamelist.o zippy.o \\r
-        wsockerr.o wbres.o wclipbrd.o woptions.o uci.o \\r
-        wengineo.o wevalgraph.o whistory.o wlayout.o \\r
-        wplugin.o wsnap.o book.o\r
-\r
-dotc=   winboard.c backend.c parser.c moves.c lists.c \\r
-       gamelist.c pgntags.c wedittags.c wgamelist.c zippy.c \\r
-       wsockerr.c winboard.rc wclipbrd.c woptions.c uci.c \\r
-       wengineo.c wevalgraph.c whistory.c wlayout.c \\r
-       wplugin.c wsnap.c book.c\r
-\r
-# Currently WinBoard will build either with or without -mno-cygwin\r
-# however, a Cygwin bug in forming the command line to WinMain() is\r
-# exposed if -mno-cygwin is not used.\r
-cygwin= -mno-cygwin\r
-\r
-VPATH= .:..\r
-CFLAGS= $(cdebug)\r
-INCLUDES= -I. -I..\r
-CVARS= $(INCLUDES) $(cygwin)\r
-CC = gcc $(CVARS)\r
-WCC = $(CC) -mwindows $(linkdebug)\r
-HC="/c/program files/help workshop/hcrtf.exe" -xn\r
-\r
-all: $(proj).exe\r
-\r
-depend: $(dotc)\r
-       makedepend -Y -f cygwin.mak $(INCLUDES) $^\r
-\r
-clean:\r
-       rm -f *.obj *~ $(proj).exe $(proj).err $(proj).rbj \\r
-               $(proj).RES $(proj).res $(proj).ini *.sbr *.bsc *.o \\r
-               *.plg *.opt *.ncb *.debug *.bak *.gid *.GID\r
-\r
-maintainer-clean: clean\r
-       rm -f parser.c *.hlp *.HLP\r
-\r
-# Update the help file if necessary\r
-#$(proj).hlp : $(proj).rtf\r
-#      $(HC) $(proj).hpj\r
-#      cat $(proj).err\r
-\r
-# Update the resource if necessary\r
-wbres.o: $(proj).rc $(proj).h resource.h\r
-       windres --use-temp-file --include-dir .. $< -O coff -o $@\r
-\r
-# Update the object files if necessary\r
-\r
-parser.c: parser.l\r
-       flex -oparser.c -L $<\r
-\r
-#$(proj).exe: $(allobj) $(proj).hlp $(proj).rc\r
-$(proj).exe: $(allobj) $(proj).rc\r
-       $(WCC) $(guiflags) $(allobj) \\r
-       -lwsock32 -lwinmm \\r
-       -o $(proj).exe\r
-\r
-# DO NOT DELETE\r
-\r
-winboard.o: config.h ../common.h winboard.h resource.h ../frontend.h\r
-winboard.o: ../backend.h ../lists.h ../moves.h wclipbrd.h wgamelist.h\r
-winboard.o: wedittags.h woptions.h wsockerr.h defaults.h\r
-backend.o: config.h ../common.h ../frontend.h ../backend.h ../lists.h\r
-backend.o: ../parser.h ../moves.h ../zippy.h ../backendz.h\r
-parser.o: config.h ../common.h ../backend.h ../lists.h ../frontend.h\r
-parser.o: ../parser.h ../moves.h\r
-moves.o: config.h ../common.h ../backend.h ../lists.h ../frontend.h\r
-moves.o: ../moves.h ../parser.h\r
-lists.o: config.h ../common.h ../lists.h\r
-gamelist.o: config.h ../common.h ../frontend.h ../backend.h ../lists.h\r
-gamelist.o: ../parser.h\r
-pgntags.o: config.h ../common.h ../frontend.h ../backend.h ../lists.h\r
-pgntags.o: ../parser.h\r
-wedittags.o: config.h ../common.h winboard.h resource.h ../frontend.h\r
-wedittags.o: ../backend.h ../lists.h\r
-wgamelist.o: config.h ../common.h winboard.h resource.h ../frontend.h\r
-wgamelist.o: ../backend.h ../lists.h\r
-zippy.o: config.h ../common.h ../zippy.h ../frontend.h ../backend.h\r
-zippy.o: ../lists.h ../backendz.h\r
-wsockerr.o: wsockerr.h\r
-winboard.o: resource.h\r
-wclipbrd.o: config.h ../common.h winboard.h resource.h ../frontend.h\r
-wclipbrd.o: ../backend.h ../lists.h wclipbrd.h\r
-woptions.o: config.h ../common.h winboard.h resource.h ../backend.h\r
-woptions.o: ../lists.h ../frontend.h woptions.h defaults.h wedittags.h\r
+#
+# Makefile for WinBoard, using the GNU Cygwin toolset
+#
+
+# Uncomment both lines to turn on debugging symbols #######
+cdebug= -g
+linkdebug= -g
+#######################################################
+
+proj=winboard
+allobj=  winboard.o backend.o parser.o moves.o lists.o \
+        gamelist.o pgntags.o wedittags.o wgamelist.o zippy.o \
+        wsockerr.o wbres.o wclipbrd.o woptions.o uci.o \
+        wengineo.o wevalgraph.o whistory.o wlayout.o \
+        wplugin.o wsnap.o book.o
+
+dotc=   winboard.c backend.c parser.c moves.c lists.c \
+       gamelist.c pgntags.c wedittags.c wgamelist.c zippy.c \
+       wsockerr.c winboard.rc wclipbrd.c woptions.c uci.c \
+       wengineo.c wevalgraph.c whistory.c wlayout.c \
+       wplugin.c wsnap.c book.c
+
+# Currently WinBoard will build either with or without -mno-cygwin
+# however, a Cygwin bug in forming the command line to WinMain() is
+# exposed if -mno-cygwin is not used.
+cygwin= -mno-cygwin
+
+VPATH= .:..
+CFLAGS= $(cdebug)
+INCLUDES= -I. -I..
+CVARS= $(INCLUDES) $(cygwin)
+CC = gcc $(CVARS)
+WCC = $(CC) -mwindows $(linkdebug)
+HC="/c/program files/help workshop/hcrtf.exe" -xn
+
+all: $(proj).exe
+
+depend: $(dotc)
+       makedepend -Y -f cygwin.mak $(INCLUDES) $^
+
+clean:
+       rm -f *.obj *~ $(proj).exe $(proj).err $(proj).rbj \
+               $(proj).RES $(proj).res $(proj).ini *.sbr *.bsc *.o \
+               *.plg *.opt *.ncb *.debug *.bak *.gid *.GID
+
+maintainer-clean: clean
+       rm -f parser.c *.hlp *.HLP
+
+# Update the help file if necessary
+#$(proj).hlp : $(proj).rtf
+#      $(HC) $(proj).hpj
+#      cat $(proj).err
+
+# Update the resource if necessary
+wbres.o: $(proj).rc $(proj).h resource.h
+       windres --use-temp-file --include-dir .. $< -O coff -o $@
+
+# Update the object files if necessary
+
+parser.c: parser.l
+       flex -oparser.c -L $<
+
+$(proj).exe: $(allobj) $(proj).hlp $(proj).rc
+       $(WCC) $(guiflags) $(allobj) \
+       -lwsock32 -lwinmm \
+       -o $(proj).exe
+
+# DO NOT DELETE
+
+winboard.o: config.h ../common.h winboard.h resource.h ../frontend.h
+winboard.o: ../backend.h ../lists.h ../moves.h wclipbrd.h wgamelist.h
+winboard.o: wedittags.h woptions.h wsockerr.h defaults.h
+backend.o: config.h ../common.h ../frontend.h ../backend.h ../lists.h
+backend.o: ../parser.h ../moves.h ../zippy.h ../backendz.h
+parser.o: config.h ../common.h ../backend.h ../lists.h ../frontend.h
+parser.o: ../parser.h ../moves.h
+moves.o: config.h ../common.h ../backend.h ../lists.h ../frontend.h
+moves.o: ../moves.h ../parser.h
+lists.o: config.h ../common.h ../lists.h
+gamelist.o: config.h ../common.h ../frontend.h ../backend.h ../lists.h
+gamelist.o: ../parser.h
+pgntags.o: config.h ../common.h ../frontend.h ../backend.h ../lists.h
+pgntags.o: ../parser.h
+wedittags.o: config.h ../common.h winboard.h resource.h ../frontend.h
+wedittags.o: ../backend.h ../lists.h
+wgamelist.o: config.h ../common.h winboard.h resource.h ../frontend.h
+wgamelist.o: ../backend.h ../lists.h
+zippy.o: config.h ../common.h ../zippy.h ../frontend.h ../backend.h
+zippy.o: ../lists.h ../backendz.h
+wsockerr.o: wsockerr.h
+winboard.o: resource.h
+wclipbrd.o: config.h ../common.h winboard.h resource.h ../frontend.h
+wclipbrd.o: ../backend.h ../lists.h wclipbrd.h
+woptions.o: config.h ../common.h winboard.h resource.h ../backend.h
+woptions.o: ../lists.h ../frontend.h woptions.h defaults.h wedittags.h
 book.o: ../common.h ../backend.h
\ No newline at end of file
index 8ebc2ca..b22e6b4 100644 (file)
@@ -1,34 +1,3 @@
-                             WinBoard 4.3.15m RELEASE NOTES\r
-\r
-Compared to version 4.3.14k described below, this version features\r
-\r
-New command-line options\r
-/rewindIndex=N (for the new auto-increment mode of the loadGameIndex or loadPositionIndex in match mode\r
-/sameColorGames=N (for playing a match where the same player has white all the time)\r
-/egtFormats="..." (for specifying where various end-game tables are installed on the computer)\r
-\r
-New menu items\r
-+ Time-odds factors can be set in the time-control dialog\r
-+ Nr of CPUs for SMP engines can be set in the Options -> UCI dialog\r
-+ Own-Book options can be switched from the Options -> UCI dialog\r
-+ The ScoreIsAbs options can be set from the Options -> Engine dialog\r
-+ New-Variant menu adds Superchess\r
-\r
-General Enhancements:\r
-* WinBoard engines can now also use the Polyglot opening book (implemented as general GUI book)\r
-* New WB-protocol commands memory, cores and egtpath make interactive setting of these parameters \r
-  possible on WB engines\r
-* New Polyglot is available that relays the interactive setting of these parameters to UCI engines\r
-* Match mode suports an auto-increment mode, so that all games or positions from a file can be played\r
-* Draw claims with Kings and an arbitrary number of like Bishops (e.g. KBBKB) are accepted\r
-\r
-The source tree in original XBoard 4.2.7 format can now be compiled under Cygwin with the aid\r
-of the cygwin.mak file in the ~/winboard/ subdirectory of the source release. Makefiles for \r
-other compilers are not updated since 4.2.7, as I do not have those compilers.\r
-\r
-Note that this release is a bug-fix for the 4.3.15k release, which had a bug in human-ICS play mode.\r
-\r
-\r
                              WinBoard 4.3.14k RELEASE NOTES\r
 \r
 Compared to version 4.3.13 described below, this version features\r
@@ -52,7 +21,7 @@ Bugfixes:
 * In ICS observing mode game history is now fully accessible \r
 * Moves are not fed to engine in zippy mode, when observing a game from a variant unknown to the engine \r
 * a problem with loading PGN of FRC games with move disambiguation and initial castling rights was fixed.\r
-* A bug in the clock display that made previous versions of WinBoard crash for tiny displays is fixed\r
+* A bug in the clock display that mad previous versions of WinBoard crash for tiny displays is fixed\r
 \r
 General enhancements: \r
 * variant name displayed in title bar in ICS mode, when not 'normal' \r
index 0623e3d..994af41 100644 (file)
-/*\r
- * Engine output (PV)\r
- *\r
- * Author: Alessandro Scotti (Dec 2005)\r
- *\r
- * ------------------------------------------------------------------------\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- * ------------------------------------------------------------------------\r
- */\r
-#include "config.h"\r
-\r
-#include <windows.h> /* required for all Windows applications */\r
-#include <richedit.h>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <malloc.h>\r
-#include <commdlg.h>\r
-#include <dlgs.h>\r
-\r
-#include "common.h"\r
-#include "winboard.h"\r
-#include "frontend.h"\r
-#include "backend.h"\r
-\r
-#include "wsnap.h"\r
-\r
-VOID EngineOutputPopUp();\r
-VOID EngineOutputPopDown();\r
-BOOL EngineOutputIsUp();\r
-\r
-#define SHOW_PONDERING\r
-\r
-/* Imports from backend.c */\r
-char * SavePart(char *str);\r
-\r
-/* Imports from winboard.c */\r
-extern HWND engineOutputDialog;\r
-extern BOOLEAN engineOutputDialogUp;\r
-\r
-extern HINSTANCE hInst;\r
-extern HWND hwndMain;\r
-\r
-extern WindowPlacement wpEngineOutput;\r
-\r
-/* Module variables */\r
-#define H_MARGIN            2\r
-#define V_MARGIN            2\r
-#define LABEL_V_DISTANCE    1   /* Distance between label and memo */\r
-#define SPLITTER_SIZE       4   /* Distance between first memo and second label */\r
-\r
-#define ICON_SIZE           14\r
-\r
-#define STATE_UNKNOWN   -1\r
-#define STATE_THINKING   0\r
-#define STATE_IDLE       1\r
-#define STATE_PONDERING  2\r
-#define STATE_ANALYZING  3\r
-\r
-static int  windowMode = 1;\r
-\r
-static BOOL needInit = TRUE;\r
-\r
-static HICON hiColorBlack = NULL;\r
-static HICON hiColorWhite = NULL;\r
-static HICON hiColorUnknown = NULL;\r
-static HICON hiClear = NULL;\r
-static HICON hiPondering = NULL;\r
-static HICON hiThinking = NULL;\r
-static HICON hiAnalyzing = NULL;\r
-\r
-static int  lastDepth[2] = { -1, -1 };\r
-static int  lastForwardMostMove[2] = { -1, -1 };\r
-static int  engineState[2] = { -1, -1 };\r
-\r
-typedef struct {\r
-    HWND hColorIcon;\r
-    HWND hLabel;\r
-    HWND hStateIcon;\r
-    HWND hStateData;\r
-    HWND hLabelNPS;\r
-    HWND hMemo;\r
-    char * name;\r
-    int which;\r
-    int depth;\r
-    unsigned long nodes;\r
-    int score;\r
-    int time;\r
-    char * pv;\r
-    char * hint;\r
-    int an_move_index;\r
-    int an_move_count;\r
-} EngineOutputData;\r
-\r
-static HICON LoadIconEx( int id )\r
-{\r
-    return LoadImage( hInst, MAKEINTRESOURCE(id), IMAGE_ICON, ICON_SIZE, ICON_SIZE, 0 );\r
-}\r
-\r
-static VOID InitializeEngineOutput()\r
-{\r
-    if( needInit ) {\r
-        hiColorBlack = LoadIconEx( IDI_BLACK_14 );\r
-        hiColorWhite = LoadIconEx( IDI_WHITE_14 );\r
-        hiColorUnknown = LoadIconEx( IDI_UNKNOWN_14 );\r
-        hiClear = LoadIconEx( IDI_TRANS_14 );\r
-        hiPondering = LoadIconEx( IDI_PONDER_14 );\r
-        hiThinking = LoadIconEx( IDI_CLOCK_14 );\r
-        hiAnalyzing = LoadIconEx( IDI_ANALYZE2_14 );\r
-        needInit = FALSE;\r
-    }\r
-}\r
-\r
-static VOID SetControlPos( HWND hDlg, int id, int x, int y, int width, int height )\r
-{\r
-    HWND hControl = GetDlgItem( hDlg, id );\r
-\r
-    SetWindowPos( hControl, HWND_TOP, x, y, width, height, SWP_NOZORDER );\r
-}\r
-\r
-#define HIDDEN_X    20000\r
-#define HIDDEN_Y    20000\r
-\r
-static VOID HideControl( HWND hDlg, int id )\r
-{\r
-    HWND hControl = GetDlgItem( hDlg, id );\r
-    RECT rc;\r
-\r
-    GetWindowRect( hControl, &rc );\r
-\r
-    /* \r
-        Avoid hiding an already hidden control, because that causes many\r
-        unnecessary WM_ERASEBKGND messages!\r
-    */\r
-    if( rc.left != HIDDEN_X || rc.top != HIDDEN_Y ) {\r
-        SetControlPos( hDlg, id, 20000, 20000, 100, 100 );\r
-    }\r
-}\r
-\r
-static int GetControlWidth( HWND hDlg, int id )\r
-{\r
-    RECT rc;\r
-\r
-    GetWindowRect( GetDlgItem( hDlg, id ), &rc );\r
-\r
-    return rc.right - rc.left;\r
-}\r
-\r
-static int GetControlHeight( HWND hDlg, int id )\r
-{\r
-    RECT rc;\r
-\r
-    GetWindowRect( GetDlgItem( hDlg, id ), &rc );\r
-\r
-    return rc.bottom - rc.top;\r
-}\r
-\r
-static int GetHeaderHeight()\r
-{\r
-    int result = GetControlHeight( engineOutputDialog, IDC_EngineLabel1 );\r
-\r
-    if( result < ICON_SIZE ) result = ICON_SIZE;\r
-\r
-    return result;\r
-}\r
-\r
-#define ENGINE_COLOR_WHITE      'w'\r
-#define ENGINE_COLOR_BLACK      'b'\r
-#define ENGINE_COLOR_UNKNOWN    ' '\r
-\r
-char GetEngineColor( int which )\r
-{\r
-    char result = ENGINE_COLOR_UNKNOWN;\r
-\r
-    if( which == 0 || which == 1 ) {\r
-        ChessProgramState * cps;\r
-\r
-        switch (gameMode) {\r
-        case MachinePlaysBlack:\r
-        case IcsPlayingBlack:\r
-            result = ENGINE_COLOR_BLACK;\r
-            break;\r
-        case MachinePlaysWhite:\r
-        case IcsPlayingWhite:\r
-            result = ENGINE_COLOR_WHITE;\r
-            break;\r
-        case AnalyzeMode:\r
-        case AnalyzeFile:\r
-            result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;\r
-            break;\r
-        case TwoMachinesPlay:\r
-            cps = (which == 0) ? &first : &second;\r
-            result = cps->twoMachinesColor[0];\r
-            result = result == 'w' ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;\r
-            break;\r
-        }\r
-    }\r
-\r
-    return result;\r
-}\r
-\r
-char GetActiveEngineColor()\r
-{\r
-    char result = ENGINE_COLOR_UNKNOWN;\r
-\r
-    if( gameMode == TwoMachinesPlay ) {\r
-        result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;\r
-    }\r
-\r
-    return result;\r
-}\r
-\r
-static int IsEnginePondering( int which )\r
-{\r
-    int result = FALSE;\r
-\r
-    switch (gameMode) {\r
-    case MachinePlaysBlack:\r
-    case IcsPlayingBlack:\r
-        if( WhiteOnMove(forwardMostMove) ) result = TRUE;\r
-        break;\r
-    case MachinePlaysWhite:\r
-    case IcsPlayingWhite:\r
-        if( ! WhiteOnMove(forwardMostMove) ) result = TRUE;\r
-        break;\r
-    case TwoMachinesPlay:\r
-        if( GetActiveEngineColor() != ENGINE_COLOR_UNKNOWN ) {\r
-            if( GetEngineColor( which ) != GetActiveEngineColor() ) result = TRUE;\r
-        }\r
-        break;\r
-    }\r
-\r
-    return result;\r
-}\r
-\r
-static VOID PositionControlSet( HWND hDlg, int x, int y, int clientWidth, int memoHeight, int idColor, int idEngineLabel, int idNPS, int idMemo, int idStateIcon, int idStateData )\r
-{\r
-    int label_x = x + ICON_SIZE + H_MARGIN;\r
-    int label_h = GetControlHeight( hDlg, IDC_EngineLabel1 );\r
-    int label_y = y + ICON_SIZE - label_h;\r
-    int nps_w = GetControlWidth( hDlg, IDC_Engine1_NPS );\r
-    int nps_x = clientWidth - H_MARGIN - nps_w;\r
-    int state_data_w = GetControlWidth( hDlg, IDC_StateData1 );\r
-    int state_data_x = nps_x - H_MARGIN - state_data_w;\r
-    int state_icon_x = state_data_x - ICON_SIZE - 2;\r
-    int max_w = clientWidth - 2*H_MARGIN;\r
-    int memo_y = y + ICON_SIZE + LABEL_V_DISTANCE;\r
-\r
-    SetControlPos( hDlg, idColor, x, y, ICON_SIZE, ICON_SIZE );\r
-    SetControlPos( hDlg, idEngineLabel, label_x, label_y, state_icon_x - label_x, label_h );\r
-    SetControlPos( hDlg, idStateIcon, state_icon_x, y, ICON_SIZE, ICON_SIZE );\r
-    SetControlPos( hDlg, idStateData, state_data_x, label_y, state_data_w, label_h );\r
-    SetControlPos( hDlg, idNPS, nps_x, label_y, nps_w, label_h );\r
-    SetControlPos( hDlg, idMemo, x, memo_y, max_w, memoHeight );\r
-}\r
-\r
-static VOID ResizeWindowControls( HWND hDlg, int mode )\r
-{\r
-    RECT rc;\r
-    int headerHeight = GetHeaderHeight();\r
-    int labelHeight = GetControlHeight( hDlg, IDC_EngineLabel1 );\r
-    int labelOffset = H_MARGIN + ICON_SIZE + H_MARGIN;\r
-    int labelDeltaY = ICON_SIZE - labelHeight;\r
-    int clientWidth;\r
-    int clientHeight;\r
-    int maxControlWidth;\r
-    int npsWidth;\r
-\r
-    /* Initialize variables */\r
-    GetClientRect( hDlg, &rc );\r
-\r
-    clientWidth = rc.right - rc.left;\r
-    clientHeight = rc.bottom - rc.top;\r
-\r
-    maxControlWidth = clientWidth - 2*H_MARGIN;\r
-\r
-    npsWidth = GetControlWidth( hDlg, IDC_Engine1_NPS );\r
-\r
-    /* Resize controls */\r
-    if( mode == 0 ) {\r
-        /* One engine */\r
-        PositionControlSet( hDlg, H_MARGIN, V_MARGIN, \r
-            clientWidth, \r
-            clientHeight - V_MARGIN - LABEL_V_DISTANCE - headerHeight- V_MARGIN,\r
-            IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );\r
-\r
-        /* Hide controls for the second engine */\r
-        HideControl( hDlg, IDC_Color2 );\r
-        HideControl( hDlg, IDC_EngineLabel2 );\r
-        HideControl( hDlg, IDC_StateIcon2 );\r
-        HideControl( hDlg, IDC_StateData2 );\r
-        HideControl( hDlg, IDC_Engine2_NPS );\r
-        HideControl( hDlg, IDC_EngineMemo2 );\r
-        SendDlgItemMessage( hDlg, IDC_EngineMemo2, WM_SETTEXT, 0, (LPARAM) "" );\r
-        /* TODO: we should also hide/disable them!!! what about tab stops?!?! */\r
-    }\r
-    else {\r
-        /* Two engines */\r
-        int memo_h = (clientHeight - headerHeight*2 - V_MARGIN*2 - LABEL_V_DISTANCE*2 - SPLITTER_SIZE) / 2;\r
-        int header1_y = V_MARGIN;\r
-        int header2_y = V_MARGIN + headerHeight + LABEL_V_DISTANCE + memo_h + SPLITTER_SIZE;\r
-\r
-        PositionControlSet( hDlg, H_MARGIN, header1_y, clientWidth, memo_h,\r
-            IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );\r
-\r
-        PositionControlSet( hDlg, H_MARGIN, header2_y, clientWidth, memo_h,\r
-            IDC_Color2, IDC_EngineLabel2, IDC_Engine2_NPS, IDC_EngineMemo2, IDC_StateIcon2, IDC_StateData2 );\r
-    }\r
-\r
-    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo1), NULL, FALSE );\r
-    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo2), NULL, FALSE );\r
-}\r
-\r
-static VOID SetDisplayMode( int mode )\r
-{\r
-    if( windowMode != mode ) {\r
-        windowMode = mode;\r
-\r
-        ResizeWindowControls( engineOutputDialog, mode );\r
-    }\r
-}\r
-\r
-static VOID VerifyDisplayMode()\r
-{\r
-    int mode;\r
-\r
-    /* Get proper mode for current game */\r
-    switch( gameMode ) {\r
-    case AnalyzeMode:\r
-    case AnalyzeFile:\r
-    case MachinePlaysWhite:\r
-    case MachinePlaysBlack:\r
-    case IcsPlayingWhite:\r
-    case IcsPlayingBlack:\r
-        mode = 0;\r
-        break;\r
-    case TwoMachinesPlay:\r
-        mode = 1;\r
-        break;\r
-    default:\r
-        /* Do not change */\r
-        return;\r
-    }\r
-\r
-    SetDisplayMode( mode );\r
-}\r
-\r
-static VOID InsertIntoMemo( HWND hMemo, char * text )\r
-{\r
-    SendMessage( hMemo, EM_SETSEL, 0, 0 );\r
-\r
-    SendMessage( hMemo, EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );\r
-}\r
-\r
-static VOID SetIcon( HWND hControl, HICON hIcon )\r
-{\r
-    if( hIcon != NULL ) {\r
-        SendMessage( hControl, STM_SETICON, (WPARAM) hIcon, 0 );\r
-    }\r
-}\r
-\r
-static VOID SetEngineColorIcon( HWND hControl, int which )\r
-{\r
-    char color = GetEngineColor(which);\r
-    HICON hicon = NULL;\r
-\r
-    if( color == ENGINE_COLOR_BLACK )\r
-        hicon = hiColorBlack;\r
-    else if( color == ENGINE_COLOR_WHITE )\r
-        hicon = hiColorWhite;\r
-    else\r
-        hicon = hiColorUnknown;\r
-\r
-    SetIcon( hControl, hicon );\r
-}\r
-\r
-static SetEngineState( int which, int state, char * state_data )\r
-{\r
-    int x_which = 1 - which;\r
-    HWND hStateIcon = GetDlgItem( engineOutputDialog, which == 0 ? IDC_StateIcon1 : IDC_StateIcon2 );\r
-    HWND hStateData = GetDlgItem( engineOutputDialog, which == 0 ? IDC_StateData1 : IDC_StateData2 );\r
-\r
-    if( engineState[ which ] != state ) {\r
-        engineState[ which ] = state;\r
-\r
-        switch( state ) {\r
-        case STATE_THINKING:\r
-            SetIcon( hStateIcon, hiThinking );\r
-            if( engineState[ x_which ] == STATE_THINKING ) {\r
-                SetEngineState( x_which, STATE_IDLE, "" );\r
-            }\r
-            break;\r
-        case STATE_PONDERING:\r
-            SetIcon( hStateIcon, hiPondering );\r
-            break;\r
-        case STATE_ANALYZING:\r
-            SetIcon( hStateIcon, hiAnalyzing );\r
-            break;\r
-        default:\r
-            SetIcon( hStateIcon, hiClear );\r
-            break;\r
-        }\r
-    }\r
-\r
-    if( state_data != 0 ) {\r
-        SetWindowText( hStateData, state_data );\r
-    }\r
-}\r
-\r
-#define MAX_NAME_LENGTH 32\r
-\r
-static VOID UpdateControls( EngineOutputData * ed )\r
-{\r
-    BOOL isPondering = FALSE;\r
-\r
-    char s_label[MAX_NAME_LENGTH + 32];\r
-    \r
-    char * name = ed->name;\r
-\r
-    /* Label */\r
-    if( name == 0 || *name == '\0' ) {\r
-        name = "?";\r
-    }\r
-\r
-    strncpy( s_label, name, MAX_NAME_LENGTH );\r
-    s_label[ MAX_NAME_LENGTH-1 ] = '\0';\r
-\r
-#ifdef SHOW_PONDERING\r
-    if( IsEnginePondering( ed->which ) ) {\r
-        char buf[8];\r
-\r
-        buf[0] = '\0';\r
-\r
-        if( ed->hint != 0 && *ed->hint != '\0' ) {\r
-            strncpy( buf, ed->hint, sizeof(buf) );\r
-            buf[sizeof(buf)-1] = '\0';\r
-        }\r
-        else if( ed->pv != 0 && *ed->pv != '\0' ) {\r
-            char * sep = strchr( ed->pv, ' ' );\r
-            int buflen = sizeof(buf);\r
-\r
-            if( sep != NULL ) {\r
-                buflen = sep - ed->pv + 1;\r
-                if( buflen > sizeof(buf) ) buflen = sizeof(buf);\r
-            }\r
-\r
-            strncpy( buf, ed->pv, buflen );\r
-            buf[ buflen-1 ] = '\0';\r
-        }\r
-\r
-        SetEngineState( ed->which, STATE_PONDERING, buf );\r
-    }\r
-    else if( gameMode == TwoMachinesPlay ) {\r
-        SetEngineState( ed->which, STATE_THINKING, "" );\r
-    }\r
-    else if( gameMode == AnalyzeMode || gameMode == AnalyzeFile ) {\r
-        char buf[64];\r
-        int time_secs = ed->time / 100;\r
-        int time_mins = time_secs / 60;\r
-\r
-        buf[0] = '\0';\r
-\r
-        if( ed->an_move_index != 0 && ed->an_move_count != 0 && *ed->hint != '\0' ) {\r
-            char mov[16];\r
-\r
-            strncpy( mov, ed->hint, sizeof(mov) );\r
-            mov[ sizeof(mov)-1 ] = '\0';\r
-\r
-            sprintf( buf, "%d/%d: %s [%02d:%02d:%02d]", ed->an_move_index, ed->an_move_count, mov, time_mins / 60, time_mins % 60, time_secs % 60 );\r
-        }\r
-\r
-        SetEngineState( ed->which, STATE_ANALYZING, buf );\r
-    }\r
-    else {\r
-        SetEngineState( ed->which, STATE_IDLE, "" );\r
-    }\r
-#endif\r
-\r
-    SetWindowText( ed->hLabel, s_label );\r
-\r
-    s_label[0] = '\0';\r
-\r
-    if( ed->time > 0 && ed->nodes > 0 ) {\r
-        unsigned long nps_100 = ed->nodes / ed->time;\r
-\r
-        if( nps_100 < 100000 ) {\r
-            sprintf( s_label, "NPS: %lu", nps_100 * 100 );\r
-        }\r
-        else {\r
-            sprintf( s_label, "NPS: %.1fk", nps_100 / 10.0 );\r
-        }\r
-    }\r
-\r
-    SetWindowText( ed->hLabelNPS, s_label );\r
-\r
-    /* Memo */\r
-    if( ed->pv != 0 && *ed->pv != '\0' ) {\r
-        char s_nodes[24];\r
-        char s_score[16];\r
-        char s_time[24];\r
-        char buf[256];\r
-        int buflen;\r
-        int time_secs = ed->time / 100;\r
-        int time_cent = ed->time % 100;\r
-\r
-        /* Nodes */\r
-        if( ed->nodes < 1000000 ) {\r
-            sprintf( s_nodes, "%lu", ed->nodes );\r
-        }\r
-        else {\r
-            sprintf( s_nodes, "%.1fM", ed->nodes / 1000000.0 );\r
-        }\r
-\r
-        /* Score */\r
-        if( ed->score > 0 ) {\r
-            sprintf( s_score, "+%.2f", ed->score / 100.0 );\r
-        }\r
-        else {\r
-            sprintf( s_score, "%.2f", ed->score / 100.0 );\r
-        }\r
-\r
-        /* Time */\r
-        sprintf( s_time, "%d:%02d.%02d", time_secs / 60, time_secs % 60, time_cent );\r
-\r
-        /* Put all together... */\r
-        sprintf( buf, "%3d\t%s\t%s\t%s\t", ed->depth, s_score, s_nodes, s_time );\r
-\r
-        /* Add PV */\r
-        buflen = strlen(buf);\r
-\r
-        strncpy( buf + buflen, ed->pv, sizeof(buf) - buflen );\r
-\r
-        buf[ sizeof(buf) - 3 ] = '\0';\r
-\r
-        strcat( buf + buflen, "\r\n" );\r
-\r
-        /* Update memo */\r
-        InsertIntoMemo( ed->hMemo, buf );\r
-    }\r
-\r
-    /* Colors */\r
-    SetEngineColorIcon( ed->hColorIcon, ed->which );\r
-}\r
-\r
-LRESULT CALLBACK EngineOutputProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )\r
-{\r
-    static SnapData sd;\r
-\r
-    switch (message) {\r
-    case WM_INITDIALOG:\r
-        if( engineOutputDialog == NULL ) {\r
-            engineOutputDialog = hDlg;\r
-\r
-            RestoreWindowPlacement( hDlg, &wpEngineOutput ); /* Restore window placement */\r
-\r
-            ResizeWindowControls( hDlg, windowMode );\r
-\r
-            SetEngineState( 0, STATE_IDLE, "" );\r
-            SetEngineState( 1, STATE_IDLE, "" );\r
-        }\r
-\r
-        return FALSE;\r
-\r
-    case WM_COMMAND:\r
-        switch (LOWORD(wParam)) {\r
-        case IDOK:\r
-          EndDialog(hDlg, TRUE);\r
-          return TRUE;\r
-\r
-        case IDCANCEL:\r
-          EndDialog(hDlg, FALSE);\r
-          return TRUE;\r
-\r
-        default:\r
-          break;\r
-        }\r
-\r
-        break;\r
-\r
-    case WM_GETMINMAXINFO:\r
-        {\r
-            MINMAXINFO * mmi = (MINMAXINFO *) lParam;\r
-        \r
-            mmi->ptMinTrackSize.x = 100;\r
-            mmi->ptMinTrackSize.y = 160;\r
-        }\r
-        break;\r
-\r
-    case WM_CLOSE:\r
-        EngineOutputPopDown();\r
-        break;\r
-\r
-    case WM_SIZE:\r
-        ResizeWindowControls( hDlg, windowMode );\r
-        break;\r
-\r
-    case WM_ENTERSIZEMOVE:\r
-        return OnEnterSizeMove( &sd, hDlg, wParam, lParam );\r
-\r
-    case WM_SIZING:\r
-        return OnSizing( &sd, hDlg, wParam, lParam );\r
-\r
-    case WM_MOVING:\r
-        return OnMoving( &sd, hDlg, wParam, lParam );\r
-\r
-    case WM_EXITSIZEMOVE:\r
-        return OnExitSizeMove( &sd, hDlg, wParam, lParam );\r
-    }\r
-\r
-    return FALSE;\r
-}\r
-\r
-VOID EngineOutputPopUp()\r
-{\r
-  FARPROC lpProc;\r
-\r
-  if( needInit ) {\r
-      InitializeEngineOutput();\r
-  }\r
-  \r
-  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_CHECKED);\r
-\r
-  if( engineOutputDialog ) {\r
-    SendMessage( engineOutputDialog, WM_INITDIALOG, 0, 0 );\r
-\r
-    if( ! engineOutputDialogUp ) {\r
-        ShowWindow(engineOutputDialog, SW_SHOW);\r
-    }\r
-  }\r
-  else {\r
-    lpProc = MakeProcInstance( (FARPROC) EngineOutputProc, hInst );\r
-\r
-    /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */\r
-    CreateDialog( hInst, MAKEINTRESOURCE(DLG_EngineOutput), hwndMain, (DLGPROC)lpProc );\r
-\r
-    FreeProcInstance(lpProc);\r
-  }\r
-\r
-  engineOutputDialogUp = TRUE;\r
-  ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output
-}\r
-\r
-VOID EngineOutputPopDown()\r
-{\r
-  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_UNCHECKED);\r
-\r
-  if( engineOutputDialog ) {\r
-      ShowWindow(engineOutputDialog, SW_HIDE);\r
-  }\r
-\r
-  engineOutputDialogUp = FALSE;\r
-  ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output
-}\r
-\r
-BOOL EngineOutputIsUp()\r
-{\r
-    return engineOutputDialogUp;\r
-}\r
-\r
-VOID EngineOutputUpdate( FrontEndProgramStats * stats )\r
-{\r
-    EngineOutputData ed;\r
-    BOOL clearMemo = FALSE;\r
-    int which;\r
-    int depth;\r
-\r
-    if( stats == 0 ) {\r
-        SetEngineState( 0, STATE_IDLE, "" );\r
-        SetEngineState( 1, STATE_IDLE, "" );\r
-        return;\r
-    }\r
-\r
-    which = stats->which;\r
-    depth = stats->depth;\r
-\r
-    if( which < 0 || which > 1 || depth < 0 || stats->time < 0 || stats->pv == 0 ) {\r
-        return;\r
-    }\r
-\r
-    if( engineOutputDialog == NULL ) {\r
-        return;\r
-    }\r
-\r
-    VerifyDisplayMode();\r
-\r
-    ed.which = which;\r
-    ed.depth = depth;\r
-    ed.nodes = stats->nodes;\r
-    ed.score = stats->score;\r
-    ed.time = stats->time;\r
-    ed.pv = stats->pv;\r
-    ed.hint = stats->hint;\r
-    ed.an_move_index = stats->an_move_index;\r
-    ed.an_move_count = stats->an_move_count;\r
-\r
-    /* Get target control */\r
-    if( which == 0 ) {\r
-        ed.hColorIcon = GetDlgItem( engineOutputDialog, IDC_Color1 );\r
-        ed.hLabel = GetDlgItem( engineOutputDialog, IDC_EngineLabel1 );\r
-        ed.hStateIcon = GetDlgItem( engineOutputDialog, IDC_StateIcon1 );\r
-        ed.hStateData = GetDlgItem( engineOutputDialog, IDC_StateData1 );\r
-        ed.hLabelNPS = GetDlgItem( engineOutputDialog, IDC_Engine1_NPS );\r
-        ed.hMemo  = GetDlgItem( engineOutputDialog, IDC_EngineMemo1 );\r
-        ed.name = first.tidy;\r
-    }\r
-    else {\r
-        ed.hColorIcon = GetDlgItem( engineOutputDialog, IDC_Color2 );\r
-        ed.hLabel = GetDlgItem( engineOutputDialog, IDC_EngineLabel2 );\r
-        ed.hStateIcon = GetDlgItem( engineOutputDialog, IDC_StateIcon2 );\r
-        ed.hStateData = GetDlgItem( engineOutputDialog, IDC_StateData2 );\r
-        ed.hLabelNPS = GetDlgItem( engineOutputDialog, IDC_Engine2_NPS );\r
-        ed.hMemo  = GetDlgItem( engineOutputDialog, IDC_EngineMemo2 );\r
-        ed.name = second.tidy;\r
-    }\r
-\r
-    /* Clear memo if needed */\r
-    if( lastDepth[which] > depth || (lastDepth[which] == depth && depth <= 1) ) {\r
-        clearMemo = TRUE;\r
-    }\r
-\r
-    if( lastForwardMostMove[which] != forwardMostMove ) {\r
-        clearMemo = TRUE;\r
-    }\r
-\r
-    if( clearMemo ) {\r
-        SendMessage( ed.hMemo, WM_SETTEXT, 0, (LPARAM) "" );\r
-    }\r
-\r
-    /* Update */\r
-    lastDepth[which] = depth;\r
-    lastForwardMostMove[which] = forwardMostMove;\r
-\r
-    if( ed.pv != 0 && ed.pv[0] == ' ' ) {\r
-        if( strncmp( ed.pv, " no PV", 6 ) == 0 ) { /* Hack on hack! :-O */\r
-            ed.pv = "";\r
-        }\r
-    }\r
-\r
-    UpdateControls( &ed );\r
-}\r
+/*
+ * Engine output (PV)
+ *
+ * Author: Alessandro Scotti (Dec 2005)
+ *
+ * ------------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ------------------------------------------------------------------------
+ */
+#include "config.h"
+
+#include <windows.h> /* required for all Windows applications */
+#include <richedit.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <commdlg.h>
+#include <dlgs.h>
+
+#include "common.h"
+#include "winboard.h"
+#include "frontend.h"
+#include "backend.h"
+
+#include "wsnap.h"
+
+// [HGM] define numbers to indicate icons, for referring to them in platform-independent way
+#define nColorBlack   1
+#define nColorWhite   2
+#define nColorUnknown 3
+#define nClear        4
+#define nPondering    5
+#define nThinking     6
+#define nAnalyzing    7
+
+HICON icons[8]; // [HGM] this front-end array translates back-end icon indicator to handle
+
+// [HGM] same for output fields (note that there are two of each type, one per color)
+#define nColorIcon 1
+#define nStateIcon 2
+#define nLabel     3
+#define nStateData 4
+#define nLabelNPS  5
+#define nMemo      6
+
+HWND outputField[2][7]; // [HGM] front-end array to translate output field to window handle
+
+void EngineOutputPopUp();
+void EngineOutputPopDown();
+int  EngineOutputIsUp();
+
+#define SHOW_PONDERING
+
+/* Imports from backend.c */
+char * SavePart(char *str);
+extern int opponentKibitzes;
+
+/* Imports from winboard.c */
+extern HWND engineOutputDialog;
+extern int     engineOutputDialogUp;
+
+extern HINSTANCE hInst;
+extern HWND hwndMain;
+
+extern WindowPlacement wpEngineOutput;
+
+/* Module variables */
+#define H_MARGIN            2
+#define V_MARGIN            2
+#define LABEL_V_DISTANCE    1   /* Distance between label and memo */
+#define SPLITTER_SIZE       4   /* Distance between first memo and second label */
+
+#define ICON_SIZE           14
+
+#define STATE_UNKNOWN   -1
+#define STATE_THINKING   0
+#define STATE_IDLE       1
+#define STATE_PONDERING  2
+#define STATE_ANALYZING  3
+
+static int  windowMode = 1;
+
+static int  needInit = TRUE;
+
+static int  lastDepth[2] = { -1, -1 };
+static int  lastForwardMostMove[2] = { -1, -1 };
+static int  engineState[2] = { -1, -1 };
+
+typedef struct {
+//    HWND hColorIcon; // [HGM] the output-control handles are no loger passed,
+//    HWND hLabel;     //       to give better front-end / back-end separation
+//    HWND hStateIcon; //       the front-end routines now get them from a (front-end)
+//    HWND hStateData; //       table, indexed by output-field indicators.
+//    HWND hLabelNPS;
+//    HWND hMemo;
+    char * name;
+    int which;
+    int depth;
+    unsigned long nodes;
+    int score;
+    int time;
+    char * pv;
+    char * hint;
+    int an_move_index;
+    int an_move_count;
+} EngineOutputData;
+
+static VerifyDisplayMode();
+static void UpdateControls( EngineOutputData * ed );
+static SetEngineState( int which, int state, char * state_data );
+
+// front end
+static HICON LoadIconEx( int id )
+{
+    return LoadImage( hInst, MAKEINTRESOURCE(id), IMAGE_ICON, ICON_SIZE, ICON_SIZE, 0 );
+}
+
+// [HGM] the platform-dependent way of indicating where output should go is now all
+// concentrated here, where a table of platform-dependent handles are initialized.
+// This cleanses most other routines of front-end stuff, so they can go into the back end.
+static void InitializeEngineOutput()
+{
+ //   if( needInit ) { // needInit was already tested before call
+       // [HGM] made this into a table, rather than separate global variables
+        icons[nColorBlack]   = LoadIconEx( IDI_BLACK_14 );
+        icons[nColorWhite]   = LoadIconEx( IDI_WHITE_14 );
+        icons[nColorUnknown] = LoadIconEx( IDI_UNKNOWN_14 );
+        icons[nClear]        = LoadIconEx( IDI_TRANS_14 );
+        icons[nPondering]    = LoadIconEx( IDI_PONDER_14 );
+        icons[nThinking]     = LoadIconEx( IDI_CLOCK_14 );
+        icons[nAnalyzing]    = LoadIconEx( IDI_ANALYZE2_14 );
+
+       // [HGM] also make a table of handles to output controls
+       // Note that engineOutputDialog must be defined first!
+        outputField[0][nColorIcon] = GetDlgItem( engineOutputDialog, IDC_Color1 );
+        outputField[0][nLabel]     = GetDlgItem( engineOutputDialog, IDC_EngineLabel1 );
+        outputField[0][nStateIcon] = GetDlgItem( engineOutputDialog, IDC_StateIcon1 );
+        outputField[0][nStateData] = GetDlgItem( engineOutputDialog, IDC_StateData1 );
+        outputField[0][nLabelNPS]  = GetDlgItem( engineOutputDialog, IDC_Engine1_NPS );
+        outputField[0][nMemo]      = GetDlgItem( engineOutputDialog, IDC_EngineMemo1 );
+
+        outputField[1][nColorIcon] = GetDlgItem( engineOutputDialog, IDC_Color2 );
+        outputField[1][nLabel]     = GetDlgItem( engineOutputDialog, IDC_EngineLabel2 );
+        outputField[1][nStateIcon] = GetDlgItem( engineOutputDialog, IDC_StateIcon2 );
+        outputField[1][nStateData] = GetDlgItem( engineOutputDialog, IDC_StateData2 );
+        outputField[1][nLabelNPS]  = GetDlgItem( engineOutputDialog, IDC_Engine2_NPS );
+        outputField[1][nMemo]      = GetDlgItem( engineOutputDialog, IDC_EngineMemo2 );
+//        needInit = FALSE;
+//    }
+}
+
+// front end
+static void SetControlPos( HWND hDlg, int id, int x, int y, int width, int height )
+{
+    HWND hControl = GetDlgItem( hDlg, id );
+
+    SetWindowPos( hControl, HWND_TOP, x, y, width, height, SWP_NOZORDER );
+}
+
+#define HIDDEN_X    20000
+#define HIDDEN_Y    20000
+
+// front end
+static void HideControl( HWND hDlg, int id )
+{
+    HWND hControl = GetDlgItem( hDlg, id );
+    RECT rc;
+
+    GetWindowRect( hControl, &rc );
+
+    /* 
+        Avoid hiding an already hidden control, because that causes many
+        unnecessary WM_ERASEBKGND messages!
+    */
+    if( rc.left != HIDDEN_X || rc.top != HIDDEN_Y ) {
+        SetControlPos( hDlg, id, 20000, 20000, 100, 100 );
+    }
+}
+
+// front end, although we might make GetWindowRect front end instead
+static int GetControlWidth( HWND hDlg, int id )
+{
+    RECT rc;
+
+    GetWindowRect( GetDlgItem( hDlg, id ), &rc );
+
+    return rc.right - rc.left;
+}
+
+// front end?
+static int GetControlHeight( HWND hDlg, int id )
+{
+    RECT rc;
+
+    GetWindowRect( GetDlgItem( hDlg, id ), &rc );
+
+    return rc.bottom - rc.top;
+}
+
+static int GetHeaderHeight()
+{
+    int result = GetControlHeight( engineOutputDialog, IDC_EngineLabel1 );
+
+    if( result < ICON_SIZE ) result = ICON_SIZE;
+
+    return result;
+}
+
+// The size calculations should be backend? If setControlPos is a platform-dependent way of doing things,
+// a platform-independent wrapper for it should be supplied.
+static void PositionControlSet( HWND hDlg, int x, int y, int clientWidth, int memoHeight, int idColor, int idEngineLabel, int idNPS, int idMemo, int idStateIcon, int idStateData )
+{
+    int label_x = x + ICON_SIZE + H_MARGIN;
+    int label_h = GetControlHeight( hDlg, IDC_EngineLabel1 );
+    int label_y = y + ICON_SIZE - label_h;
+    int nps_w = GetControlWidth( hDlg, IDC_Engine1_NPS );
+    int nps_x = clientWidth - H_MARGIN - nps_w;
+    int state_data_w = GetControlWidth( hDlg, IDC_StateData1 );
+    int state_data_x = nps_x - H_MARGIN - state_data_w;
+    int state_icon_x = state_data_x - ICON_SIZE - 2;
+    int max_w = clientWidth - 2*H_MARGIN;
+    int memo_y = y + ICON_SIZE + LABEL_V_DISTANCE;
+
+    SetControlPos( hDlg, idColor, x, y, ICON_SIZE, ICON_SIZE );
+    SetControlPos( hDlg, idEngineLabel, label_x, label_y, state_icon_x - label_x, label_h );
+    SetControlPos( hDlg, idStateIcon, state_icon_x, y, ICON_SIZE, ICON_SIZE );
+    SetControlPos( hDlg, idStateData, state_data_x, label_y, state_data_w, label_h );
+    SetControlPos( hDlg, idNPS, nps_x, label_y, nps_w, label_h );
+    SetControlPos( hDlg, idMemo, x, memo_y, max_w, memoHeight );
+}
+
+// Also here some of the size calculations should go to the back end, and their actual application to a front-end routine
+static void ResizeWindowControls( HWND hDlg, int mode )
+{
+    RECT rc;
+    int headerHeight = GetHeaderHeight();
+    int labelHeight = GetControlHeight( hDlg, IDC_EngineLabel1 );
+    int labelOffset = H_MARGIN + ICON_SIZE + H_MARGIN;
+    int labelDeltaY = ICON_SIZE - labelHeight;
+    int clientWidth;
+    int clientHeight;
+    int maxControlWidth;
+    int npsWidth;
+
+    /* Initialize variables */
+    GetClientRect( hDlg, &rc );
+
+    clientWidth = rc.right - rc.left;
+    clientHeight = rc.bottom - rc.top;
+
+    maxControlWidth = clientWidth - 2*H_MARGIN;
+
+    npsWidth = GetControlWidth( hDlg, IDC_Engine1_NPS );
+
+    /* Resize controls */
+    if( mode == 0 ) {
+        /* One engine */
+        PositionControlSet( hDlg, H_MARGIN, V_MARGIN, 
+            clientWidth, 
+            clientHeight - V_MARGIN - LABEL_V_DISTANCE - headerHeight- V_MARGIN,
+            IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );
+
+        /* Hide controls for the second engine */
+        HideControl( hDlg, IDC_Color2 );
+        HideControl( hDlg, IDC_EngineLabel2 );
+        HideControl( hDlg, IDC_StateIcon2 );
+        HideControl( hDlg, IDC_StateData2 );
+        HideControl( hDlg, IDC_Engine2_NPS );
+        HideControl( hDlg, IDC_EngineMemo2 );
+        SendDlgItemMessage( hDlg, IDC_EngineMemo2, WM_SETTEXT, 0, (LPARAM) "" );
+        /* TODO: we should also hide/disable them!!! what about tab stops?!?! */
+    }
+    else {
+        /* Two engines */
+        int memo_h = (clientHeight - headerHeight*2 - V_MARGIN*2 - LABEL_V_DISTANCE*2 - SPLITTER_SIZE) / 2;
+        int header1_y = V_MARGIN;
+        int header2_y = V_MARGIN + headerHeight + LABEL_V_DISTANCE + memo_h + SPLITTER_SIZE;
+
+        PositionControlSet( hDlg, H_MARGIN, header1_y, clientWidth, memo_h,
+            IDC_Color1, IDC_EngineLabel1, IDC_Engine1_NPS, IDC_EngineMemo1, IDC_StateIcon1, IDC_StateData1 );
+
+        PositionControlSet( hDlg, H_MARGIN, header2_y, clientWidth, memo_h,
+            IDC_Color2, IDC_EngineLabel2, IDC_Engine2_NPS, IDC_EngineMemo2, IDC_StateIcon2, IDC_StateData2 );
+    }
+
+    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo1), NULL, FALSE );
+    InvalidateRect( GetDlgItem(hDlg,IDC_EngineMemo2), NULL, FALSE );
+}
+
+// front end. Actual printing of PV lines into the output field
+static void InsertIntoMemo( int which, char * text )
+{
+    SendMessage( outputField[which][nMemo], EM_SETSEL, 0, 0 );
+
+    SendMessage( outputField[which][nMemo], EM_REPLACESEL, (WPARAM) FALSE, (LPARAM) text );
+}
+
+// front end. Associates an icon with an output field ("control" in Windows jargon).
+// [HGM] let it find out the output field from the 'which' number by itself
+static void SetIcon( int which, int field, int nIcon )
+{
+
+    if( nIcon != 0 ) {
+        SendMessage( outputField[which][field], STM_SETICON, (WPARAM) icons[nIcon], 0 );
+    }
+}
+
+// front end wrapper for SetWindowText, taking control number in stead of handle
+void DoSetWindowText(int which, int field, char *s_label)
+{
+    SetWindowText( outputField[which][field], s_label );
+}
+
+// This seems pure front end
+LRESULT CALLBACK EngineOutputProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
+{
+    static SnapData sd;
+
+    switch (message) {
+    case WM_INITDIALOG:
+        if( engineOutputDialog == NULL ) {
+            engineOutputDialog = hDlg;
+
+            RestoreWindowPlacement( hDlg, &wpEngineOutput ); /* Restore window placement */
+
+            ResizeWindowControls( hDlg, windowMode );
+
+            SetEngineState( 0, STATE_IDLE, "" );
+            SetEngineState( 1, STATE_IDLE, "" );
+        }
+
+        return FALSE;
+
+    case WM_COMMAND:
+        switch (LOWORD(wParam)) {
+        case IDOK:
+          EndDialog(hDlg, TRUE);
+          return TRUE;
+
+        case IDCANCEL:
+          EndDialog(hDlg, FALSE);
+          return TRUE;
+
+        default:
+          break;
+        }
+
+        break;
+
+    case WM_GETMINMAXINFO:
+        {
+            MINMAXINFO * mmi = (MINMAXINFO *) lParam;
+        
+            mmi->ptMinTrackSize.x = 100;
+            mmi->ptMinTrackSize.y = 160;
+        }
+        break;
+
+    case WM_CLOSE:
+        EngineOutputPopDown();
+        break;
+
+    case WM_SIZE:
+        ResizeWindowControls( hDlg, windowMode );
+        break;
+
+    case WM_ENTERSIZEMOVE:
+        return OnEnterSizeMove( &sd, hDlg, wParam, lParam );
+
+    case WM_SIZING:
+        return OnSizing( &sd, hDlg, wParam, lParam );
+
+    case WM_MOVING:
+        return OnMoving( &sd, hDlg, wParam, lParam );
+
+    case WM_EXITSIZEMOVE:
+        return OnExitSizeMove( &sd, hDlg, wParam, lParam );
+    }
+
+    return FALSE;
+}
+
+// front end
+void EngineOutputPopUp()
+{
+  FARPROC lpProc;
+  
+  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_CHECKED);
+
+  if( engineOutputDialog ) {
+    SendMessage( engineOutputDialog, WM_INITDIALOG, 0, 0 );
+
+    if( ! engineOutputDialogUp ) {
+        ShowWindow(engineOutputDialog, SW_SHOW);
+    }
+  }
+  else {
+    lpProc = MakeProcInstance( (FARPROC) EngineOutputProc, hInst );
+
+    /* Note to self: dialog must have the WS_VISIBLE style set, otherwise it's not shown! */
+    CreateDialog( hInst, MAKEINTRESOURCE(DLG_EngineOutput), hwndMain, (DLGPROC)lpProc );
+
+    FreeProcInstance(lpProc);
+  }
+
+  // [HGM] displaced to after creation of dialog, to allow initialization of output fields
+  if( needInit ) {
+      InitializeEngineOutput();
+      needInit = FALSE;
+  }
+
+  engineOutputDialogUp = TRUE;
+}
+
+// front end
+void EngineOutputPopDown()
+{
+  CheckMenuItem(GetMenu(hwndMain), IDM_ShowEngineOutput, MF_UNCHECKED);
+
+  if( engineOutputDialog ) {
+      ShowWindow(engineOutputDialog, SW_HIDE);
+  }
+
+  engineOutputDialogUp = FALSE;
+}
+
+// front end. [HGM] Takes handle of output control from table, so only number is passed
+void DoClearMemo(int which)
+{
+        SendMessage( outputField[which][nMemo], WM_SETTEXT, 0, (LPARAM) "" );
+}
+
+//------------------------ pure back-end routines -------------------------------
+
+
+// back end, due to front-end wrapper for SetWindowText, and new SetIcon arguments
+static SetEngineState( int which, int state, char * state_data )
+{
+    int x_which = 1 - which;
+
+    if( engineState[ which ] != state ) {
+        engineState[ which ] = state;
+
+        switch( state ) {
+        case STATE_THINKING:
+            SetIcon( which, nStateIcon, nThinking );
+            if( engineState[ x_which ] == STATE_THINKING ) {
+                SetEngineState( x_which, STATE_IDLE, "" );
+            }
+            break;
+        case STATE_PONDERING:
+            SetIcon( which, nStateIcon, nPondering );
+            break;
+        case STATE_ANALYZING:
+            SetIcon( which, nStateIcon, nAnalyzing );
+            break;
+        default:
+            SetIcon( which, nStateIcon, nClear );
+            break;
+        }
+    }
+
+    if( state_data != 0 ) {
+        DoSetWindowText( which, nStateData, state_data );
+    }
+}
+
+// back end, now the front-end wrapper ClearMemo is used, and ed no longer contains handles.
+void EngineOutputUpdate( FrontEndProgramStats * stats )
+{
+    EngineOutputData ed;
+    int clearMemo = FALSE;
+    int which;
+    int depth;
+
+    if( stats == 0 ) {
+        SetEngineState( 0, STATE_IDLE, "" );
+        SetEngineState( 1, STATE_IDLE, "" );
+        return;
+    }
+
+    if(gameMode == IcsObserving) return; // [HGM] kibitz: shut up engine if we are observing an ICS game
+
+    which = stats->which;
+    depth = stats->depth;
+
+    if( which < 0 || which > 1 || depth < 0 || stats->time < 0 || stats->pv == 0 ) {
+        return;
+    }
+
+    if( engineOutputDialog == NULL ) {
+        return;
+    }
+
+    VerifyDisplayMode();
+
+    ed.which = which;
+    ed.depth = depth;
+    ed.nodes = stats->nodes;
+    ed.score = stats->score;
+    ed.time = stats->time;
+    ed.pv = stats->pv;
+    ed.hint = stats->hint;
+    ed.an_move_index = stats->an_move_index;
+    ed.an_move_count = stats->an_move_count;
+
+    /* Get target control. [HGM] this is moved to front end, which get them from a table */
+    if( which == 0 ) {
+        ed.name = first.tidy;
+    }
+    else {
+        ed.name = second.tidy;
+    }
+
+    /* Clear memo if needed */
+    if( lastDepth[which] > depth || (lastDepth[which] == depth && depth <= 1) ) {
+        clearMemo = TRUE;
+    }
+
+    if( lastForwardMostMove[which] != forwardMostMove ) {
+        clearMemo = TRUE;
+    }
+
+    if( clearMemo ) DoClearMemo(which);
+
+    /* Update */
+    lastDepth[which] = depth;
+    lastForwardMostMove[which] = forwardMostMove;
+
+    if( ed.pv != 0 && ed.pv[0] == ' ' ) {
+        if( strncmp( ed.pv, " no PV", 6 ) == 0 ) { /* Hack on hack! :-O */
+            ed.pv = "";
+        }
+    }
+
+    UpdateControls( &ed );
+}
+
+#define ENGINE_COLOR_WHITE      'w'
+#define ENGINE_COLOR_BLACK      'b'
+#define ENGINE_COLOR_UNKNOWN    ' '
+
+// pure back end
+char GetEngineColor( int which )
+{
+    char result = ENGINE_COLOR_UNKNOWN;
+
+    if( which == 0 || which == 1 ) {
+        ChessProgramState * cps;
+
+        switch (gameMode) {
+        case MachinePlaysBlack:
+        case IcsPlayingBlack:
+            result = ENGINE_COLOR_BLACK;
+            break;
+        case MachinePlaysWhite:
+        case IcsPlayingWhite:
+            result = ENGINE_COLOR_WHITE;
+            break;
+        case AnalyzeMode:
+        case AnalyzeFile:
+            result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;
+            break;
+        case TwoMachinesPlay:
+            cps = (which == 0) ? &first : &second;
+            result = cps->twoMachinesColor[0];
+            result = result == 'w' ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;
+            break;
+        }
+    }
+
+    return result;
+}
+
+// pure back end
+char GetActiveEngineColor()
+{
+    char result = ENGINE_COLOR_UNKNOWN;
+
+    if( gameMode == TwoMachinesPlay ) {
+        result = WhiteOnMove(forwardMostMove) ? ENGINE_COLOR_WHITE : ENGINE_COLOR_BLACK;
+    }
+
+    return result;
+}
+
+// pure back end
+static int IsEnginePondering( int which )
+{
+    int result = FALSE;
+
+    switch (gameMode) {
+    case MachinePlaysBlack:
+    case IcsPlayingBlack:
+        if( WhiteOnMove(forwardMostMove) ) result = TRUE;
+        break;
+    case MachinePlaysWhite:
+    case IcsPlayingWhite:
+        if( ! WhiteOnMove(forwardMostMove) ) result = TRUE;
+        break;
+    case TwoMachinesPlay:
+        if( GetActiveEngineColor() != ENGINE_COLOR_UNKNOWN ) {
+            if( GetEngineColor( which ) != GetActiveEngineColor() ) result = TRUE;
+        }
+        break;
+    }
+
+    return result;
+}
+
+// back end
+static void SetDisplayMode( int mode )
+{
+    if( windowMode != mode ) {
+        windowMode = mode;
+
+        ResizeWindowControls( engineOutputDialog, mode );
+    }
+}
+
+// pure back end
+static VerifyDisplayMode()
+{
+    int mode;
+
+    /* Get proper mode for current game */
+    switch( gameMode ) {
+    case AnalyzeMode:
+    case AnalyzeFile:
+    case MachinePlaysWhite:
+    case MachinePlaysBlack:
+        mode = 0;
+        break;
+    case IcsPlayingWhite:
+    case IcsPlayingBlack:
+        mode = appData.zippyPlay && opponentKibitzes; // [HGM] kibitz
+        break;
+    case TwoMachinesPlay:
+        mode = 1;
+        break;
+    default:
+        /* Do not change */
+        return;
+    }
+
+    SetDisplayMode( mode );
+}
+
+// back end. Determine what icon to se in the color-icon field, and print it
+static void SetEngineColorIcon( int which )
+{
+    char color = GetEngineColor(which);
+    int nicon = 0;
+
+    if( color == ENGINE_COLOR_BLACK )
+        nicon = nColorBlack;
+    else if( color == ENGINE_COLOR_WHITE )
+        nicon = nColorWhite;
+    else
+        nicon = nColorUnknown;
+
+    SetIcon( which, nColorIcon, nicon );
+}
+
+#define MAX_NAME_LENGTH 32
+
+// pure back end, now SetWindowText is called via wrapper DoSetWindowText
+static void UpdateControls( EngineOutputData * ed )
+{
+    int isPondering = FALSE;
+
+    char s_label[MAX_NAME_LENGTH + 32];
+    
+    char * name = ed->name;
+
+    /* Label */
+    if( name == 0 || *name == '\0' ) {
+        name = "?";
+    }
+
+    strncpy( s_label, name, MAX_NAME_LENGTH );
+    s_label[ MAX_NAME_LENGTH-1 ] = '\0';
+
+#ifdef SHOW_PONDERING
+    if( IsEnginePondering( ed->which ) ) {
+        char buf[8];
+
+        buf[0] = '\0';
+
+        if( ed->hint != 0 && *ed->hint != '\0' ) {
+            strncpy( buf, ed->hint, sizeof(buf) );
+            buf[sizeof(buf)-1] = '\0';
+        }
+        else if( ed->pv != 0 && *ed->pv != '\0' ) {
+            char * sep = strchr( ed->pv, ' ' );
+            int buflen = sizeof(buf);
+
+            if( sep != NULL ) {
+                buflen = sep - ed->pv + 1;
+                if( buflen > sizeof(buf) ) buflen = sizeof(buf);
+            }
+
+            strncpy( buf, ed->pv, buflen );
+            buf[ buflen-1 ] = '\0';
+        }
+
+        SetEngineState( ed->which, STATE_PONDERING, buf );
+    }
+    else if( gameMode == TwoMachinesPlay ) {
+        SetEngineState( ed->which, STATE_THINKING, "" );
+    }
+    else if( gameMode == AnalyzeMode || gameMode == AnalyzeFile ) {
+        char buf[64];
+        int time_secs = ed->time / 100;
+        int time_mins = time_secs / 60;
+
+        buf[0] = '\0';
+
+        if( ed->an_move_index != 0 && ed->an_move_count != 0 && *ed->hint != '\0' ) {
+            char mov[16];
+
+            strncpy( mov, ed->hint, sizeof(mov) );
+            mov[ sizeof(mov)-1 ] = '\0';
+
+            sprintf( buf, "%d/%d: %s [%02d:%02d:%02d]", ed->an_move_index, ed->an_move_count, mov, time_mins / 60, time_mins % 60, time_secs % 60 );
+        }
+
+        SetEngineState( ed->which, STATE_ANALYZING, buf );
+    }
+    else {
+        SetEngineState( ed->which, STATE_IDLE, "" );
+    }
+#endif
+
+    DoSetWindowText( ed->which, nLabel, s_label );
+
+    s_label[0] = '\0';
+
+    if( ed->time > 0 && ed->nodes > 0 ) {
+        unsigned long nps_100 = ed->nodes / ed->time;
+
+        if( nps_100 < 100000 ) {
+            sprintf( s_label, "NPS: %lu", nps_100 * 100 );
+        }
+        else {
+            sprintf( s_label, "NPS: %.1fk", nps_100 / 10.0 );
+        }
+    }
+
+    DoSetWindowText( ed->which, nLabelNPS, s_label );
+
+    /* Memo */
+    if( ed->pv != 0 && *ed->pv != '\0' ) {
+        char s_nodes[24];
+        char s_score[16];
+        char s_time[24];
+        char buf[256];
+        int buflen;
+        int time_secs = ed->time / 100;
+        int time_cent = ed->time % 100;
+
+        /* Nodes */
+        if( ed->nodes < 1000000 ) {
+            sprintf( s_nodes, "%lu", ed->nodes );
+        }
+        else {
+            sprintf( s_nodes, "%.1fM", ed->nodes / 1000000.0 );
+        }
+
+        /* Score */
+        if( ed->score > 0 ) {
+            sprintf( s_score, "+%.2f", ed->score / 100.0 );
+        }
+        else {
+            sprintf( s_score, "%.2f", ed->score / 100.0 );
+        }
+
+        /* Time */
+        sprintf( s_time, "%d:%02d.%02d", time_secs / 60, time_secs % 60, time_cent );
+
+        /* Put all together... */
+        sprintf( buf, "%3d\t%s\t%s\t%s\t", ed->depth, s_score, s_nodes, s_time );
+
+        /* Add PV */
+        buflen = strlen(buf);
+
+        strncpy( buf + buflen, ed->pv, sizeof(buf) - buflen );
+
+        buf[ sizeof(buf) - 3 ] = '\0';
+
+        strcat( buf + buflen, "\r\n" );
+
+        /* Update memo */
+        InsertIntoMemo( ed->which, buf );
+    }
+
+    /* Colors */
+    SetEngineColorIcon( ed->which );
+}
+
+// back end
+int EngineOutputIsUp()
+{
+    return engineOutputDialogUp;
+}
+
+// [HGM] kibitz: write kibitz line; split window for it if necessary
+void OutputKibitz(int window, char *text)
+{
+       if(!EngineOutputIsUp()) return;
+       if(!opponentKibitzes) { // on first kibitz of game, clear memos
+           DoClearMemo(1);
+           if(gameMode == IcsObserving) DoClearMemo(0);
+       }
+       opponentKibitzes = TRUE; // this causes split window DisplayMode in ICS modes.
+       VerifyDisplayMode();
+       if(gameMode == IcsObserving) {
+           DoSetWindowText(0, nLabel, gameInfo.white);
+           SetIcon( 0, nColorIcon,  nColorWhite);
+           SetIcon( 0, nStateIcon,  nClear);
+       }
+       DoSetWindowText(1, nLabel, gameMode == IcsPlayingBlack ? gameInfo.white : gameInfo.black); // opponent name
+       SetIcon( 1, nColorIcon,  gameMode == IcsPlayingBlack ? nColorWhite : nColorBlack);
+       SetIcon( 1, nStateIcon,  nClear);
+       InsertIntoMemo(window-1, text);
+}
+
index 86715e3..0623e3d 100644 (file)
@@ -648,6 +648,7 @@ VOID EngineOutputPopUp()
   }\r
 \r
   engineOutputDialogUp = TRUE;\r
+  ShowThinkingEvent(); // [HGM] thinking: might need to prompt engine for thinking output
 }\r
 \r
 VOID EngineOutputPopDown()\r
@@ -659,6 +660,7 @@ VOID EngineOutputPopDown()
   }\r
 \r
   engineOutputDialogUp = FALSE;\r
+  ShowThinkingEvent(); // [HGM] thinking: might need to shut off thinking output
 }\r
 \r
 BOOL EngineOutputIsUp()\r
index a70f16b..6ad5def 100644 (file)
@@ -140,7 +140,8 @@ BOOLEAN chessProgram;
 static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;\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
@@ -613,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
@@ -630,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
@@ -1188,6 +1219,10 @@ ArgDescriptor argDescriptors[] = {
   { "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
@@ -2530,7 +2565,7 @@ 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
@@ -2569,7 +2604,7 @@ static void CreatePieceMaskFromFont( HDC hdc_window, HDC hdc, int index )
         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
@@ -2610,7 +2645,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
@@ -3059,27 +3094,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
@@ -3565,7 +3625,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
@@ -3710,16 +3770,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
@@ -4045,7 +4105,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
@@ -4086,14 +4146,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
@@ -4130,6 +4192,32 @@ void fputDW(FILE *f, int x)
 #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
@@ -4383,6 +4471,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
@@ -4727,7 +4820,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                   gameMode == MachinePlaysWhite) {\r
          CallFlagEvent();\r
         } else if (gameMode == EditGame) {\r
-          AdjustClock(flipClock, -1);\r
+          AdjustClock((logoHeight > 0 ? flipView: flipClock), -1);\r
         }\r
       } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
        if (gameMode == EditPosition) {\r
@@ -4736,7 +4829,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                   gameMode == MachinePlaysBlack) {\r
          CallFlagEvent();\r
         } else if (gameMode == EditGame) {\r
-          AdjustClock(!flipClock, -1);\r
+          AdjustClock(!(logoHeight > 0 ? flipView: flipClock), -1);\r
        }\r
       }\r
       if (!appData.highlightLastMove) {\r
@@ -4794,7 +4887,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                   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)\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
@@ -4893,7 +4986,7 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
           else \r
           if (moveType == WhitePromotionQueen || moveType == BlackPromotionQueen ) {\r
                DrawPosition(forceFullRepaint || FALSE, NULL);\r
-                 if(gameInfo.variant == VariantSuper)\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
@@ -4961,9 +5054,9 @@ MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
     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(flipClock, 1);\r
+          if (gameMode == EditGame) AdjustClock((logoHeight > 0 ? flipView: flipClock), 1);\r
       } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
-          if (gameMode == EditGame) AdjustClock(!flipClock, 1);\r
+          if (gameMode == EditGame) AdjustClock(!(logoHeight > 0 ? flipView: flipClock), 1);\r
       }\r
     }\r
     DrawPosition(TRUE, NULL);\r
@@ -5192,7 +5285,7 @@ VOID
 ToggleShowThinking()\r
 {\r
   appData.showThinking = !appData.showThinking;\r
-  ShowThinkingEvent();
+  ShowThinkingEvent();\r
 }\r
 \r
 VOID\r
@@ -5506,7 +5599,7 @@ WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
         }\r
         else {\r
             EngineOutputPopUp();\r
-        }
+        }\r
         break;\r
 \r
     /* [AS] User adjudication */\r
@@ -9293,7 +9386,8 @@ DisplayWhiteClock(long timeRemaining, int highlight)
   char *flag = whiteFlag && gameMode == TwoMachinesPlay ? "(!)" : "";\r
 \r
   if (!IsIconic(hwndMain)) {\r
-    DisplayAClock(hdc, timeRemaining, highlight, flipClock ? &blackRect : &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
@@ -9315,7 +9409,8 @@ DisplayBlackClock(long timeRemaining, int highlight)
 \r
   hdc = GetDC(hwndMain);\r
   if (!IsIconic(hwndMain)) {\r
-    DisplayAClock(hdc, timeRemaining, highlight, flipClock ? &whiteRect : &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
@@ -9406,6 +9501,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
@@ -9521,6 +9633,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
index 0941cce..aa272e9 100644 (file)
-/*\r
- * woptions.c -- Options dialog box routines for WinBoard\r
- * $Id: woptions.c,v 2.1 2003/10/27 19:21:02 mann Exp $\r
- *\r
- * Copyright 2000 Free Software Foundation, Inc.\r
- *\r
- * ------------------------------------------------------------------------\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- * ------------------------------------------------------------------------\r
- */\r
-\r
-#include "config.h"\r
-\r
-#include <windows.h>   /* required for all Windows applications */\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <shlobj.h>    /* [AS] Requires NT 4.0 or Win95 */\r
-\r
-#include "common.h"\r
-#include "winboard.h"\r
-#include "backend.h"\r
-#include "woptions.h"\r
-#include "defaults.h"\r
-#include "wedittags.h"\r
-#include <richedit.h>\r
-\r
-#if __GNUC__\r
-#include <errno.h>\r
-#include <string.h>\r
-#endif\r
-\r
-/* Imports from winboard.c */\r
-\r
-extern MyFont *font[NUM_SIZES][NUM_FONTS];\r
-extern HINSTANCE hInst;          /* current instance */\r
-extern HWND hwndMain;            /* root window*/\r
-extern BOOLEAN alwaysOnTop;\r
-extern RECT boardRect;\r
-extern COLORREF lightSquareColor, darkSquareColor, whitePieceColor, \r
-  blackPieceColor, highlightSquareColor, premoveHighlightColor;\r
-extern HPALETTE hPal;\r
-extern BoardSize boardSize;\r
-extern COLORREF consoleBackgroundColor;\r
-extern MyColorizeAttribs colorizeAttribs[]; /* do I need the size? */\r
-extern MyTextAttribs textAttribs[];\r
-extern MySound sounds[];\r
-extern ColorClass currentColorClass;\r
-extern HWND hwndConsole;\r
-extern char *defaultTextAttribs[];\r
-extern HWND commentDialog;\r
-extern HWND moveHistoryDialog;\r
-extern char installDir[];\r
-extern HWND hCommPort;    /* currently open comm port */\r
-extern DCB dcb;\r
-extern BOOLEAN chessProgram;\r
-extern startedFromPositionFile; /* [HGM] loadPos */\r
-\r
-/* types */\r
-\r
-typedef struct {\r
-  char *label;\r
-  unsigned value;\r
-} ComboData;\r
-\r
-typedef struct {\r
-  char *label;\r
-  char *name;\r
-} SoundComboData;\r
-\r
-/* module prototypes */\r
-\r
-LRESULT CALLBACK GeneralOptions(HWND, UINT, WPARAM, LPARAM);\r
-LRESULT CALLBACK BoardOptions(HWND, UINT, WPARAM, LPARAM);\r
-LRESULT CALLBACK NewVariant(HWND, UINT, WPARAM, LPARAM);\r
-LRESULT CALLBACK IcsOptions(HWND, UINT, WPARAM, LPARAM);\r
-LRESULT CALLBACK FontOptions(HWND, UINT, WPARAM, LPARAM);\r
-LRESULT CALLBACK CommPortOptions(HWND, UINT, WPARAM, LPARAM);\r
-LRESULT CALLBACK LoadOptions(HWND, UINT, WPARAM, LPARAM);\r
-LRESULT CALLBACK SaveOptions(HWND, UINT, WPARAM, LPARAM);\r
-LRESULT CALLBACK TimeControl(HWND, UINT, WPARAM, LPARAM);\r
-VOID ChangeBoardSize(BoardSize newSize);\r
-VOID PaintSampleSquare(\r
-    HWND     hwnd, \r
-    int      ctrlid, \r
-    COLORREF squareColor, \r
-    COLORREF pieceColor,\r
-    COLORREF squareOutlineColor,\r
-    COLORREF pieceDetailColor,\r
-    BOOL     isWhitePiece,\r
-    BOOL     isMono,\r
-    HBITMAP  pieces[3] \r
-    );\r
-VOID PaintColorBlock(HWND hwnd, int ctrlid, COLORREF color);\r
-VOID SetBoardOptionEnables(HWND hDlg);\r
-BoardSize BoardOptionsWhichRadio(HWND hDlg);\r
-BOOL APIENTRY MyCreateFont(HWND hwnd, MyFont *font);\r
-VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);\r
-LRESULT CALLBACK ColorizeTextDialog(HWND , UINT, WPARAM, LPARAM);\r
-VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);\r
-VOID SetIcsOptionEnables(HWND hDlg);\r
-VOID SetSampleFontText(HWND hwnd, int id, const MyFont *mf);\r
-VOID CopyFont(MyFont *dest, const MyFont *src);\r
-void InitSoundComboData(SoundComboData *scd);\r
-void ResetSoundComboData(SoundComboData *scd);\r
-void InitSoundCombo(HWND hwndCombo, SoundComboData *scd);\r
-int SoundDialogWhichRadio(HWND hDlg);\r
-VOID SoundDialogSetEnables(HWND hDlg, int radio);\r
-char * SoundDialogGetName(HWND hDlg, int radio);\r
-void DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name);\r
-VOID ParseCommSettings(char *arg, DCB *dcb);\r
-VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);\r
-void InitCombo(HANDLE hwndCombo, ComboData *cd);\r
-void SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value);\r
-VOID SetLoadOptionEnables(HWND hDlg);\r
-VOID SetSaveOptionEnables(HWND hDlg);\r
-VOID SetTimeControlEnables(HWND hDlg);\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * General Options Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-\r
-LRESULT CALLBACK\r
-GeneralOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  static Boolean oldShowCoords;\r
-  static Boolean oldBlindfold;\r
-  static Boolean oldShowButtonBar;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-    oldShowCoords = appData.showCoords;\r
-    oldBlindfold  = appData.blindfold;\r
-    oldShowButtonBar = appData.showButtonBar;\r
-\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-\r
-    /* Initialize the dialog items */\r
-#define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))\r
-\r
-    CHECK_BOX(OPT_AlwaysOnTop, alwaysOnTop);\r
-    CHECK_BOX(OPT_AlwaysQueen, appData.alwaysPromoteToQueen);\r
-    CHECK_BOX(OPT_AnimateDragging, appData.animateDragging);\r
-    CHECK_BOX(OPT_AnimateMoving, appData.animate);\r
-    CHECK_BOX(OPT_AutoFlag, appData.autoCallFlag);\r
-    CHECK_BOX(OPT_AutoFlipView, appData.autoFlipView);\r
-    CHECK_BOX(OPT_AutoRaiseBoard, appData.autoRaiseBoard);\r
-    CHECK_BOX(OPT_Blindfold, appData.blindfold);\r
-    CHECK_BOX(OPT_HighlightDragging, appData.highlightDragging);\r
-    CHECK_BOX(OPT_HighlightLastMove, appData.highlightLastMove);\r
-    CHECK_BOX(OPT_PeriodicUpdates, appData.periodicUpdates);\r
-    CHECK_BOX(OPT_PonderNextMove, appData.ponderNextMove);\r
-    CHECK_BOX(OPT_PopupExitMessage, appData.popupExitMessage);\r
-    CHECK_BOX(OPT_PopupMoveErrors, appData.popupMoveErrors);\r
-    CHECK_BOX(OPT_ShowButtonBar, appData.showButtonBar);\r
-    CHECK_BOX(OPT_ShowCoordinates, appData.showCoords);\r
-    CHECK_BOX(OPT_ShowThinking, appData.showThinking);\r
-    CHECK_BOX(OPT_TestLegality, appData.testLegality);\r
-    CHECK_BOX(OPT_HideThinkFromHuman, appData.hideThinkingFromHuman);\r
-    CHECK_BOX(OPT_SaveExtPGN, appData.saveExtendedInfoInPGN);\r
-    CHECK_BOX(OPT_ExtraInfoInMoveHistory, appData.showEvalInMoveHistory);\r
-    CHECK_BOX(OPT_HighlightMoveArrow, appData.highlightMoveWithArrow);\r
-\r
-#undef CHECK_BOX\r
-\r
-    EnableWindow(GetDlgItem(hDlg, OPT_AutoFlag),\r
-                appData.icsActive || !appData.noChessProgram);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_AutoFlipView),\r
-                appData.icsActive || !appData.noChessProgram);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_PonderNextMove),\r
-                !appData.noChessProgram);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_PeriodicUpdates), \r
-                !appData.noChessProgram && !appData.icsActive);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_ShowThinking), \r
-                !appData.noChessProgram);\r
-    return TRUE;\r
-\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* Read changed options from the dialog box */\r
-      \r
-#define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))\r
-\r
-      alwaysOnTop                  = IS_CHECKED(OPT_AlwaysOnTop);\r
-      appData.alwaysPromoteToQueen = IS_CHECKED(OPT_AlwaysQueen);\r
-      appData.animateDragging      = IS_CHECKED(OPT_AnimateDragging);\r
-      appData.animate              = IS_CHECKED(OPT_AnimateMoving);\r
-      appData.autoCallFlag         = IS_CHECKED(OPT_AutoFlag);\r
-      appData.autoFlipView         = IS_CHECKED(OPT_AutoFlipView);\r
-      appData.autoRaiseBoard       = IS_CHECKED(OPT_AutoRaiseBoard);\r
-      appData.blindfold            = IS_CHECKED(OPT_Blindfold);\r
-      appData.highlightDragging    = IS_CHECKED(OPT_HighlightDragging);\r
-      appData.highlightLastMove    = IS_CHECKED(OPT_HighlightLastMove);\r
-      PeriodicUpdatesEvent(          IS_CHECKED(OPT_PeriodicUpdates));\r
-      PonderNextMoveEvent(           IS_CHECKED(OPT_PonderNextMove));\r
-      appData.popupExitMessage     = IS_CHECKED(OPT_PopupExitMessage);\r
-      appData.popupMoveErrors      = IS_CHECKED(OPT_PopupMoveErrors);\r
-      appData.showButtonBar        = IS_CHECKED(OPT_ShowButtonBar);\r
-      appData.showCoords           = IS_CHECKED(OPT_ShowCoordinates);\r
-      // [HGM] thinking: next three moved up\r
-      appData.saveExtendedInfoInPGN= IS_CHECKED(OPT_SaveExtPGN);\r
-      appData.hideThinkingFromHuman= IS_CHECKED(OPT_HideThinkFromHuman);\r
-      appData.showEvalInMoveHistory= IS_CHECKED(OPT_ExtraInfoInMoveHistory);\r
-#if 0\r
-      ShowThinkingEvent(             IS_CHECKED(OPT_ShowThinking));\r
-#else\r
-      appData.showThinking         = IS_CHECKED(OPT_ShowThinking);\r
-      ShowThinkingEvent(); // [HGM] thinking: tests four options\r
-#endif\r
-      appData.testLegality         = IS_CHECKED(OPT_TestLegality);\r
-      appData.highlightMoveWithArrow=IS_CHECKED(OPT_HighlightMoveArrow);\r
-\r
-#undef IS_CHECKED\r
-\r
-      SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
-                  0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
-#if AOT_CONSOLE\r
-      if (hwndConsole) {\r
-       SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
-                    0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
-      }\r
-#endif\r
-      if (!appData.highlightLastMove) {\r
-       ClearHighlights();\r
-       DrawPosition(FALSE, NULL);\r
-      }\r
-      /* \r
-       * for some reason the redraw seems smoother when we invalidate\r
-       * the board rect after the call to EndDialog()\r
-       */\r
-      EndDialog(hDlg, TRUE);\r
-\r
-      if (oldShowButtonBar != appData.showButtonBar) {\r
-       InitDrawingSizes(boardSize, 0);\r
-      } else if ((oldShowCoords != appData.showCoords) || \r
-                (oldBlindfold != appData.blindfold)) {\r
-       InvalidateRect(hwndMain, &boardRect, FALSE);\r
-      }\r
-\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID \r
-GeneralOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc;\r
-\r
-  lpProc = MakeProcInstance((FARPROC)GeneralOptionsDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_GeneralOptions), hwnd,\r
-           (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Board Options Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-const int SAMPLE_SQ_SIZE = 54;\r
-\r
-VOID\r
-ChangeBoardSize(BoardSize newSize)\r
-{\r
-  if (newSize != boardSize) {\r
-    boardSize = newSize;\r
-    InitDrawingSizes(boardSize, 0);\r
-  }\r
-}\r
-\r
-VOID\r
-PaintSampleSquare(\r
-    HWND     hwnd, \r
-    int      ctrlid, \r
-    COLORREF squareColor, \r
-    COLORREF pieceColor,\r
-    COLORREF squareOutlineColor,\r
-    COLORREF pieceDetailColor,\r
-    BOOL     isWhitePiece,\r
-    BOOL     isMono,\r
-    HBITMAP  pieces[3] \r
-    )\r
-{\r
-  HBRUSH  brushSquare;\r
-  HBRUSH  brushSquareOutline;\r
-  HBRUSH  brushPiece;\r
-  HBRUSH  brushPieceDetail;\r
-  HBRUSH  oldBrushPiece;\r
-  HBRUSH  oldBrushSquare;\r
-  HBITMAP oldBitmapMem;\r
-  HBITMAP oldBitmapTemp;\r
-  HBITMAP bufferBitmap;\r
-  RECT    rect;\r
-  HDC     hdcScreen, hdcMem, hdcTemp;\r
-  HPEN    pen, oldPen;\r
-  HWND    hCtrl = GetDlgItem(hwnd, ctrlid);\r
-  int     x, y;\r
-\r
-  const int SOLID   = 0;\r
-  const int WHITE   = 1;\r
-  const int OUTLINE = 2;\r
-  const int BORDER  = 4;\r
-\r
-  InvalidateRect(hCtrl, NULL, TRUE);\r
-  UpdateWindow(hCtrl);\r
-  GetClientRect(hCtrl, &rect);\r
-  x = rect.left + (BORDER / 2);\r
-  y = rect.top  + (BORDER / 2);\r
-  hdcScreen = GetDC(hCtrl);\r
-  hdcMem  = CreateCompatibleDC(hdcScreen);\r
-  hdcTemp = CreateCompatibleDC(hdcScreen);\r
-\r
-  bufferBitmap = CreateCompatibleBitmap(hdcScreen, rect.right-rect.left+1,\r
-                                       rect.bottom-rect.top+1);\r
-  oldBitmapMem = SelectObject(hdcMem, bufferBitmap);\r
-  if (!isMono) {\r
-    SelectPalette(hdcMem, hPal, FALSE);\r
-  }\r
-  brushSquare         = CreateSolidBrush(squareColor);\r
-  brushSquareOutline  = CreateSolidBrush(squareOutlineColor);\r
-  brushPiece          = CreateSolidBrush(pieceColor);\r
-  brushPieceDetail    = CreateSolidBrush(pieceDetailColor);\r
-\r
-  /* \r
-   * first draw the rectangle \r
-   */\r
-  pen      = CreatePen(PS_SOLID, BORDER, squareOutlineColor);\r
-  oldPen   = (HPEN)  SelectObject(hdcMem, pen);\r
-  oldBrushSquare = (HBRUSH)SelectObject(hdcMem, brushSquare);\r
-  Rectangle(hdcMem, rect.left, rect.top, rect.right, rect.bottom);\r
-\r
-  /* \r
-   * now draw the piece\r
-   */\r
-  if (isMono) {\r
-    oldBitmapTemp = SelectObject(hdcTemp, pieces[OUTLINE]);\r
-    BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, hdcTemp, 0, 0,\r
-          isWhitePiece ? SRCCOPY : NOTSRCCOPY);\r
-    SelectObject(hdcTemp, oldBitmapTemp);\r
-  } else {\r
-    if (isWhitePiece) {\r
-      oldBitmapTemp = SelectObject(hdcTemp, pieces[WHITE]);\r
-      oldBrushPiece = SelectObject(hdcMem, brushPiece);\r
-      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, \r
-            hdcTemp, 0, 0, 0x00B8074A);\r
-#if 0\r
-      /* Use pieceDetailColor for outline of white pieces */\r
-      SelectObject(hdcTemp, pieces[OUTLINE]);\r
-      SelectObject(hdcMem, brushPieceDetail);\r
-      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, \r
-            hdcTemp, 0, 0, 0x00B8074A);\r
-#else\r
-      /* Use black for outline of white pieces */\r
-      SelectObject(hdcTemp, pieces[OUTLINE]);\r
-      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, \r
-            hdcTemp, 0, 0, SRCAND);\r
-#endif\r
-    } else {\r
-#if 0\r
-      /* Use pieceDetailColor for details of black pieces */\r
-      /* Requires filled-in solid bitmaps (BLACK_PIECE class); the\r
-        WHITE_PIECE ones aren't always the right shape. */\r
-      oldBitmapTemp = SelectObject(hdcTemp, pieces[BLACK]);\r
-      oldBrushPiece = SelectObject(hdcMem, brushPieceDetail);\r
-      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, \r
-            hdcTemp, 0, 0, 0x00B8074A);\r
-      SelectObject(hdcTemp, pieces[SOLID]);\r
-      SelectObject(hdcMem, brushPiece);\r
-      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, \r
-            hdcTemp, 0, 0, 0x00B8074A);\r
-#else\r
-      /* Use square color for details of black pieces */\r
-      oldBitmapTemp = SelectObject(hdcTemp, pieces[SOLID]);\r
-      oldBrushPiece = SelectObject(hdcMem, brushPiece);\r
-      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, \r
-            hdcTemp, 0, 0, 0x00B8074A);\r
-#endif\r
-    }\r
-    SelectObject(hdcMem, oldBrushPiece);\r
-    SelectObject(hdcTemp, oldBitmapTemp);\r
-  }\r
-  /* \r
-   * copy the memory dc to the screen\r
-   */\r
-  SelectObject(hdcMem, bufferBitmap);\r
-  BitBlt(hdcScreen, rect.left, rect.top,\r
-        rect.right - rect.left,\r
-        rect.bottom - rect.top,\r
-        hdcMem, rect.left, rect.top, SRCCOPY);\r
-  SelectObject(hdcMem, oldBitmapMem);\r
-  /* \r
-   * clean up\r
-   */\r
-  SelectObject(hdcMem, oldBrushPiece);\r
-  SelectObject(hdcMem, oldPen);\r
-  DeleteObject(brushPiece);\r
-  DeleteObject(brushPieceDetail);\r
-  DeleteObject(brushSquare);\r
-  DeleteObject(brushSquareOutline);\r
-  DeleteObject(pen);\r
-  DeleteDC(hdcTemp);\r
-  DeleteDC(hdcMem);\r
-  ReleaseDC(hCtrl, hdcScreen);\r
-}\r
-\r
-\r
-VOID\r
-PaintColorBlock(HWND hwnd, int ctrlid, COLORREF color)\r
-{\r
-  HDC    hdc;\r
-  HBRUSH brush, oldBrush;\r
-  RECT   rect;\r
-  HWND   hCtrl = GetDlgItem(hwnd, ctrlid);\r
-\r
-  hdc = GetDC(hCtrl);\r
-  InvalidateRect(hCtrl, NULL, TRUE);\r
-  UpdateWindow(hCtrl);\r
-  GetClientRect(hCtrl, &rect);\r
-  brush = CreateSolidBrush(color);\r
-  oldBrush = (HBRUSH)SelectObject(hdc, brush);\r
-  Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);\r
-  SelectObject(hdc, oldBrush);\r
-  DeleteObject(brush);\r
-  ReleaseDC(hCtrl, hdc);\r
-}\r
-\r
-\r
-VOID\r
-SetBoardOptionEnables(HWND hDlg)\r
-{\r
-  if (IsDlgButtonChecked(hDlg, OPT_Monochrome)) {\r
-    ShowWindow(GetDlgItem(hDlg, OPT_LightSquareColor), SW_HIDE);\r
-    ShowWindow(GetDlgItem(hDlg, OPT_DarkSquareColor), SW_HIDE);\r
-    ShowWindow(GetDlgItem(hDlg, OPT_WhitePieceColor), SW_HIDE);\r
-    ShowWindow(GetDlgItem(hDlg, OPT_BlackPieceColor), SW_HIDE);\r
-\r
-    EnableWindow(GetDlgItem(hDlg, OPT_ChooseLightSquareColor), FALSE);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_ChooseDarkSquareColor), FALSE);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_ChooseWhitePieceColor), FALSE);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_ChooseBlackPieceColor), FALSE);\r
-  } else {\r
-    ShowWindow(GetDlgItem(hDlg, OPT_LightSquareColor), SW_SHOW);\r
-    ShowWindow(GetDlgItem(hDlg, OPT_DarkSquareColor), SW_SHOW);\r
-    ShowWindow(GetDlgItem(hDlg, OPT_WhitePieceColor), SW_SHOW);\r
-    ShowWindow(GetDlgItem(hDlg, OPT_BlackPieceColor), SW_SHOW);\r
-\r
-    EnableWindow(GetDlgItem(hDlg, OPT_ChooseLightSquareColor), TRUE);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_ChooseDarkSquareColor), TRUE);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_ChooseWhitePieceColor), TRUE);\r
-    EnableWindow(GetDlgItem(hDlg, OPT_ChooseBlackPieceColor), TRUE);\r
-  }\r
-}\r
-\r
-BoardSize \r
-BoardOptionsWhichRadio(HWND hDlg)\r
-{\r
-  return (IsDlgButtonChecked(hDlg, OPT_SizeTiny) ? SizeTiny :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeTeeny) ? SizeTeeny :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeDinky) ? SizeDinky :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizePetite) ? SizePetite :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeSlim) ? SizeSlim :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeSmall) ? SizeSmall :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeMediocre) ? SizeMediocre :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeMiddling) ? SizeMiddling :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeAverage) ? SizeAverage :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeModerate) ? SizeModerate :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeMedium) ? SizeMedium :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeBulky) ? SizeBulky :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeLarge) ? SizeLarge :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeBig) ? SizeBig :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeHuge) ? SizeHuge :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeGiant) ? SizeGiant :\r
-         (IsDlgButtonChecked(hDlg, OPT_SizeColossal) ? SizeColossal :\r
-          SizeTitanic )))))))))))))))));\r
-}\r
-\r
-LRESULT CALLBACK\r
-BoardOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  static Boolean  mono, white, flip;\r
-  static BoardSize size;\r
-  static COLORREF lsc, dsc, wpc, bpc, hsc, phc;\r
-  static HBITMAP pieces[3];\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-    /* Initialize the dialog items */\r
-    switch (boardSize) {\r
-    case SizeTiny:\r
-      CheckDlgButton(hDlg, OPT_SizeTiny, TRUE);\r
-      break;\r
-    case SizeTeeny:\r
-      CheckDlgButton(hDlg, OPT_SizeTeeny, TRUE);\r
-      break;\r
-    case SizeDinky:\r
-      CheckDlgButton(hDlg, OPT_SizeDinky, TRUE);\r
-      break;\r
-    case SizePetite:\r
-      CheckDlgButton(hDlg, OPT_SizePetite, TRUE);\r
-      break;\r
-    case SizeSlim:\r
-      CheckDlgButton(hDlg, OPT_SizeSlim, TRUE);\r
-      break;\r
-    case SizeSmall:\r
-      CheckDlgButton(hDlg, OPT_SizeSmall, TRUE);\r
-      break;\r
-    case SizeMediocre:\r
-      CheckDlgButton(hDlg, OPT_SizeMediocre, TRUE);\r
-      break;\r
-    case SizeMiddling:\r
-      CheckDlgButton(hDlg, OPT_SizeMiddling, TRUE);\r
-      break;\r
-    case SizeAverage:\r
-      CheckDlgButton(hDlg, OPT_SizeAverage, TRUE);\r
-      break;\r
-    case SizeModerate:\r
-      CheckDlgButton(hDlg, OPT_SizeModerate, TRUE);\r
-      break;\r
-    case SizeMedium:\r
-      CheckDlgButton(hDlg, OPT_SizeMedium, TRUE);\r
-      break;\r
-    case SizeBulky:\r
-      CheckDlgButton(hDlg, OPT_SizeBulky, TRUE);\r
-      break;\r
-    case SizeLarge:\r
-      CheckDlgButton(hDlg, OPT_SizeLarge, TRUE);\r
-      break;\r
-    case SizeBig:\r
-      CheckDlgButton(hDlg, OPT_SizeBig, TRUE);\r
-      break;\r
-    case SizeHuge:\r
-      CheckDlgButton(hDlg, OPT_SizeHuge, TRUE);\r
-      break;\r
-    case SizeGiant:\r
-      CheckDlgButton(hDlg, OPT_SizeGiant, TRUE);\r
-      break;\r
-    case SizeColossal:\r
-      CheckDlgButton(hDlg, OPT_SizeColossal, TRUE);\r
-      break;\r
-    case SizeTitanic:\r
-      CheckDlgButton(hDlg, OPT_SizeTitanic, TRUE);\r
-    }\r
-\r
-    if (appData.monoMode)\r
-      CheckDlgButton(hDlg, OPT_Monochrome, TRUE);\r
-\r
-    if (appData.allWhite)\r
-      CheckDlgButton(hDlg, OPT_AllWhite, TRUE);\r
-\r
-    if (appData.upsideDown)\r
-      CheckDlgButton(hDlg, OPT_UpsideDown, TRUE);\r
-\r
-    pieces[0] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "s");\r
-    pieces[1] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "w");\r
-    pieces[2] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "o");\r
-       \r
-    lsc = lightSquareColor;\r
-    dsc = darkSquareColor;\r
-    wpc = whitePieceColor;\r
-    bpc = blackPieceColor;\r
-    hsc = highlightSquareColor;\r
-    phc = premoveHighlightColor;\r
-    mono = appData.monoMode;\r
-    white= appData.allWhite;\r
-    flip = appData.upsideDown;\r
-    size = boardSize;\r
-\r
-    SetBoardOptionEnables(hDlg);\r
-    return TRUE;\r
-\r
-  case WM_PAINT:\r
-    PaintColorBlock(hDlg, OPT_LightSquareColor, lsc);\r
-    PaintColorBlock(hDlg, OPT_DarkSquareColor,  dsc);\r
-    PaintColorBlock(hDlg, OPT_WhitePieceColor,  wpc);\r
-    PaintColorBlock(hDlg, OPT_BlackPieceColor,  bpc);\r
-    PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc);\r
-    PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc);\r
-    PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
-       TRUE, mono, pieces);\r
-    PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
-       FALSE, mono, pieces);\r
-\r
-    return FALSE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* \r
-       * if we call EndDialog() after the call to ChangeBoardSize(),\r
-       * then ChangeBoardSize() does not take effect, although the new\r
-       * boardSize is saved. Go figure...\r
-       */\r
-      EndDialog(hDlg, TRUE);\r
-\r
-      size = BoardOptionsWhichRadio(hDlg);\r
-\r
-      /*\r
-       * did any settings change?\r
-       */\r
-      if (size != boardSize) {\r
-       ChangeBoardSize(size);\r
-      }\r
-\r
-      if ((mono != appData.monoMode) ||\r
-         (lsc  != lightSquareColor) ||\r
-         (dsc  != darkSquareColor) ||\r
-         (wpc  != whitePieceColor) ||\r
-         (bpc  != blackPieceColor) ||\r
-         (hsc  != highlightSquareColor) ||\r
-          (flip != appData.upsideDown) ||\r
-          (white != appData.allWhite) ||\r
-         (phc  != premoveHighlightColor)) {\r
-\r
-         lightSquareColor = lsc;\r
-         darkSquareColor = dsc;\r
-         whitePieceColor = wpc;\r
-         blackPieceColor = bpc;\r
-         highlightSquareColor = hsc;\r
-         premoveHighlightColor = phc;\r
-         appData.monoMode = mono;\r
-          appData.allWhite = white;\r
-          appData.upsideDown = flip;\r
-\r
-         InitDrawingColors();\r
-         InitDrawingSizes(boardSize, 0);\r
-         InvalidateRect(hwndMain, &boardRect, FALSE);\r
-      }\r
-      DeleteObject(pieces[0]);\r
-      DeleteObject(pieces[1]);\r
-      DeleteObject(pieces[2]);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      DeleteObject(pieces[0]);\r
-      DeleteObject(pieces[1]);\r
-      DeleteObject(pieces[2]);\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    case OPT_ChooseLightSquareColor:\r
-      if (ChangeColor(hDlg, &lsc)) \r
-       PaintColorBlock(hDlg, OPT_LightSquareColor, lsc);\r
-       PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
-           TRUE, mono, pieces);\r
-      break;\r
-\r
-    case OPT_ChooseDarkSquareColor:\r
-      if (ChangeColor(hDlg, &dsc)) \r
-       PaintColorBlock(hDlg, OPT_DarkSquareColor, dsc);\r
-       PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
-           FALSE, mono, pieces);\r
-      break;\r
-\r
-    case OPT_ChooseWhitePieceColor:\r
-      if (ChangeColor(hDlg, &wpc)) \r
-       PaintColorBlock(hDlg, OPT_WhitePieceColor, wpc);\r
-       PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
-           TRUE, mono, pieces);\r
-      break;\r
-\r
-    case OPT_ChooseBlackPieceColor:\r
-      if (ChangeColor(hDlg, &bpc)) \r
-       PaintColorBlock(hDlg, OPT_BlackPieceColor, bpc);\r
-       PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
-           FALSE, mono, pieces);\r
-      break;\r
-\r
-    case OPT_ChooseHighlightSquareColor:\r
-      if (ChangeColor(hDlg, &hsc)) \r
-       PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc);\r
-       PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
-           TRUE, mono, pieces);\r
-      break;\r
-\r
-    case OPT_ChoosePremoveHighlightColor:\r
-      if (ChangeColor(hDlg, &phc)) \r
-       PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc);\r
-       PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
-           FALSE, mono, pieces);\r
-      break;\r
-\r
-    case OPT_DefaultBoardColors:\r
-      lsc = ParseColorName(LIGHT_SQUARE_COLOR);\r
-      dsc = ParseColorName(DARK_SQUARE_COLOR);\r
-      wpc = ParseColorName(WHITE_PIECE_COLOR);\r
-      bpc = ParseColorName(BLACK_PIECE_COLOR);\r
-      hsc = ParseColorName(HIGHLIGHT_SQUARE_COLOR);\r
-      phc = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);\r
-      mono = FALSE;\r
-      white= FALSE;\r
-      flip = FALSE;\r
-      CheckDlgButton(hDlg, OPT_Monochrome, FALSE);\r
-      CheckDlgButton(hDlg, OPT_AllWhite,   FALSE);\r
-      CheckDlgButton(hDlg, OPT_UpsideDown, FALSE);\r
-      PaintColorBlock(hDlg, OPT_LightSquareColor, lsc);\r
-      PaintColorBlock(hDlg, OPT_DarkSquareColor,  dsc);\r
-      PaintColorBlock(hDlg, OPT_WhitePieceColor,  wpc);\r
-      PaintColorBlock(hDlg, OPT_BlackPieceColor,  bpc);\r
-      PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc);\r
-      PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc);\r
-      SetBoardOptionEnables(hDlg);\r
-      PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,\r
-         TRUE, mono, pieces);\r
-      PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,\r
-         FALSE, mono, pieces);\r
-      break;\r
-\r
-    case OPT_Monochrome:\r
-      mono = !mono;\r
-      SetBoardOptionEnables(hDlg);\r
-      break;\r
-\r
-    case OPT_AllWhite:\r
-      white = !white;\r
-      SetBoardOptionEnables(hDlg);\r
-      break;\r
-\r
-    case OPT_UpsideDown:\r
-      flip = !flip;\r
-      SetBoardOptionEnables(hDlg);\r
-      break;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-\r
-VOID\r
-BoardOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc = MakeProcInstance((FARPROC)BoardOptionsDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_BoardOptions), hwnd,\r
-         (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-VariantClass\r
-VariantWhichRadio(HWND hDlg)\r
-{\r
-  return (IsDlgButtonChecked(hDlg, OPT_VariantFairy) ? VariantFairy :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantGothic) ? VariantGothic :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantCrazyhouse) ? VariantCrazyhouse :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantBughouse) ? VariantBughouse :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantCourier) ? VariantCourier :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantShatranj) ? VariantShatranj :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantShogi) ? VariantShogi :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantXiangqi) ? VariantXiangqi :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantCapablanca) ? VariantCapablanca :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantTwoKings) ? VariantTwoKings :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantKnightmate) ? VariantKnightmate :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantLosers) ? VariantLosers :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantSuicide) ? VariantSuicide :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantAtomic) ? VariantAtomic :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantShatranj) ? VariantShatranj :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantFRC) ? VariantFischeRandom :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantCylinder) ? VariantCylinder :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantFalcon) ? VariantFalcon :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantCRC) ? VariantCapaRandom :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantSuper) ? VariantSuper :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantBerolina) ? VariantBerolina :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantJanus) ? VariantJanus :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantWildcastle) ? VariantWildCastle :\r
-         (IsDlgButtonChecked(hDlg, OPT_VariantNocastle) ? VariantNoCastle :\r
-          VariantNormal ))))))))))))))))))))))));\r
-}\r
-\r
-LRESULT CALLBACK\r
-NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  static Boolean  mono;\r
-  static VariantClass v;\r
-  static COLORREF lsc, dsc, wpc, bpc, hsc, phc;\r
-  static HBITMAP pieces[3];\r
-  static int n1_ok, n2_ok, n3_ok;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-    /* Initialize the dialog items */\r
-    switch (gameInfo.variant) {\r
-    case VariantNormal:\r
-      CheckDlgButton(hDlg, OPT_VariantNormal, TRUE);\r
-      break;\r
-    case VariantCrazyhouse:\r
-      CheckDlgButton(hDlg, OPT_VariantCrazyhouse, TRUE);\r
-      break;\r
-    case VariantBughouse:\r
-      CheckDlgButton(hDlg, OPT_VariantBughouse, TRUE);\r
-      break;\r
-    case VariantShogi:\r
-      CheckDlgButton(hDlg, OPT_VariantShogi, TRUE);\r
-      break;\r
-    case VariantXiangqi:\r
-      CheckDlgButton(hDlg, OPT_VariantXiangqi, TRUE);\r
-      break;\r
-    case VariantCapablanca:\r
-      CheckDlgButton(hDlg, OPT_VariantCapablanca, TRUE);\r
-      break;\r
-    case VariantGothic:\r
-      CheckDlgButton(hDlg, OPT_VariantGothic, TRUE);\r
-      break;\r
-    case VariantCourier:\r
-      CheckDlgButton(hDlg, OPT_VariantCourier, TRUE);\r
-      break;\r
-    case VariantKnightmate:\r
-      CheckDlgButton(hDlg, OPT_VariantKnightmate, TRUE);\r
-      break;\r
-    case VariantTwoKings:\r
-      CheckDlgButton(hDlg, OPT_VariantTwoKings, TRUE);\r
-      break;\r
-    case VariantFairy:\r
-      CheckDlgButton(hDlg, OPT_VariantFairy, TRUE);\r
-      break;\r
-    case VariantAtomic:\r
-      CheckDlgButton(hDlg, OPT_VariantAtomic, TRUE);\r
-      break;\r
-    case VariantSuicide:\r
-      CheckDlgButton(hDlg, OPT_VariantSuicide, TRUE);\r
-      break;\r
-    case VariantLosers:\r
-      CheckDlgButton(hDlg, OPT_VariantLosers, TRUE);\r
-      break;\r
-    case VariantShatranj:\r
-      CheckDlgButton(hDlg, OPT_VariantShatranj, TRUE);\r
-      break;\r
-    case VariantFischeRandom:\r
-      CheckDlgButton(hDlg, OPT_VariantFRC, TRUE);\r
-      break;\r
-    case VariantCapaRandom:\r
-      CheckDlgButton(hDlg, OPT_VariantCRC, TRUE);\r
-      break;\r
-    case VariantFalcon:\r
-      CheckDlgButton(hDlg, OPT_VariantFalcon, TRUE);\r
-      break;\r
-    case VariantCylinder:\r
-      CheckDlgButton(hDlg, OPT_VariantCylinder, TRUE);\r
-      break;\r
-    case Variant3Check:\r
-    case VariantSuper:\r
-      CheckDlgButton(hDlg, OPT_VariantSuper, TRUE);\r
-      break;\r
-    case VariantBerolina:\r
-      CheckDlgButton(hDlg, OPT_VariantBerolina, TRUE);\r
-      break;\r
-    case VariantJanus:\r
-      CheckDlgButton(hDlg, OPT_VariantJanus, TRUE);\r
-      break;\r
-    case VariantWildCastle:\r
-      CheckDlgButton(hDlg, OPT_VariantWildcastle, TRUE);\r
-      break;\r
-    case VariantNoCastle:\r
-      CheckDlgButton(hDlg, OPT_VariantNocastle, TRUE);\r
-      break;\r
-    }\r
-\r
-    SetDlgItemInt( hDlg, IDC_Files, -1, TRUE );\r
-    SendDlgItemMessage( hDlg, IDC_Files, EM_SETSEL, 0, -1 );\r
-\r
-    SetDlgItemInt( hDlg, IDC_Ranks, -1, TRUE );\r
-    SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 );\r
-\r
-    SetDlgItemInt( hDlg, IDC_Holdings, -1, TRUE );\r
-    SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 );\r
-\r
-    n1_ok = n2_ok = n3_ok = FALSE;\r
-\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* \r
-       * if we call EndDialog() after the call to ChangeBoardSize(),\r
-       * then ChangeBoardSize() does not take effect, although the new\r
-       * boardSize is saved. Go figure...\r
-       */\r
-      EndDialog(hDlg, TRUE);\r
-\r
-      v = VariantWhichRadio(hDlg);\r
-      if(!appData.noChessProgram) { char *name = VariantName(v), buf[MSG_SIZ];\r
-       if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {\r
-           /* [HGM] in protocol 2 we check if variant is suported by engine */\r
-           sprintf(buf, "Variant %s not supported by %s", name, first.tidy);\r
-           DisplayError(buf, 0);\r
-           return TRUE; /* treat as "Cancel" if first engine does not support it */\r
-       } else\r
-       if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {\r
-           sprintf(buf, "Warning: second engine (%s) does not support this!", second.tidy);\r
-           DisplayError(buf, 0);   /* use of second engine is optional; only warn user */\r
-       }\r
-      }\r
-\r
-      gameInfo.variant = v;\r
-      appData.variant = VariantName(v);\r
-\r
-      appData.NrFiles = (int) GetDlgItemInt(hDlg, IDC_Files, NULL, FALSE );\r
-      appData.NrRanks = (int) GetDlgItemInt(hDlg, IDC_Ranks, NULL, FALSE );\r
-      appData.holdingsSize = (int) GetDlgItemInt(hDlg, IDC_Holdings, NULL, FALSE );\r
-\r
-      if(!n1_ok) appData.NrFiles = -1;\r
-      if(!n2_ok) appData.NrRanks = -1;\r
-      if(!n3_ok) appData.holdingsSize = -1;\r
-\r
-      shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */\r
-      startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */\r
-      appData.pieceToCharTable = NULL;\r
-      Reset(TRUE, TRUE);\r
-\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    case IDC_Ranks:\r
-    case IDC_Files:\r
-    case IDC_Holdings:\r
-        if( HIWORD(wParam) == EN_CHANGE ) {\r
-\r
-            GetDlgItemInt(hDlg, IDC_Files, &n1_ok, FALSE );\r
-            GetDlgItemInt(hDlg, IDC_Ranks, &n2_ok, FALSE );\r
-            GetDlgItemInt(hDlg, IDC_Holdings, &n3_ok, FALSE );\r
-\r
-            /*EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok ? TRUE : FALSE );*/\r
-        }\r
-        return TRUE;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-\r
-VOID\r
-NewVariantPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc = MakeProcInstance((FARPROC)NewVariantDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_NewVariant), hwnd,\r
-         (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * ICS Options Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-BOOL APIENTRY\r
-MyCreateFont(HWND hwnd, MyFont *font)\r
-{\r
-  CHOOSEFONT cf;\r
-  HFONT hf;\r
-\r
-  /* Initialize members of the CHOOSEFONT structure. */\r
-  cf.lStructSize = sizeof(CHOOSEFONT);\r
-  cf.hwndOwner = hwnd;\r
-  cf.hDC = (HDC)NULL;\r
-  cf.lpLogFont = &font->lf;\r
-  cf.iPointSize = 0;\r
-  cf.Flags = CF_SCREENFONTS|/*CF_ANSIONLY|*/CF_INITTOLOGFONTSTRUCT;\r
-  cf.rgbColors = RGB(0,0,0);\r
-  cf.lCustData = 0L;\r
-  cf.lpfnHook = (LPCFHOOKPROC)NULL;\r
-  cf.lpTemplateName = (LPSTR)NULL;\r
-  cf.hInstance = (HINSTANCE) NULL;\r
-  cf.lpszStyle = (LPSTR)NULL;\r
-  cf.nFontType = SCREEN_FONTTYPE;\r
-  cf.nSizeMin = 0;\r
-  cf.nSizeMax = 0;\r
-\r
-  /* Display the CHOOSEFONT common-dialog box. */\r
-  if (!ChooseFont(&cf)) {\r
-    return FALSE;\r
-  }\r
-\r
-  /* Create a logical font based on the user's   */\r
-  /* selection and return a handle identifying   */\r
-  /* that font. */\r
-  hf = CreateFontIndirect(cf.lpLogFont);\r
-  if (hf == NULL) {\r
-    return FALSE;\r
-  }\r
-\r
-  font->hf = hf;\r
-  font->mfp.pointSize = (float) (cf.iPointSize / 10.0);\r
-  font->mfp.bold = (font->lf.lfWeight >= FW_BOLD);\r
-  font->mfp.italic = font->lf.lfItalic;\r
-  font->mfp.underline = font->lf.lfUnderline;\r
-  font->mfp.strikeout = font->lf.lfStrikeOut;\r
-  strcpy(font->mfp.faceName, font->lf.lfFaceName);\r
-  return TRUE;\r
-}\r
-\r
-\r
-VOID\r
-UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca)\r
-{\r
-  CHARFORMAT cf;\r
-  cf.cbSize = sizeof(CHARFORMAT);\r
-  cf.dwMask = \r
-    CFM_COLOR|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|CFM_FACE|CFM_SIZE;\r
-  cf.crTextColor = mca->color;\r
-  cf.dwEffects = mca->effects;\r
-  strcpy(cf.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName);\r
-  /* \r
-   * The 20.0 below is in fact documented. yHeight is expressed in twips.\r
-   * A twip is 1/20 of a font's point size. See documentation of CHARFORMAT.\r
-   * --msw\r
-   */\r
-  cf.yHeight = (int)(font[boardSize][CONSOLE_FONT]->mfp.pointSize * 20.0 + 0.5);\r
-  cf.bCharSet = DEFAULT_CHARSET; /* should be ignored anyway */\r
-  cf.bPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
-  SendDlgItemMessage(hDlg, id, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
-}\r
-\r
-LRESULT CALLBACK\r
-ColorizeTextDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  static MyColorizeAttribs mca;\r
-  static ColorClass cc;\r
-  COLORREF background = (COLORREF)0;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG:\r
-    cc = (ColorClass)lParam;\r
-    mca = colorizeAttribs[cc];\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-    /* Initialize the dialog items */\r
-    CheckDlgButton(hDlg, OPT_Bold, (mca.effects & CFE_BOLD) != 0);\r
-    CheckDlgButton(hDlg, OPT_Italic, (mca.effects & CFE_ITALIC) != 0);\r
-    CheckDlgButton(hDlg, OPT_Underline, (mca.effects & CFE_UNDERLINE) != 0);\r
-    CheckDlgButton(hDlg, OPT_Strikeout, (mca.effects & CFE_STRIKEOUT) != 0);\r
-\r
-    /* get the current background color from the parent window */\r
-    SendMessage(GetWindow(hDlg, GW_OWNER),WM_COMMAND, \r
-               (WPARAM)WM_USER_GetConsoleBackground, \r
-               (LPARAM)&background);\r
-\r
-    /* set the background color */\r
-    SendDlgItemMessage(hDlg, OPT_Sample, EM_SETBKGNDCOLOR, FALSE, background);\r
-\r
-    SetDlgItemText(hDlg, OPT_Sample, mca.name);\r
-    UpdateSampleText(hDlg, OPT_Sample, &mca);\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* Read changed options from the dialog box */\r
-      colorizeAttribs[cc] = mca;\r
-      textAttribs[cc].color = mca.color;\r
-      textAttribs[cc].effects = mca.effects;\r
-      Colorize(currentColorClass, TRUE);\r
-      if (cc == ColorNormal) {\r
-       CHARFORMAT cf;\r
-       cf.cbSize = sizeof(CHARFORMAT);\r
-       cf.dwMask = CFM_COLOR;\r
-       cf.crTextColor = mca.color;\r
-       SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, \r
-         EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
-      }\r
-      EndDialog(hDlg, TRUE);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    case OPT_ChooseColor:\r
-      ChangeColor(hDlg, &mca.color);\r
-      UpdateSampleText(hDlg, OPT_Sample, &mca);\r
-      return TRUE;\r
-\r
-    default:\r
-      mca.effects =\r
-       (IsDlgButtonChecked(hDlg, OPT_Bold) ? CFE_BOLD : 0) |\r
-       (IsDlgButtonChecked(hDlg, OPT_Italic) ? CFE_ITALIC : 0) |\r
-       (IsDlgButtonChecked(hDlg, OPT_Underline) ? CFE_UNDERLINE : 0) |\r
-       (IsDlgButtonChecked(hDlg, OPT_Strikeout) ? CFE_STRIKEOUT : 0);\r
-      UpdateSampleText(hDlg, OPT_Sample, &mca);\r
-      break;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID\r
-ColorizeTextPopup(HWND hwnd, ColorClass cc)\r
-{\r
-  FARPROC lpProc;\r
-\r
-  lpProc = MakeProcInstance((FARPROC)ColorizeTextDialog, hInst);\r
-  DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_Colorize),\r
-    hwnd, (DLGPROC)lpProc, (LPARAM) cc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-VOID\r
-SetIcsOptionEnables(HWND hDlg)\r
-{\r
-#define ENABLE_DLG_ITEM(x,y) EnableWindow(GetDlgItem(hDlg,(x)), (y))\r
-\r
-  UINT state = IsDlgButtonChecked(hDlg, OPT_Premove);\r
-  ENABLE_DLG_ITEM(OPT_PremoveWhite, state);\r
-  ENABLE_DLG_ITEM(OPT_PremoveWhiteText, state);\r
-  ENABLE_DLG_ITEM(OPT_PremoveBlack, state);\r
-  ENABLE_DLG_ITEM(OPT_PremoveBlackText, state);\r
-\r
-  ENABLE_DLG_ITEM(OPT_IcsAlarmTime, IsDlgButtonChecked(hDlg, OPT_IcsAlarm));\r
-\r
-#undef ENABLE_DLG_ITEM\r
-}\r
-\r
-\r
-LRESULT CALLBACK\r
-IcsOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  char buf[MSG_SIZ];\r
-  int number;\r
-  int i;\r
-  static COLORREF cbc;\r
-  static MyColorizeAttribs *mca;\r
-  COLORREF *colorref;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-\r
-    mca = colorizeAttribs;\r
-\r
-    for (i=0; i < NColorClasses - 1; i++) {\r
-      mca[i].color   = textAttribs[i].color;\r
-      mca[i].effects = textAttribs[i].effects;\r
-    }\r
-    cbc = consoleBackgroundColor;\r
-\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-\r
-    /* Initialize the dialog items */\r
-#define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))\r
-\r
-    CHECK_BOX(OPT_AutoComment, appData.autoComment);\r
-    CHECK_BOX(OPT_AutoObserve, appData.autoObserve);\r
-    CHECK_BOX(OPT_GetMoveList, appData.getMoveList);\r
-    CHECK_BOX(OPT_LocalLineEditing, appData.localLineEditing);\r
-    CHECK_BOX(OPT_QuietPlay, appData.quietPlay);\r
-    CHECK_BOX(OPT_Premove, appData.premove);\r
-    CHECK_BOX(OPT_PremoveWhite, appData.premoveWhite);\r
-    CHECK_BOX(OPT_PremoveBlack, appData.premoveBlack);\r
-    CHECK_BOX(OPT_IcsAlarm, appData.icsAlarm);\r
-    CHECK_BOX(OPT_DontColorize, !appData.colorize);\r
-\r
-#undef CHECK_BOX\r
-\r
-    sprintf(buf, "%d", appData.icsAlarmTime / 1000);\r
-    SetDlgItemText(hDlg, OPT_IcsAlarmTime, buf);\r
-    SetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText);\r
-    SetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText);\r
-\r
-    SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);\r
-    SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);\r
-    SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);\r
-    SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);\r
-    SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);\r
-    SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);\r
-    SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);\r
-    SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);\r
-    SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);\r
-    SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);\r
-\r
-    SetDlgItemText(hDlg, OPT_SampleShout,     mca[ColorShout].name);\r
-    SetDlgItemText(hDlg, OPT_SampleSShout,    mca[ColorSShout].name);\r
-    SetDlgItemText(hDlg, OPT_SampleChannel1,  mca[ColorChannel1].name);\r
-    SetDlgItemText(hDlg, OPT_SampleChannel,   mca[ColorChannel].name);\r
-    SetDlgItemText(hDlg, OPT_SampleKibitz,    mca[ColorKibitz].name);\r
-    SetDlgItemText(hDlg, OPT_SampleTell,      mca[ColorTell].name);\r
-    SetDlgItemText(hDlg, OPT_SampleChallenge, mca[ColorChallenge].name);\r
-    SetDlgItemText(hDlg, OPT_SampleRequest,   mca[ColorRequest].name);\r
-    SetDlgItemText(hDlg, OPT_SampleSeek,      mca[ColorSeek].name);\r
-    SetDlgItemText(hDlg, OPT_SampleNormal,    mca[ColorNormal].name);\r
-\r
-    UpdateSampleText(hDlg, OPT_SampleShout,     &mca[ColorShout]);\r
-    UpdateSampleText(hDlg, OPT_SampleSShout,    &mca[ColorSShout]);\r
-    UpdateSampleText(hDlg, OPT_SampleChannel1,  &mca[ColorChannel1]);\r
-    UpdateSampleText(hDlg, OPT_SampleChannel,   &mca[ColorChannel]);\r
-    UpdateSampleText(hDlg, OPT_SampleKibitz,    &mca[ColorKibitz]);\r
-    UpdateSampleText(hDlg, OPT_SampleTell,      &mca[ColorTell]);\r
-    UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);\r
-    UpdateSampleText(hDlg, OPT_SampleRequest,   &mca[ColorRequest]);\r
-    UpdateSampleText(hDlg, OPT_SampleSeek,      &mca[ColorSeek]);\r
-    UpdateSampleText(hDlg, OPT_SampleNormal,    &mca[ColorNormal]);\r
-\r
-    SetIcsOptionEnables(hDlg);\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-\r
-    case WM_USER_GetConsoleBackground: \r
-      /* the ColorizeTextDialog needs the current background color */\r
-      colorref = (COLORREF *)lParam;\r
-      *colorref = cbc;\r
-      return FALSE;\r
-\r
-    case IDOK:\r
-      /* Read changed options from the dialog box */\r
-      GetDlgItemText(hDlg, OPT_IcsAlarmTime, buf, MSG_SIZ);\r
-      if (sscanf(buf, "%d", &number) != 1 || (number < 0)){\r
-         MessageBox(hDlg, "Invalid ICS Alarm Time",\r
-                    "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
-         return FALSE;\r
-      }\r
-\r
-#define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))\r
-\r
-      appData.icsAlarm         = IS_CHECKED(OPT_IcsAlarm);\r
-      appData.premove          = IS_CHECKED(OPT_Premove);\r
-      appData.premoveWhite     = IS_CHECKED(OPT_PremoveWhite);\r
-      appData.premoveBlack     = IS_CHECKED(OPT_PremoveBlack);\r
-      appData.autoComment      = IS_CHECKED(OPT_AutoComment);\r
-      appData.autoObserve      = IS_CHECKED(OPT_AutoObserve);\r
-      appData.getMoveList      = IS_CHECKED(OPT_GetMoveList);\r
-      appData.localLineEditing = IS_CHECKED(OPT_LocalLineEditing);\r
-      appData.quietPlay        = IS_CHECKED(OPT_QuietPlay);\r
-\r
-#undef IS_CHECKED\r
-\r
-      appData.icsAlarmTime = number * 1000;\r
-      GetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText, 5);\r
-      GetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText, 5);\r
-\r
-      if (appData.localLineEditing) {\r
-       DontEcho();\r
-       EchoOn();\r
-      } else {\r
-       DoEcho();\r
-       EchoOff();\r
-      }\r
-\r
-      appData.colorize =\r
-       (Boolean)!IsDlgButtonChecked(hDlg, OPT_DontColorize);\r
-\r
-      if (!appData.colorize) {\r
-       CHARFORMAT cf;\r
-       COLORREF background = ParseColorName(COLOR_BKGD);\r
-       /*\r
-       SetDefaultTextAttribs();\r
-        Colorize(currentColorClass);\r
-       */\r
-       cf.cbSize = sizeof(CHARFORMAT);\r
-       cf.dwMask = CFM_COLOR;\r
-       cf.crTextColor = ParseColorName(COLOR_NORMAL);\r
-\r
-       SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, \r
-         EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
-        SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
-         EM_SETBKGNDCOLOR, FALSE, background);\r
-       SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, \r
-         EM_SETBKGNDCOLOR, FALSE, background);\r
-      }\r
-\r
-      if (cbc != consoleBackgroundColor) {\r
-       consoleBackgroundColor = cbc;\r
-       if (appData.colorize) {\r
-         SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
-           EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
-         SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, \r
-           EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
-       }\r
-      }\r
-\r
-      for (i=0; i < NColorClasses - 1; i++) {\r
-       textAttribs[i].color   = mca[i].color;\r
-       textAttribs[i].effects = mca[i].effects;\r
-      }\r
-\r
-      EndDialog(hDlg, TRUE);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    case OPT_ChooseShoutColor:\r
-      ColorizeTextPopup(hDlg, ColorShout);\r
-      UpdateSampleText(hDlg, OPT_SampleShout, &mca[ColorShout]);\r
-      break;\r
-\r
-    case OPT_ChooseSShoutColor:\r
-      ColorizeTextPopup(hDlg, ColorSShout);\r
-      UpdateSampleText(hDlg, OPT_SampleSShout, &mca[ColorSShout]);\r
-      break;\r
-\r
-    case OPT_ChooseChannel1Color:\r
-      ColorizeTextPopup(hDlg, ColorChannel1);\r
-      UpdateSampleText(hDlg, OPT_SampleChannel1, \r
-                      &colorizeAttribs[ColorChannel1]);\r
-      break;\r
-\r
-    case OPT_ChooseChannelColor:\r
-      ColorizeTextPopup(hDlg, ColorChannel);\r
-      UpdateSampleText(hDlg, OPT_SampleChannel, &mca[ColorChannel]);\r
-      break;\r
-\r
-    case OPT_ChooseKibitzColor:\r
-      ColorizeTextPopup(hDlg, ColorKibitz);\r
-      UpdateSampleText(hDlg, OPT_SampleKibitz, &mca[ColorKibitz]);\r
-      break;\r
-\r
-    case OPT_ChooseTellColor:\r
-      ColorizeTextPopup(hDlg, ColorTell);\r
-      UpdateSampleText(hDlg, OPT_SampleTell, &mca[ColorTell]);\r
-      break;\r
-\r
-    case OPT_ChooseChallengeColor:\r
-      ColorizeTextPopup(hDlg, ColorChallenge);\r
-      UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);\r
-      break;\r
-\r
-    case OPT_ChooseRequestColor:\r
-      ColorizeTextPopup(hDlg, ColorRequest);\r
-      UpdateSampleText(hDlg, OPT_SampleRequest, &mca[ColorRequest]);\r
-      break;\r
-\r
-    case OPT_ChooseSeekColor:\r
-      ColorizeTextPopup(hDlg, ColorSeek);\r
-      UpdateSampleText(hDlg, OPT_SampleSeek, &mca[ColorSeek]);\r
-      break;\r
-\r
-    case OPT_ChooseNormalColor:\r
-      ColorizeTextPopup(hDlg, ColorNormal);\r
-      UpdateSampleText(hDlg, OPT_SampleNormal, &mca[ColorNormal]);\r
-      break;\r
-\r
-    case OPT_ChooseBackgroundColor:\r
-      if (ChangeColor(hDlg, &cbc)) {\r
-       SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);\r
-       SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);\r
-       SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);\r
-       SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);\r
-       SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);\r
-       SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);\r
-       SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);\r
-       SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);\r
-       SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);\r
-       SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);\r
-      }\r
-      break;\r
-\r
-    case OPT_DefaultColors:\r
-      for (i=0; i < NColorClasses - 1; i++)\r
-       ParseAttribs(&mca[i].color, \r
-                    &mca[i].effects,\r
-                    defaultTextAttribs[i]);\r
-\r
-      cbc = ParseColorName(COLOR_BKGD);\r
-      SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);\r
-      SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);\r
-      SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);\r
-      SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);\r
-      SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);\r
-      SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);\r
-      SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);\r
-      SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);\r
-      SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);\r
-      SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);\r
-\r
-      UpdateSampleText(hDlg, OPT_SampleShout,     &mca[ColorShout]);\r
-      UpdateSampleText(hDlg, OPT_SampleSShout,    &mca[ColorSShout]);\r
-      UpdateSampleText(hDlg, OPT_SampleChannel1,  &mca[ColorChannel1]);\r
-      UpdateSampleText(hDlg, OPT_SampleChannel,   &mca[ColorChannel]);\r
-      UpdateSampleText(hDlg, OPT_SampleKibitz,    &mca[ColorKibitz]);\r
-      UpdateSampleText(hDlg, OPT_SampleTell,      &mca[ColorTell]);\r
-      UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);\r
-      UpdateSampleText(hDlg, OPT_SampleRequest,   &mca[ColorRequest]);\r
-      UpdateSampleText(hDlg, OPT_SampleSeek,      &mca[ColorSeek]);\r
-      UpdateSampleText(hDlg, OPT_SampleNormal,    &mca[ColorNormal]);\r
-      break;\r
-\r
-    default:\r
-      SetIcsOptionEnables(hDlg);\r
-      break;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID\r
-IcsOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc = MakeProcInstance((FARPROC)IcsOptionsDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_IcsOptions), hwnd,\r
-           (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Fonts Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-VOID\r
-SetSampleFontText(HWND hwnd, int id, const MyFont *mf)\r
-{\r
-  char buf[MSG_SIZ];\r
-  HWND hControl;\r
-  HDC hdc;\r
-  CHARFORMAT cf;\r
-  SIZE size;\r
-  RECT rectClient, rectFormat;\r
-  HFONT oldFont;\r
-  POINT center;\r
-  int len;\r
-\r
-  len = sprintf(buf, "%.0f pt. %s%s%s\n",\r
-               mf->mfp.pointSize, mf->mfp.faceName,\r
-               mf->mfp.bold ? " bold" : "",\r
-               mf->mfp.italic ? " italic" : "");\r
-  SetDlgItemText(hwnd, id, buf);\r
-\r
-  hControl = GetDlgItem(hwnd, id);\r
-  hdc = GetDC(hControl);\r
-  SetMapMode(hdc, MM_TEXT);    /* 1 pixel == 1 logical unit */\r
-  oldFont = SelectObject(hdc, mf->hf);\r
-  \r
-  /* get number of logical units necessary to display font name */\r
-  GetTextExtentPoint32(hdc, buf, len, &size);\r
-\r
-  /* calculate formatting rectangle in the rich edit control.  \r
-   * May be larger or smaller than the actual control.\r
-   */\r
-  GetClientRect(hControl, &rectClient);\r
-  center.x = (rectClient.left + rectClient.right) / 2;\r
-  center.y = (rectClient.top  + rectClient.bottom) / 2;\r
-  rectFormat.top    = center.y - (size.cy / 2) - 1;\r
-  rectFormat.bottom = center.y + (size.cy / 2) + 1;\r
-  rectFormat.left   = center.x - (size.cx / 2) - 1;\r
-  rectFormat.right  = center.x + (size.cx / 2) + 1;\r
-\r
-#if 0\r
-  fprintf(debugFP, "\nfont: %s\n"\r
-                   "center.x   %d, centerY %d\n"\r
-                  "size.cx    %d, size.cy %d\n"\r
-                  "client.top %d, bottom %d, left %d, right %d\n"\r
-                  "format.top %d, bottom %d, left %d, right %d\n",\r
-                  buf,\r
-                  center.x, center.y,\r
-                  size.cx, size.cy,\r
-                  rectClient.top, rectClient.bottom, rectClient.left,\r
-                  rectClient.right,\r
-                  rectFormat.top, rectFormat.bottom, rectFormat.left,\r
-                  rectFormat.right);\r
-#endif\r
-\r
-  cf.cbSize = sizeof(CHARFORMAT);\r
-  cf.dwMask = CFM_FACE|CFM_SIZE|CFM_CHARSET|CFM_BOLD|CFM_ITALIC;\r
-  cf.dwEffects = 0;\r
-  if (mf->lf.lfWeight == FW_BOLD) cf.dwEffects |= CFE_BOLD;\r
-  if (mf->lf.lfItalic) cf.dwEffects |= CFE_ITALIC;\r
-  strcpy(cf.szFaceName, mf->mfp.faceName);\r
-  /*\r
-   * yHeight is expressed in twips.  A twip is 1/20 of a font's point\r
-   * size. See documentation of CHARFORMAT.  --msw\r
-   */\r
-  cf.yHeight = (int)(mf->mfp.pointSize * 20.0 + 0.5);\r
-  cf.bCharSet = mf->lf.lfCharSet;\r
-  cf.bPitchAndFamily = mf->lf.lfPitchAndFamily;\r
-\r
-  /* format the text in the rich edit control */\r
-  SendMessage(hControl, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cf);\r
-  SendMessage(hControl, EM_SETRECT, (WPARAM)0, (LPARAM) &rectFormat);\r
-\r
-  /* clean up */\r
-  SelectObject(hdc, oldFont);\r
-  ReleaseDC(hControl, hdc);\r
-}\r
-\r
-VOID\r
-CopyFont(MyFont *dest, const MyFont *src)\r
-{\r
-  dest->mfp.pointSize = src->mfp.pointSize;\r
-  dest->mfp.bold      = src->mfp.bold;\r
-  dest->mfp.italic    = src->mfp.italic;\r
-  dest->mfp.underline = src->mfp.underline;\r
-  dest->mfp.strikeout = src->mfp.strikeout;\r
-  lstrcpy(dest->mfp.faceName, src->mfp.faceName);\r
-  CreateFontInMF(dest);\r
-}\r
-\r
-\r
-LRESULT CALLBACK\r
-FontOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  static MyFont workFont[NUM_FONTS];\r
-  static BOOL firstPaint;\r
-  int i;\r
-  RECT rect;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG:\r
-\r
-    /* copy the current font settings into a working copy */\r
-    for (i=0; i < NUM_FONTS; i++)\r
-      CopyFont(&workFont[i], font[boardSize][i]);\r
-\r
-    if (!appData.icsActive)\r
-      EnableWindow(GetDlgItem(hDlg, OPT_ChooseConsoleFont), FALSE);\r
-\r
-    firstPaint = TRUE; /* see rant below */\r
-\r
-    /* If I don't call SetFocus(), the dialog won't respond to the keyboard\r
-     * when first drawn. Why is this the only dialog that behaves this way? Is\r
-     * is the WM_PAINT stuff below?? Sigh...\r
-     */\r
-    SetFocus(GetDlgItem(hDlg, IDOK));\r
-    break;\r
-\r
-  case WM_PAINT:\r
-    /* This should not be necessary. However, if SetSampleFontText() is called\r
-     * in response to WM_INITDIALOG, the strings are not properly centered in\r
-     * the controls when the dialog first appears. I can't figure out why, so\r
-     * this is the workaround.  --msw\r
-     */\r
-    if (firstPaint) {\r
-      SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);\r
-      firstPaint = FALSE;\r
-    }\r
-    break;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-\r
-    case IDOK:\r
-      /* again, it seems to avoid redraw problems if we call EndDialog first */\r
-      EndDialog(hDlg, FALSE);\r
-\r
-      /* copy modified settings back to the fonts array */\r
-      for (i=0; i < NUM_FONTS; i++)\r
-       CopyFont(font[boardSize][i], &workFont[i]);\r
-\r
-      /* a sad necessity due to the original design of having a separate\r
-       * console font, tags font, and comment font for each board size.  IMHO\r
-       * these fonts should not be dependent on the current board size.  I'm\r
-       * running out of time, so I am doing this hack rather than redesign the\r
-       * data structure. Besides, I think if I redesigned the data structure, I\r
-       * might break backwards compatibility with old winboard.ini files.\r
-       * --msw\r
-       */\r
-      for (i=0; i < NUM_SIZES; i++) {\r
-       CopyFont(font[i][EDITTAGS_FONT], &workFont[EDITTAGS_FONT]);\r
-       CopyFont(font[i][CONSOLE_FONT],  &workFont[CONSOLE_FONT]);\r
-       CopyFont(font[i][COMMENT_FONT],  &workFont[COMMENT_FONT]);\r
-       CopyFont(font[i][MOVEHISTORY_FONT],  &workFont[MOVEHISTORY_FONT]);\r
-      }\r
-      /* end sad necessity */\r
-\r
-      InitDrawingSizes(boardSize, 0);\r
-      InvalidateRect(hwndMain, NULL, TRUE);\r
-\r
-      if (commentDialog) {\r
-       SendDlgItemMessage(commentDialog, OPT_CommentText,\r
-         WM_SETFONT, (WPARAM)font[boardSize][COMMENT_FONT]->hf, \r
-         MAKELPARAM(TRUE, 0));\r
-       GetClientRect(GetDlgItem(commentDialog, OPT_CommentText), &rect);\r
-       InvalidateRect(commentDialog, &rect, TRUE);\r
-      }\r
-\r
-      if (editTagsDialog) {\r
-       SendDlgItemMessage(editTagsDialog, OPT_TagsText,\r
-         WM_SETFONT, (WPARAM)font[boardSize][EDITTAGS_FONT]->hf, \r
-         MAKELPARAM(TRUE, 0));\r
-       GetClientRect(GetDlgItem(editTagsDialog, OPT_TagsText), &rect);\r
-       InvalidateRect(editTagsDialog, &rect, TRUE);\r
-      }\r
-\r
-      if( moveHistoryDialog != NULL ) {\r
-       SendDlgItemMessage(moveHistoryDialog, IDC_MoveHistory,\r
-         WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, \r
-         MAKELPARAM(TRUE, 0));\r
-       InvalidateRect(editTagsDialog, NULL, TRUE);\r
-      }\r
-\r
-      if (hwndConsole) {\r
-       ChangedConsoleFont();\r
-      }\r
-\r
-      for (i=0; i<NUM_FONTS; i++)\r
-       DeleteObject(&workFont[i].hf);\r
-\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      for (i=0; i<NUM_FONTS; i++)\r
-       DeleteObject(&workFont[i].hf);\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    case OPT_ChooseClockFont:\r
-      MyCreateFont(hDlg, &workFont[CLOCK_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);\r
-      break;\r
-\r
-    case OPT_ChooseMessageFont:\r
-      MyCreateFont(hDlg, &workFont[MESSAGE_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);\r
-      break;\r
-\r
-    case OPT_ChooseCoordFont:\r
-      MyCreateFont(hDlg, &workFont[COORD_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);\r
-      break;\r
-\r
-    case OPT_ChooseTagFont:\r
-      MyCreateFont(hDlg, &workFont[EDITTAGS_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);\r
-      break;\r
-\r
-    case OPT_ChooseCommentsFont:\r
-      MyCreateFont(hDlg, &workFont[COMMENT_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);\r
-      break;\r
-\r
-    case OPT_ChooseConsoleFont:\r
-      MyCreateFont(hDlg, &workFont[CONSOLE_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);\r
-      break;\r
-\r
-    case OPT_ChooseMoveHistoryFont:\r
-      MyCreateFont(hDlg, &workFont[MOVEHISTORY_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);\r
-      break;\r
-\r
-    case OPT_DefaultFonts:\r
-      for (i=0; i<NUM_FONTS; i++) {\r
-       DeleteObject(&workFont[i].hf);\r
-       ParseFontName(font[boardSize][i]->def, &workFont[i].mfp);\r
-       CreateFontInMF(&workFont[i]);\r
-      }\r
-      SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);\r
-      SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);\r
-      break;\r
-    }\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID\r
-FontsOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc = MakeProcInstance((FARPROC)FontOptionsDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_Fonts), hwnd,\r
-         (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Sounds Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-\r
-SoundComboData soundComboData[] = {\r
-  {"Move", NULL},\r
-  {"Bell", NULL},\r
-  {"ICS Alarm", NULL},\r
-  {"ICS Win", NULL},\r
-  {"ICS Loss", NULL},\r
-  {"ICS Draw", NULL},\r
-  {"ICS Unfinished", NULL},\r
-  {"Shout", NULL},\r
-  {"SShout/CShout", NULL},\r
-  {"Channel 1", NULL},\r
-  {"Channel", NULL},\r
-  {"Kibitz", NULL},\r
-  {"Tell", NULL},\r
-  {"Challenge", NULL},\r
-  {"Request", NULL},\r
-  {"Seek", NULL},\r
-  {NULL, NULL},\r
-};\r
-\r
-\r
-void\r
-InitSoundComboData(SoundComboData *scd)\r
-{\r
-  SoundClass sc;\r
-  ColorClass cc;\r
-  int index;\r
-\r
-  /* copy current sound settings to combo array */\r
-\r
-  for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
-    scd[sc].name = strdup(sounds[sc].name);\r
-  }\r
-  for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {\r
-    index = (int)cc + (int)NSoundClasses;\r
-    scd[index].name = strdup(textAttribs[cc].sound.name);\r
-  }\r
-}\r
-\r
-\r
-void\r
-ResetSoundComboData(SoundComboData *scd)\r
-{\r
-  while (scd->label) {\r
-    if (scd->name != NULL) {\r
-      free (scd->name);\r
-      scd->name = NULL;\r
-    }\r
-    scd++;\r
-  }\r
-}\r
-\r
-void\r
-InitSoundCombo(HWND hwndCombo, SoundComboData *scd)\r
-{\r
-  char buf[255];\r
-  DWORD err;\r
-  DWORD cnt = 0;\r
-  SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
-\r
-  /* send the labels to the combo box */\r
-  while (scd->label) {\r
-    err = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) scd->label);\r
-    if (err != cnt++) {\r
-      sprintf(buf, "InitSoundCombo(): err '%d', cnt '%d'\n",\r
-         err, cnt);\r
-      MessageBox(NULL, buf, NULL, MB_OK);\r
-    }\r
-    scd++;\r
-  }\r
-  SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
-}\r
-\r
-int\r
-SoundDialogWhichRadio(HWND hDlg)\r
-{\r
-  if (IsDlgButtonChecked(hDlg, OPT_NoSound)) return OPT_NoSound;\r
-  if (IsDlgButtonChecked(hDlg, OPT_DefaultBeep)) return OPT_DefaultBeep;\r
-  if (IsDlgButtonChecked(hDlg, OPT_BuiltInSound)) return OPT_BuiltInSound;\r
-  if (IsDlgButtonChecked(hDlg, OPT_WavFile)) return OPT_WavFile;\r
-  return -1;\r
-}\r
-\r
-VOID\r
-SoundDialogSetEnables(HWND hDlg, int radio)\r
-{\r
-  EnableWindow(GetDlgItem(hDlg, OPT_BuiltInSoundName),\r
-              radio == OPT_BuiltInSound);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_WavFileName), radio == OPT_WavFile);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_BrowseSound), radio == OPT_WavFile);\r
-}\r
-\r
-char *\r
-SoundDialogGetName(HWND hDlg, int radio)\r
-{\r
-  static char buf[MSG_SIZ], buf2[MSG_SIZ], buf3[MSG_SIZ];\r
-  char *dummy, *ret;\r
-  switch (radio) {\r
-  case OPT_NoSound:\r
-  default:\r
-    return "";\r
-  case OPT_DefaultBeep:\r
-    return "$";\r
-  case OPT_BuiltInSound:\r
-    buf[0] = '!';\r
-    GetDlgItemText(hDlg, OPT_BuiltInSoundName, buf + 1, sizeof(buf) - 1);\r
-    return buf;\r
-  case OPT_WavFile:\r
-    GetDlgItemText(hDlg, OPT_WavFileName, buf, sizeof(buf));\r
-    GetCurrentDirectory(MSG_SIZ, buf3);\r
-    SetCurrentDirectory(installDir);\r
-    if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) {\r
-      ret = buf2;\r
-    } else {\r
-      ret = buf;\r
-    }\r
-    SetCurrentDirectory(buf3);\r
-    return ret;\r
-  }\r
-}\r
-\r
-void\r
-DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name)\r
-{\r
-  int radio;\r
-  /* \r
-   * I think it's best to clear the combo and edit boxes. It looks stupid\r
-   * to have a value from another sound event sitting there grayed out.\r
-   */\r
-  SetDlgItemText(hDlg, OPT_WavFileName, "");\r
-  SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
-\r
-  if (appData.debugMode)\r
-      fprintf(debugFP, "DisplaySelectedSound(,,'%s'):\n", name);\r
-  switch (name[0]) {\r
-  case NULLCHAR:\r
-    radio = OPT_NoSound;\r
-    break;\r
-  case '$':\r
-    if (name[1] == NULLCHAR) {\r
-      radio = OPT_DefaultBeep;\r
-    } else {\r
-      radio = OPT_WavFile;\r
-      SetDlgItemText(hDlg, OPT_WavFileName, name);\r
-    }\r
-    break;\r
-  case '!':\r
-    if (name[1] == NULLCHAR) {\r
-      radio = OPT_NoSound;\r
-    } else {\r
-      radio = OPT_BuiltInSound;\r
-      if (SendMessage(hCombo, CB_SELECTSTRING, (WPARAM) -1, \r
-                     (LPARAM) (name + 1)) == CB_ERR) {\r
-       SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
-       SendMessage(hCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) (name + 1));\r
-      }\r
-    }\r
-    break;\r
-  default:\r
-    radio = OPT_WavFile;\r
-    SetDlgItemText(hDlg, OPT_WavFileName, name);\r
-    break;\r
-  }\r
-  SoundDialogSetEnables(hDlg, radio);\r
-  CheckRadioButton(hDlg, OPT_NoSound, OPT_WavFile, radio);\r
-}\r
-    \r
-\r
-char *builtInSoundNames[] = BUILT_IN_SOUND_NAMES;\r
-\r
-LRESULT CALLBACK\r
-SoundOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  static HWND hSoundCombo;\r
-  static DWORD index;\r
-  static HWND hBISN;\r
-  int radio;\r
-  MySound tmp;\r
-  FILE *f;\r
-  char buf[MSG_SIZ];\r
-  char *newName;\r
-  SoundClass sc;\r
-  ColorClass cc;\r
-  SoundComboData *scd;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG:\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-\r
-    /* Initialize the built-in sounds combo */\r
-    hBISN = GetDlgItem(hDlg, OPT_BuiltInSoundName);\r
-     InitComboStrings(hBISN, builtInSoundNames);\r
-\r
-    /* Initialize the  sound events combo */\r
-    index = 0;\r
-    InitSoundComboData(soundComboData);\r
-    hSoundCombo = GetDlgItem(hDlg, CBO_Sounds);\r
-    InitSoundCombo(hSoundCombo, soundComboData);\r
-\r
-    /* update the dialog */\r
-    DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-\r
-    if (((HWND)lParam == hSoundCombo) && \r
-       (HIWORD(wParam) == CBN_SELCHANGE)) {\r
-      /* \r
-       * the user has selected a new sound event. We must store the name for\r
-       * the previously selected event, then retrieve the name for the\r
-       * newly selected event and update the dialog. \r
-       */\r
-      radio = SoundDialogWhichRadio(hDlg);\r
-      newName = strdup(SoundDialogGetName(hDlg, radio));\r
-      \r
-      if (strcmp(newName, soundComboData[index].name) != 0) {\r
-       free(soundComboData[index].name);\r
-       soundComboData[index].name = newName;\r
-      } else {\r
-       free(newName);\r
-       newName = NULL;\r
-      }\r
-      /* now get the settings for the newly selected event */\r
-      index = SendMessage(hSoundCombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);\r
-      DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);\r
-      \r
-      return TRUE;\r
-    }\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* \r
-       * save the name for the currently selected sound event \r
-       */\r
-      radio = SoundDialogWhichRadio(hDlg);\r
-      newName = strdup(SoundDialogGetName(hDlg, radio));\r
-\r
-      if (strcmp(soundComboData[index].name, newName) != 0) {\r
-       free(soundComboData[index].name);\r
-       soundComboData[index].name = newName;\r
-      } else {\r
-       free(newName);\r
-       newName = NULL;\r
-      }\r
-\r
-      /* save all the sound names that changed and load the sounds */\r
-\r
-      for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
-       if (strcmp(soundComboData[sc].name, sounds[sc].name) != 0) {\r
-         free(sounds[sc].name);\r
-         sounds[sc].name = strdup(soundComboData[sc].name);\r
-         MyLoadSound(&sounds[sc]);\r
-       }\r
-      }\r
-      for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {\r
-       index = (int)cc + (int)NSoundClasses;\r
-       if (strcmp(soundComboData[index].name, \r
-                  textAttribs[cc].sound.name) != 0) {\r
-         free(textAttribs[cc].sound.name);\r
-         textAttribs[cc].sound.name = strdup(soundComboData[index].name);\r
-         MyLoadSound(&textAttribs[cc].sound);\r
-       }\r
-      }\r
-\r
-      ResetSoundComboData(soundComboData);\r
-      EndDialog(hDlg, TRUE);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      ResetSoundComboData(soundComboData);\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    case OPT_DefaultSounds:\r
-      /* can't use SetDefaultSounds() because we need to be able to "undo" if\r
-       * user selects "Cancel" later on. So we do it the hard way here.\r
-       */\r
-      scd = &soundComboData[0];\r
-      while (scd->label != NULL) {\r
-       if (scd->name != NULL) free(scd->name);\r
-       scd->name = strdup("");\r
-       scd++;\r
-      }\r
-      free(soundComboData[(int)SoundBell].name);\r
-      soundComboData[(int)SoundBell].name = strdup(SOUND_BELL);\r
-      DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);\r
-      break;\r
-\r
-    case OPT_PlaySound:\r
-      radio = SoundDialogWhichRadio(hDlg);\r
-      tmp.name = strdup(SoundDialogGetName(hDlg, radio));\r
-      tmp.data = NULL;\r
-      MyLoadSound(&tmp);\r
-      MyPlaySound(&tmp);\r
-      if (tmp.data  != NULL) free(tmp.data);\r
-      if (tmp.name != NULL) free(tmp.name);\r
-      return TRUE;\r
-\r
-    case OPT_BrowseSound:\r
-      f = OpenFileDialog(hDlg, "rb", NULL, "wav", SOUND_FILT,\r
-       "Browse for Sound File", NULL, NULL, buf);\r
-      if (f != NULL) {\r
-       fclose(f);\r
-       SetDlgItemText(hDlg, OPT_WavFileName, buf);\r
-      }\r
-      return TRUE;\r
-\r
-    default:\r
-      radio = SoundDialogWhichRadio(hDlg);\r
-      SoundDialogSetEnables(hDlg, radio);\r
-      break;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-\r
-VOID SoundOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc;\r
-\r
-  lpProc = MakeProcInstance((FARPROC)SoundOptionsDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_Sound), hwnd, (DLGPROC)lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Comm Port dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-\r
-#define FLOW_NONE   0\r
-#define FLOW_XOFF   1\r
-#define FLOW_CTS    2\r
-#define FLOW_DSR    3\r
-\r
-#define PORT_NONE\r
-\r
-ComboData cdPort[]     = { {"None", PORT_NONE}, {"COM1", 1}, {"COM2", 2},\r
-                          {"COM3", 3}, {"COM4", 4}, {NULL, 0} };\r
-ComboData cdDataRate[] = { {"110", 110}, {"300", 300}, {"600", 600}, {"1200", 1200},\r
-                          {"2400", 2400}, {"4800", 4800}, {"9600", 9600}, {"19200", 19200},\r
-                          {"38400", 38400}, {NULL, 0} };\r
-ComboData cdDataBits[] = { {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8}, {NULL, 0} };\r
-ComboData cdParity[]   = { {"None", NOPARITY}, {"Odd", ODDPARITY}, {"Even", EVENPARITY},\r
-                          {"Mark", MARKPARITY}, {"Space", SPACEPARITY}, {NULL, 0} };\r
-ComboData cdStopBits[] = { {"1", ONESTOPBIT}, {"1.5", ONE5STOPBITS},\r
-                          {"2", TWOSTOPBITS}, {NULL, 0} };\r
-ComboData cdFlow[]     = { {"None", FLOW_NONE}, {"Xoff/Xon", FLOW_XOFF}, {"CTS", FLOW_CTS},\r
-                          {"DSR", FLOW_DSR}, {NULL, 0} };\r
-\r
-\r
-VOID\r
-ParseCommSettings(char *arg, DCB *dcb)\r
-{\r
-  int dataRate, count;\r
-  char bits[MSG_SIZ], parity[MSG_SIZ], stopBits[MSG_SIZ], flow[MSG_SIZ];\r
-  ComboData *cd;\r
-  count = sscanf(arg, "%d%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]",\r
-    &dataRate, bits, parity, stopBits, flow);\r
-  if (count != 5) goto cant_parse;\r
-  dcb->BaudRate = dataRate;\r
-  cd = cdDataBits;\r
-  while (cd->label != NULL) {\r
-    if (StrCaseCmp(cd->label, bits) == 0) {\r
-      dcb->ByteSize = cd->value;\r
-      break;\r
-    }\r
-    cd++;\r
-  }\r
-  if (cd->label == NULL) goto cant_parse;\r
-  cd = cdParity;\r
-  while (cd->label != NULL) {\r
-    if (StrCaseCmp(cd->label, parity) == 0) {\r
-      dcb->Parity = cd->value;\r
-      break;\r
-    }\r
-    cd++;\r
-  }\r
-  if (cd->label == NULL) goto cant_parse;\r
-  cd = cdStopBits;\r
-  while (cd->label != NULL) {\r
-    if (StrCaseCmp(cd->label, stopBits) == 0) {\r
-      dcb->StopBits = cd->value;\r
-      break;\r
-    }\r
-    cd++;\r
-  }\r
-  cd = cdFlow;\r
-  if (cd->label == NULL) goto cant_parse;\r
-  while (cd->label != NULL) {\r
-    if (StrCaseCmp(cd->label, flow) == 0) {\r
-      switch (cd->value) {\r
-      case FLOW_NONE:\r
-       dcb->fOutX = FALSE;\r
-       dcb->fOutxCtsFlow = FALSE;\r
-       dcb->fOutxDsrFlow = FALSE;\r
-       break;\r
-      case FLOW_CTS:\r
-       dcb->fOutX = FALSE;\r
-       dcb->fOutxCtsFlow = TRUE;\r
-       dcb->fOutxDsrFlow = FALSE;\r
-       break;\r
-      case FLOW_DSR:\r
-       dcb->fOutX = FALSE;\r
-       dcb->fOutxCtsFlow = FALSE;\r
-       dcb->fOutxDsrFlow = TRUE;\r
-       break;\r
-      case FLOW_XOFF:\r
-       dcb->fOutX = TRUE;\r
-       dcb->fOutxCtsFlow = FALSE;\r
-       dcb->fOutxDsrFlow = FALSE;\r
-       break;\r
-      }\r
-      break;\r
-    }\r
-    cd++;\r
-  }\r
-  if (cd->label == NULL) goto cant_parse;\r
-  return;\r
-cant_parse:\r
-    ExitArgError("Can't parse com port settings", arg);\r
-}\r
-\r
-\r
-VOID PrintCommSettings(FILE *f, char *name, DCB *dcb)\r
-{\r
-  char *flow = "??", *parity = "??", *stopBits = "??";\r
-  ComboData *cd;\r
-  \r
-  cd = cdParity;\r
-  while (cd->label != NULL) {\r
-    if (dcb->Parity == cd->value) {\r
-      parity = cd->label;\r
-      break;\r
-    }\r
-    cd++;\r
-  }\r
-  cd = cdStopBits;\r
-  while (cd->label != NULL) {\r
-    if (dcb->StopBits == cd->value) {\r
-      stopBits = cd->label;\r
-      break;\r
-    }\r
-    cd++;\r
-  }\r
-  if (dcb->fOutX) {\r
-    flow = cdFlow[FLOW_XOFF].label;\r
-  } else if (dcb->fOutxCtsFlow) {\r
-    flow = cdFlow[FLOW_CTS].label;\r
-  } else if (dcb->fOutxDsrFlow) {\r
-    flow = cdFlow[FLOW_DSR].label;\r
-  } else {\r
-    flow = cdFlow[FLOW_NONE].label;\r
-  }\r
-  fprintf(f, "/%s=%d,%d,%s,%s,%s\n", name,\r
-    dcb->BaudRate, dcb->ByteSize, parity, stopBits, flow);\r
-}\r
-\r
-\r
-void\r
-InitCombo(HANDLE hwndCombo, ComboData *cd)\r
-{\r
-  SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
-\r
-  while (cd->label != NULL) {\r
-    SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) cd->label);\r
-    cd++;\r
-  }\r
-}\r
-\r
-void\r
-SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value)\r
-{\r
-  int i;\r
-\r
-  i = 0;\r
-  while (cd->label != NULL) {\r
-    if (cd->value == value) {\r
-      SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) i, (LPARAM) 0);\r
-      return;\r
-    }\r
-    cd++;\r
-    i++;\r
-  }\r
-}\r
-\r
-LRESULT CALLBACK\r
-CommPortOptionsDialog(HWND hDlg, UINT message, WPARAM wParam,  LPARAM lParam)\r
-{\r
-  char buf[MSG_SIZ];\r
-  HANDLE hwndCombo;\r
-  char *p;\r
-  LRESULT index;\r
-  unsigned value;\r
-  int err;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow(hDlg, GW_OWNER));\r
-    /* Initialize the dialog items */\r
-    /* !! There should probably be some synchronization\r
-       in accessing hCommPort and dcb.  Or does modal nature\r
-       of this dialog box do it for us?\r
-       */\r
-    hwndCombo = GetDlgItem(hDlg, OPT_Port);\r
-    InitCombo(hwndCombo, cdPort);\r
-    p = strrchr(appData.icsCommPort, '\\');\r
-    if (p++ == NULL) p = appData.icsCommPort;\r
-    if ((*p == '\0') ||\r
-       (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) p) == CB_ERR)) {\r
-      SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) "None");\r
-    }\r
-    EnableWindow(hwndCombo, hCommPort == NULL); /*!! don't allow change for now*/\r
-\r
-    hwndCombo = GetDlgItem(hDlg, OPT_DataRate);\r
-    InitCombo(hwndCombo, cdDataRate);\r
-    sprintf(buf, "%u", dcb.BaudRate);\r
-    if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) {\r
-      SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);\r
-      SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf);\r
-    }\r
-\r
-    hwndCombo = GetDlgItem(hDlg, OPT_Bits);\r
-    InitCombo(hwndCombo, cdDataBits);\r
-    SelectComboValue(hwndCombo, cdDataBits, dcb.ByteSize);\r
-\r
-    hwndCombo = GetDlgItem(hDlg, OPT_Parity);\r
-    InitCombo(hwndCombo, cdParity);\r
-    SelectComboValue(hwndCombo, cdParity, dcb.Parity);\r
-\r
-    hwndCombo = GetDlgItem(hDlg, OPT_StopBits);\r
-    InitCombo(hwndCombo, cdStopBits);\r
-    SelectComboValue(hwndCombo, cdStopBits, dcb.StopBits);\r
-\r
-    hwndCombo = GetDlgItem(hDlg, OPT_Flow);\r
-    InitCombo(hwndCombo, cdFlow);\r
-    if (dcb.fOutX) {\r
-      SelectComboValue(hwndCombo, cdFlow, FLOW_XOFF);\r
-    } else if (dcb.fOutxCtsFlow) {\r
-      SelectComboValue(hwndCombo, cdFlow, FLOW_CTS);\r
-    } else if (dcb.fOutxDsrFlow) {\r
-      SelectComboValue(hwndCombo, cdFlow, FLOW_DSR);\r
-    } else {\r
-      SelectComboValue(hwndCombo, cdFlow, FLOW_NONE);\r
-    }\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* Read changed options from the dialog box */\r
-#ifdef NOTDEF\r
-      /* !! Currently we can't change comm ports in midstream */\r
-      hwndCombo = GetDlgItem(hDlg, OPT_Port);\r
-      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
-      if (index == PORT_NONE) {\r
-       appData.icsCommPort = "";\r
-       if (hCommPort != NULL) {\r
-         CloseHandle(hCommPort);\r
-         hCommPort = NULL;\r
-       }\r
-       EndDialog(hDlg, TRUE);\r
-       return TRUE;\r
-      }\r
-      SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);\r
-      appData.icsCommPort = strdup(buf);\r
-      if (hCommPort != NULL) {\r
-       CloseHandle(hCommPort);\r
-       hCommPort = NULL;\r
-      }\r
-      /* now what?? can't really do this; have to fix up the ChildProc\r
-        and InputSource records for the comm port that we gave to the\r
-        back end. */\r
-#endif /*NOTDEF*/\r
-\r
-      hwndCombo = GetDlgItem(hDlg, OPT_DataRate);\r
-      SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);\r
-      if (sscanf(buf, "%u", &value) != 1) {\r
-       MessageBox(hDlg, "Invalid data rate",\r
-                  "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
-       return TRUE;\r
-      }\r
-      dcb.BaudRate = value;\r
-\r
-      hwndCombo = GetDlgItem(hDlg, OPT_Bits);\r
-      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
-      dcb.ByteSize = cdDataBits[index].value;\r
-\r
-      hwndCombo = GetDlgItem(hDlg, OPT_Parity);\r
-      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
-      dcb.Parity = cdParity[index].value;\r
-\r
-      hwndCombo = GetDlgItem(hDlg, OPT_StopBits);\r
-      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
-      dcb.StopBits = cdStopBits[index].value;\r
-\r
-      hwndCombo = GetDlgItem(hDlg, OPT_Flow);\r
-      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
-      switch (cdFlow[index].value) {\r
-      case FLOW_NONE:\r
-       dcb.fOutX = FALSE;\r
-       dcb.fOutxCtsFlow = FALSE;\r
-       dcb.fOutxDsrFlow = FALSE;\r
-       break;\r
-      case FLOW_CTS:\r
-       dcb.fOutX = FALSE;\r
-       dcb.fOutxCtsFlow = TRUE;\r
-       dcb.fOutxDsrFlow = FALSE;\r
-       break;\r
-      case FLOW_DSR:\r
-       dcb.fOutX = FALSE;\r
-       dcb.fOutxCtsFlow = FALSE;\r
-       dcb.fOutxDsrFlow = TRUE;\r
-       break;\r
-      case FLOW_XOFF:\r
-       dcb.fOutX = TRUE;\r
-       dcb.fOutxCtsFlow = FALSE;\r
-       dcb.fOutxDsrFlow = FALSE;\r
-       break;\r
-      }\r
-      if (!SetCommState(hCommPort, (LPDCB) &dcb)) {\r
-       err = GetLastError();\r
-       switch(MessageBox(hDlg, \r
-                        "Failed to set comm port state;\r\ninvalid options?",\r
-                        "Option Error", MB_ABORTRETRYIGNORE|MB_ICONQUESTION)) {\r
-       case IDABORT:\r
-         DisplayFatalError("Failed to set comm port state", err, 1);\r
-         exit(1);  /*is it ok to do this from here?*/\r
-\r
-       case IDRETRY:\r
-         return TRUE;\r
-\r
-       case IDIGNORE:\r
-         EndDialog(hDlg, TRUE);\r
-         return TRUE;\r
-       }\r
-      }\r
-\r
-      EndDialog(hDlg, TRUE);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    default:\r
-      break;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID\r
-CommPortOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc = MakeProcInstance((FARPROC)CommPortOptionsDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_CommPort), hwnd, (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Load Options dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-VOID\r
-SetLoadOptionEnables(HWND hDlg)\r
-{\r
-  UINT state;\r
-\r
-  state = IsDlgButtonChecked(hDlg, OPT_Autostep);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_ASTimeDelay), state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_AStext1), state);\r
-}\r
-\r
-LRESULT CALLBACK\r
-LoadOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  char buf[MSG_SIZ];\r
-  float fnumber;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-    /* Initialize the dialog items */\r
-    if (appData.timeDelay >= 0.0) {\r
-      CheckDlgButton(hDlg, OPT_Autostep, TRUE);\r
-      sprintf(buf, "%.2g", appData.timeDelay);\r
-      SetDlgItemText(hDlg, OPT_ASTimeDelay, buf);\r
-    } else {\r
-      CheckDlgButton(hDlg, OPT_Autostep, FALSE);\r
-    }\r
-    SetLoadOptionEnables(hDlg);\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* Read changed options from the dialog box */\r
-      if (IsDlgButtonChecked(hDlg, OPT_Autostep)) {\r
-       GetDlgItemText(hDlg, OPT_ASTimeDelay, buf, MSG_SIZ);\r
-       if (sscanf(buf, "%f", &fnumber) != 1) {\r
-         MessageBox(hDlg, "Invalid load game step rate",\r
-                    "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
-         return FALSE;\r
-       }\r
-       appData.timeDelay = fnumber;\r
-      } else {\r
-       appData.timeDelay = (float) -1.0;\r
-      }\r
-      EndDialog(hDlg, TRUE);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    default:\r
-      SetLoadOptionEnables(hDlg);\r
-      break;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-\r
-VOID \r
-LoadOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc = MakeProcInstance((FARPROC)LoadOptions, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_LoadOptions), hwnd, (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Save Options dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-VOID\r
-SetSaveOptionEnables(HWND hDlg)\r
-{\r
-  UINT state;\r
-\r
-  state = IsDlgButtonChecked(hDlg, OPT_Autosave);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_AVPrompt), state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_AVToFile), state);\r
-  if (state && !IsDlgButtonChecked(hDlg, OPT_AVPrompt) &&\r
-      !IsDlgButtonChecked(hDlg, OPT_AVToFile)) {\r
-    CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);\r
-  }\r
-\r
-  state = state && IsDlgButtonChecked(hDlg, OPT_AVToFile);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_AVFilename), state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_AVBrowse), state);\r
-}\r
-\r
-LRESULT CALLBACK\r
-SaveOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  char buf[MSG_SIZ];\r
-  FILE *f;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-    /* Initialize the dialog items */\r
-    if (*appData.saveGameFile != NULLCHAR) {\r
-      CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);\r
-      CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVToFile);\r
-      SetDlgItemText(hDlg, OPT_AVFilename, appData.saveGameFile);\r
-    } else if (appData.autoSaveGames) {\r
-      CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);\r
-      CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);\r
-    } else {\r
-      CheckDlgButton(hDlg, OPT_Autosave, (UINT) FALSE);\r
-    }\r
-    if (appData.oldSaveStyle) {\r
-      CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_Old);\r
-    } else {\r
-      CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_PGN);\r
-    }\r
-    CheckDlgButton( hDlg, OPT_OutOfBookInfo, appData.saveOutOfBookInfo );\r
-    SetSaveOptionEnables(hDlg);\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* Read changed options from the dialog box */\r
-      if (IsDlgButtonChecked(hDlg, OPT_Autosave)) {\r
-       appData.autoSaveGames = TRUE;\r
-       if (IsDlgButtonChecked(hDlg, OPT_AVPrompt)) {\r
-         appData.saveGameFile = "";\r
-       } else /*if (IsDlgButtonChecked(hDlg, OPT_AVToFile))*/ {\r
-         GetDlgItemText(hDlg, OPT_AVFilename, buf, MSG_SIZ);\r
-         if (*buf == NULLCHAR) {\r
-           MessageBox(hDlg, "Invalid save game file name",\r
-                      "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
-           return FALSE;\r
-         }\r
-         if ((isalpha(buf[0]) && buf[1] == ':') ||\r
-           (buf[0] == '\\' && buf[1] == '\\')) {\r
-           appData.saveGameFile = strdup(buf);\r
-         } else {\r
-           char buf2[MSG_SIZ], buf3[MSG_SIZ];\r
-           char *dummy;\r
-           GetCurrentDirectory(MSG_SIZ, buf3);\r
-           SetCurrentDirectory(installDir);\r
-           if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) {\r
-             appData.saveGameFile = strdup(buf2);\r
-           } else {\r
-             appData.saveGameFile = strdup(buf);\r
-           }\r
-           SetCurrentDirectory(buf3);\r
-         }\r
-       }\r
-      } else {\r
-       appData.autoSaveGames = FALSE;\r
-       appData.saveGameFile = "";\r
-      }\r
-      appData.oldSaveStyle = IsDlgButtonChecked(hDlg, OPT_Old);\r
-      appData.saveOutOfBookInfo = IsDlgButtonChecked( hDlg, OPT_OutOfBookInfo );\r
-      EndDialog(hDlg, TRUE);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    case OPT_AVBrowse:\r
-      f = OpenFileDialog(hDlg, "a", NULL, \r
-                        appData.oldSaveStyle ? "gam" : "pgn", \r
-                        GAME_FILT, "Browse for Auto Save File", \r
-                        NULL, NULL, buf);\r
-      if (f != NULL) {\r
-       fclose(f);\r
-       SetDlgItemText(hDlg, OPT_AVFilename, buf);\r
-      }\r
-      break;\r
-\r
-    default:\r
-      SetSaveOptionEnables(hDlg);\r
-      break;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID\r
-SaveOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc = MakeProcInstance((FARPROC)SaveOptionsDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_SaveOptions), hwnd, (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Time Control Options dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-VOID\r
-SetTimeControlEnables(HWND hDlg)\r
-{\r
-  UINT state;\r
-\r
-  state = IsDlgButtonChecked(hDlg, OPT_TCUseMoves);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_TCTime), state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_TCMoves), state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_TCtext1), state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_TCtext2), state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_TCTime2), !state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_TCInc), !state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_TCitext1), !state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_TCitext2), !state);\r
-  EnableWindow(GetDlgItem(hDlg, OPT_TCitext3), !state);\r
-}\r
-\r
-\r
-LRESULT CALLBACK\r
-TimeControl(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  char buf[MSG_SIZ];\r
-  int mps, increment, odds1, odds2;\r
-  BOOL ok, ok2;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-    /* Initialize the dialog items */\r
-    if (appData.clockMode && !appData.icsActive) {\r
-      if (appData.timeIncrement == -1) {\r
-       CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseInc,\r
-                        OPT_TCUseMoves);\r
-       SetDlgItemText(hDlg, OPT_TCTime, appData.timeControl);\r
-       SetDlgItemInt(hDlg, OPT_TCMoves, appData.movesPerSession,\r
-                     FALSE);\r
-       SetDlgItemText(hDlg, OPT_TCTime2, "");\r
-       SetDlgItemText(hDlg, OPT_TCInc, "");\r
-      } else {\r
-       CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseInc,\r
-                        OPT_TCUseInc);\r
-       SetDlgItemText(hDlg, OPT_TCTime, "");\r
-       SetDlgItemText(hDlg, OPT_TCMoves, "");\r
-       SetDlgItemText(hDlg, OPT_TCTime2, appData.timeControl);\r
-       SetDlgItemInt(hDlg, OPT_TCInc, appData.timeIncrement, FALSE);\r
-      }\r
-      SetDlgItemInt(hDlg, OPT_TCOdds1, 1, FALSE);\r
-      SetDlgItemInt(hDlg, OPT_TCOdds2, 1, FALSE);\r
-      SetTimeControlEnables(hDlg);\r
-    }\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* Read changed options from the dialog box */\r
-      if (IsDlgButtonChecked(hDlg, OPT_TCUseMoves)) {\r
-       increment = -1;\r
-       mps = GetDlgItemInt(hDlg, OPT_TCMoves, &ok, FALSE);\r
-       if (!ok || mps <= 0) {\r
-         MessageBox(hDlg, "Invalid moves per time control",\r
-                    "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
-         return FALSE;\r
-       }\r
-       GetDlgItemText(hDlg, OPT_TCTime, buf, MSG_SIZ);\r
-       if (!ParseTimeControl(buf, increment, mps)) {\r
-         MessageBox(hDlg, "Invalid minutes per time control",\r
-                    "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
-         return FALSE;\r
-       }\r
-      } else {\r
-       increment = GetDlgItemInt(hDlg, OPT_TCInc, &ok, FALSE);\r
-       mps = appData.movesPerSession;\r
-       if (!ok || increment < 0) {\r
-         MessageBox(hDlg, "Invalid increment",\r
-                    "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
-         return FALSE;\r
-       }\r
-       GetDlgItemText(hDlg, OPT_TCTime2, buf, MSG_SIZ);\r
-       if (!ParseTimeControl(buf, increment, mps)) {\r
-         MessageBox(hDlg, "Invalid initial time",\r
-                    "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
-         return FALSE;\r
-       }\r
-      }\r
-      odds1 = GetDlgItemInt(hDlg, OPT_TCOdds1, &ok, FALSE);\r
-      odds2 = GetDlgItemInt(hDlg, OPT_TCOdds2, &ok2, FALSE);\r
-      if (!ok || !ok2 || odds1 <= 0 || odds2 <= 0) {\r
-         MessageBox(hDlg, "Invalid time-odds factor",\r
-                    "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
-         return FALSE;\r
-      }\r
-      appData.timeControl = strdup(buf);\r
-      appData.movesPerSession = mps;\r
-      appData.timeIncrement = increment;\r
-      appData.firstTimeOdds  = first.timeOdds  = odds1;\r
-      appData.secondTimeOdds = second.timeOdds = odds2;\r
-      Reset(TRUE, TRUE);\r
-      EndDialog(hDlg, TRUE);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    default:\r
-      SetTimeControlEnables(hDlg);\r
-      break;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID\r
-TimeControlOptionsPopup(HWND hwnd)\r
-{\r
-  if (gameMode != BeginningOfGame) {\r
-    DisplayError("Changing time control during a game is not implemented", 0);\r
-  } else {\r
-    FARPROC lpProc = MakeProcInstance((FARPROC)TimeControl, hInst);\r
-    DialogBox(hInst, MAKEINTRESOURCE(DLG_TimeControl), hwnd, (DLGPROC) lpProc);\r
-    FreeProcInstance(lpProc);\r
-  }\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Engine Options Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-#define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))\r
-#define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))\r
-\r
-#define INT_ABS( n )    ((n) >= 0 ? (n) : -(n))\r
-\r
-LRESULT CALLBACK EnginePlayOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-\r
-    /* Initialize the dialog items */\r
-    CHECK_BOX(IDC_EpPeriodicUpdates, appData.periodicUpdates);\r
-    CHECK_BOX(IDC_EpPonder, appData.ponderNextMove);\r
-    CHECK_BOX(IDC_EpShowThinking, appData.showThinking);\r
-    CHECK_BOX(IDC_EpHideThinkingHuman, appData.hideThinkingFromHuman);\r
-\r
-    CHECK_BOX(IDC_TestClaims, appData.testClaims);\r
-    CHECK_BOX(IDC_DetectMates, appData.checkMates);\r
-    CHECK_BOX(IDC_MaterialDraws, appData.materialDraws);\r
-    CHECK_BOX(IDC_TrivialDraws, appData.trivialDraws);\r
-\r
-    CHECK_BOX(IDC_ScoreAbs1, appData.firstScoreIsAbsolute);\r
-    CHECK_BOX(IDC_ScoreAbs2, appData.secondScoreIsAbsolute);\r
-\r
-    SetDlgItemInt( hDlg, IDC_EpDrawMoveCount, appData.adjudicateDrawMoves, TRUE );\r
-    SendDlgItemMessage( hDlg, IDC_EpDrawMoveCount, EM_SETSEL, 0, -1 );\r
-\r
-    SetDlgItemInt( hDlg, IDC_EpAdjudicationThreshold, INT_ABS(appData.adjudicateLossThreshold), TRUE );\r
-    SendDlgItemMessage( hDlg, IDC_EpAdjudicationThreshold, EM_SETSEL, 0, -1 );\r
-\r
-    SetDlgItemInt( hDlg, IDC_RuleMoves, appData.ruleMoves, TRUE );\r
-    SendDlgItemMessage( hDlg, IDC_RuleMoves, EM_SETSEL, 0, -1 );\r
-\r
-    SetDlgItemInt( hDlg, IDC_DrawRepeats, INT_ABS(appData.drawRepeats), TRUE );\r
-    SendDlgItemMessage( hDlg, IDC_DrawRepeats, EM_SETSEL, 0, -1 );\r
-\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      /* Read changed options from the dialog box */\r
-      PeriodicUpdatesEvent(          IS_CHECKED(IDC_EpPeriodicUpdates));\r
-      PonderNextMoveEvent(           IS_CHECKED(IDC_EpPonder));\r
-      appData.hideThinkingFromHuman= IS_CHECKED(IDC_EpHideThinkingHuman); // [HGM] thinking: moved up\r
-#if 0\r
-      ShowThinkingEvent(             IS_CHECKED(IDC_EpShowThinking));\r
-#else\r
-      appData.showThinking   = IS_CHECKED(IDC_EpShowThinking);\r
-      ShowThinkingEvent(); // [HGM] thinking: tests all options that need thinking output\r
-#endif\r
-      appData.testClaims    = IS_CHECKED(IDC_TestClaims);\r
-      appData.checkMates    = IS_CHECKED(IDC_DetectMates);\r
-      appData.materialDraws = IS_CHECKED(IDC_MaterialDraws);\r
-      appData.trivialDraws  = IS_CHECKED(IDC_TrivialDraws);\r
-\r
-      appData.adjudicateDrawMoves = GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, NULL, FALSE );\r
-      appData.adjudicateLossThreshold = - (int) GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, NULL, FALSE );\r
-      appData.ruleMoves = GetDlgItemInt(hDlg, IDC_RuleMoves, NULL, FALSE );\r
-      appData.drawRepeats = (int) GetDlgItemInt(hDlg, IDC_DrawRepeats, NULL, FALSE );\r
-\r
-      appData.firstScoreIsAbsolute  = IS_CHECKED(IDC_ScoreAbs1);\r
-      appData.secondScoreIsAbsolute = IS_CHECKED(IDC_ScoreAbs2);\r
-\r
-      EndDialog(hDlg, TRUE);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    case IDC_EpDrawMoveCount:\r
-    case IDC_EpAdjudicationThreshold:\r
-    case IDC_DrawRepeats:\r
-    case IDC_RuleMoves:\r
-        if( HIWORD(wParam) == EN_CHANGE ) {\r
-            int n1_ok;\r
-            int n2_ok;\r
-            int n3_ok;\r
-            int n4_ok;\r
-\r
-            GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, &n1_ok, FALSE );\r
-            GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, &n2_ok, FALSE );\r
-            GetDlgItemInt(hDlg, IDC_RuleMoves, &n3_ok, FALSE );\r
-            GetDlgItemInt(hDlg, IDC_DrawRepeats, &n4_ok, FALSE );\r
-\r
-            EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok && n4_ok ? TRUE : FALSE );\r
-        }\r
-        return TRUE;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID EnginePlayOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc;\r
-\r
-  lpProc = MakeProcInstance((FARPROC)EnginePlayOptionsDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_EnginePlayOptions), hwnd, (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * UCI Options Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-static BOOL BrowseForFolder( const char * title, char * path )\r
-{\r
-    BOOL result = FALSE;\r
-    BROWSEINFO bi;\r
-    LPITEMIDLIST pidl;\r
-\r
-    ZeroMemory( &bi, sizeof(bi) );\r
-\r
-    bi.lpszTitle = title == 0 ? "Choose Folder" : title;\r
-    bi.ulFlags = BIF_RETURNONLYFSDIRS;\r
-\r
-    pidl = SHBrowseForFolder( &bi );\r
-\r
-    if( pidl != 0 ) {\r
-        IMalloc * imalloc = 0;\r
-\r
-        if( SHGetPathFromIDList( pidl, path ) ) {\r
-            result = TRUE;\r
-        }\r
-\r
-        if( SUCCEEDED( SHGetMalloc ( &imalloc ) ) ) {\r
-            imalloc->lpVtbl->Free(imalloc,pidl);\r
-            imalloc->lpVtbl->Release(imalloc);\r
-        }\r
-    }\r
-\r
-    return result;\r
-}\r
-\r
-LRESULT CALLBACK UciOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
-  char buf[MAX_PATH];\r
-  int oldCores;\r
-\r
-  switch (message) {\r
-  case WM_INITDIALOG: /* message: initialize dialog box */\r
-\r
-    /* Center the dialog over the application window */\r
-    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
-\r
-    /* Initialize the dialog items */\r
-    SetDlgItemText( hDlg, IDC_PolyglotDir, appData.polyglotDir );\r
-    SetDlgItemInt( hDlg, IDC_HashSize, appData.defaultHashSize, TRUE );\r
-    SetDlgItemText( hDlg, IDC_PathToEGTB, appData.defaultPathEGTB );\r
-    SetDlgItemInt( hDlg, IDC_SizeOfEGTB, appData.defaultCacheSizeEGTB, TRUE );\r
-    CheckDlgButton( hDlg, IDC_UseBook, (BOOL) appData.usePolyglotBook );\r
-    SetDlgItemText( hDlg, IDC_BookFile, appData.polyglotBook );\r
-    // [HGM] smp: input field for nr of cores:\r
-    SetDlgItemInt( hDlg, IDC_Cores, appData.smpCores, TRUE );\r
-    // [HGM] book: tick boxes for own book use\r
-    CheckDlgButton( hDlg, IDC_OwnBook1, (BOOL) appData.firstHasOwnBookUCI );\r
-    CheckDlgButton( hDlg, IDC_OwnBook2, (BOOL) appData.secondHasOwnBookUCI );\r
-\r
-    SendDlgItemMessage( hDlg, IDC_PolyglotDir, EM_SETSEL, 0, -1 );\r
-\r
-    return TRUE;\r
-\r
-  case WM_COMMAND: /* message: received a command */\r
-    switch (LOWORD(wParam)) {\r
-    case IDOK:\r
-      GetDlgItemText( hDlg, IDC_PolyglotDir, buf, sizeof(buf) );\r
-      appData.polyglotDir = strdup(buf);\r
-      appData.defaultHashSize = GetDlgItemInt(hDlg, IDC_HashSize, NULL, FALSE );\r
-      appData.defaultCacheSizeEGTB = GetDlgItemInt(hDlg, IDC_SizeOfEGTB, NULL, FALSE );\r
-      GetDlgItemText( hDlg, IDC_PathToEGTB, buf, sizeof(buf) );\r
-      appData.defaultPathEGTB = strdup(buf);\r
-      GetDlgItemText( hDlg, IDC_BookFile, buf, sizeof(buf) );\r
-      appData.polyglotBook = strdup(buf);\r
-      appData.usePolyglotBook = (Boolean) IsDlgButtonChecked( hDlg, IDC_UseBook );\r
-      // [HGM] smp: get nr of cores:\r
-      oldCores = appData.smpCores;\r
-      appData.smpCores = GetDlgItemInt(hDlg, IDC_Cores, NULL, FALSE );\r
-      if(appData.smpCores != oldCores) NewSettingEvent(FALSE, "cores", appData.smpCores);\r
-      // [HGM] book: read tick boxes for own book use\r
-      appData.firstHasOwnBookUCI  = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook1 );\r
-      appData.secondHasOwnBookUCI = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook2 );\r
-\r
-      if(gameMode == BeginningOfGame) Reset(TRUE, TRUE);\r
-      EndDialog(hDlg, TRUE);\r
-      return TRUE;\r
-\r
-    case IDCANCEL:\r
-      EndDialog(hDlg, FALSE);\r
-      return TRUE;\r
-\r
-    case IDC_BrowseForBook:\r
-      {\r
-          char filter[] = { \r
-              'A','l','l',' ','F','i','l','e','s', 0,\r
-              '*','.','*', 0,\r
-              'B','I','N',' ','F','i','l','e','s', 0,\r
-              '*','.','b','i','n', 0,\r
-              0 };\r
-\r
-          OPENFILENAME ofn;\r
-\r
-          strcpy( buf, "" );\r
-\r
-          ZeroMemory( &ofn, sizeof(ofn) );\r
-\r
-          ofn.lStructSize = sizeof(ofn);\r
-          ofn.hwndOwner = hDlg;\r
-          ofn.hInstance = hInst;\r
-          ofn.lpstrFilter = filter;\r
-          ofn.lpstrFile = buf;\r
-          ofn.nMaxFile = sizeof(buf);\r
-          ofn.lpstrTitle = "Choose Book";\r
-          ofn.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_HIDEREADONLY;\r
-\r
-          if( GetOpenFileName( &ofn ) ) {\r
-              SetDlgItemText( hDlg, IDC_BookFile, buf );\r
-          }\r
-      }\r
-      return TRUE;\r
-\r
-    case IDC_BrowseForPolyglotDir:\r
-      if( BrowseForFolder( "Choose Polyglot Directory", buf ) ) {\r
-        SetDlgItemText( hDlg, IDC_PolyglotDir, buf );\r
-\r
-        strcat( buf, "\\polyglot.exe" );\r
-\r
-        if( GetFileAttributes(buf) == 0xFFFFFFFF ) {\r
-            MessageBox( hDlg, "Polyglot was not found in the specified folder!", "Warning", MB_OK | MB_ICONWARNING );\r
-        }\r
-      }\r
-      return TRUE;\r
-\r
-    case IDC_BrowseForEGTB:\r
-      if( BrowseForFolder( "Choose EGTB Directory:", buf ) ) {\r
-        SetDlgItemText( hDlg, IDC_PathToEGTB, buf );\r
-      }\r
-      return TRUE;\r
-\r
-    case IDC_HashSize:\r
-    case IDC_SizeOfEGTB:\r
-        if( HIWORD(wParam) == EN_CHANGE ) {\r
-            int n1_ok;\r
-            int n2_ok;\r
-\r
-            GetDlgItemInt(hDlg, IDC_HashSize, &n1_ok, FALSE );\r
-            GetDlgItemInt(hDlg, IDC_SizeOfEGTB, &n2_ok, FALSE );\r
-\r
-            EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok ? TRUE : FALSE );\r
-        }\r
-        return TRUE;\r
-    }\r
-    break;\r
-  }\r
-  return FALSE;\r
-}\r
-\r
-VOID UciOptionsPopup(HWND hwnd)\r
-{\r
-  FARPROC lpProc;\r
-\r
-  lpProc = MakeProcInstance((FARPROC)UciOptionsDialog, hInst);\r
-  DialogBox(hInst, MAKEINTRESOURCE(DLG_OptionsUCI), hwnd, (DLGPROC) lpProc);\r
-  FreeProcInstance(lpProc);\r
-}\r
+/*
+ * woptions.c -- Options dialog box routines for WinBoard
+ * $Id: woptions.c,v 2.1 2003/10/27 19:21:02 mann Exp $
+ *
+ * Copyright 2000 Free Software Foundation, Inc.
+ *
+ * ------------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ------------------------------------------------------------------------
+ */
+
+#include "config.h"
+
+#include <windows.h>   /* required for all Windows applications */
+#include <stdio.h>
+#include <stdlib.h>
+#include <shlobj.h>    /* [AS] Requires NT 4.0 or Win95 */
+
+#include "common.h"
+#include "winboard.h"
+#include "backend.h"
+#include "woptions.h"
+#include "defaults.h"
+#include "wedittags.h"
+#include <richedit.h>
+
+#if __GNUC__
+#include <errno.h>
+#include <string.h>
+#endif
+
+/* Imports from winboard.c */
+
+extern MyFont *font[NUM_SIZES][NUM_FONTS];
+extern HINSTANCE hInst;          /* current instance */
+extern HWND hwndMain;            /* root window*/
+extern BOOLEAN alwaysOnTop;
+extern RECT boardRect;
+extern COLORREF lightSquareColor, darkSquareColor, whitePieceColor, 
+  blackPieceColor, highlightSquareColor, premoveHighlightColor;
+extern HPALETTE hPal;
+extern BoardSize boardSize;
+extern COLORREF consoleBackgroundColor;
+extern MyColorizeAttribs colorizeAttribs[]; /* do I need the size? */
+extern MyTextAttribs textAttribs[];
+extern MySound sounds[];
+extern ColorClass currentColorClass;
+extern HWND hwndConsole;
+extern char *defaultTextAttribs[];
+extern HWND commentDialog;
+extern HWND moveHistoryDialog;
+extern char installDir[];
+extern HWND hCommPort;    /* currently open comm port */
+extern DCB dcb;
+extern BOOLEAN chessProgram;
+extern startedFromPositionFile; /* [HGM] loadPos */
+
+/* types */
+
+typedef struct {
+  char *label;
+  unsigned value;
+} ComboData;
+
+typedef struct {
+  char *label;
+  char *name;
+} SoundComboData;
+
+/* module prototypes */
+
+LRESULT CALLBACK GeneralOptions(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK BoardOptions(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK NewVariant(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK IcsOptions(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK FontOptions(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK CommPortOptions(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK LoadOptions(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK SaveOptions(HWND, UINT, WPARAM, LPARAM);
+LRESULT CALLBACK TimeControl(HWND, UINT, WPARAM, LPARAM);
+VOID ChangeBoardSize(BoardSize newSize);
+VOID PaintSampleSquare(
+    HWND     hwnd, 
+    int      ctrlid, 
+    COLORREF squareColor, 
+    COLORREF pieceColor,
+    COLORREF squareOutlineColor,
+    COLORREF pieceDetailColor,
+    BOOL     isWhitePiece,
+    BOOL     isMono,
+    HBITMAP  pieces[3] 
+    );
+VOID PaintColorBlock(HWND hwnd, int ctrlid, COLORREF color);
+VOID SetBoardOptionEnables(HWND hDlg);
+BoardSize BoardOptionsWhichRadio(HWND hDlg);
+BOOL APIENTRY MyCreateFont(HWND hwnd, MyFont *font);
+VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
+LRESULT CALLBACK ColorizeTextDialog(HWND , UINT, WPARAM, LPARAM);
+VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
+VOID SetIcsOptionEnables(HWND hDlg);
+VOID SetSampleFontText(HWND hwnd, int id, const MyFont *mf);
+VOID CopyFont(MyFont *dest, const MyFont *src);
+void InitSoundComboData(SoundComboData *scd);
+void ResetSoundComboData(SoundComboData *scd);
+void InitSoundCombo(HWND hwndCombo, SoundComboData *scd);
+int SoundDialogWhichRadio(HWND hDlg);
+VOID SoundDialogSetEnables(HWND hDlg, int radio);
+char * SoundDialogGetName(HWND hDlg, int radio);
+void DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name);
+VOID ParseCommSettings(char *arg, DCB *dcb);
+VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
+void InitCombo(HANDLE hwndCombo, ComboData *cd);
+void SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value);
+VOID SetLoadOptionEnables(HWND hDlg);
+VOID SetSaveOptionEnables(HWND hDlg);
+VOID SetTimeControlEnables(HWND hDlg);
+
+/*---------------------------------------------------------------------------*\
+ *
+ * General Options Dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+
+
+LRESULT CALLBACK
+GeneralOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  static Boolean oldShowCoords;
+  static Boolean oldBlindfold;
+  static Boolean oldShowButtonBar;
+
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+    oldShowCoords = appData.showCoords;
+    oldBlindfold  = appData.blindfold;
+    oldShowButtonBar = appData.showButtonBar;
+
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+    /* Initialize the dialog items */
+#define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))
+
+    CHECK_BOX(OPT_AlwaysOnTop, alwaysOnTop);
+    CHECK_BOX(OPT_AlwaysQueen, appData.alwaysPromoteToQueen);
+    CHECK_BOX(OPT_AnimateDragging, appData.animateDragging);
+    CHECK_BOX(OPT_AnimateMoving, appData.animate);
+    CHECK_BOX(OPT_AutoFlag, appData.autoCallFlag);
+    CHECK_BOX(OPT_AutoFlipView, appData.autoFlipView);
+    CHECK_BOX(OPT_AutoRaiseBoard, appData.autoRaiseBoard);
+    CHECK_BOX(OPT_Blindfold, appData.blindfold);
+    CHECK_BOX(OPT_HighlightDragging, appData.highlightDragging);
+    CHECK_BOX(OPT_HighlightLastMove, appData.highlightLastMove);
+    CHECK_BOX(OPT_PeriodicUpdates, appData.periodicUpdates);
+    CHECK_BOX(OPT_PonderNextMove, appData.ponderNextMove);
+    CHECK_BOX(OPT_PopupExitMessage, appData.popupExitMessage);
+    CHECK_BOX(OPT_PopupMoveErrors, appData.popupMoveErrors);
+    CHECK_BOX(OPT_ShowButtonBar, appData.showButtonBar);
+    CHECK_BOX(OPT_ShowCoordinates, appData.showCoords);
+    CHECK_BOX(OPT_ShowThinking, appData.showThinking);
+    CHECK_BOX(OPT_TestLegality, appData.testLegality);
+    CHECK_BOX(OPT_HideThinkFromHuman, appData.hideThinkingFromHuman);
+    CHECK_BOX(OPT_SaveExtPGN, appData.saveExtendedInfoInPGN);
+    CHECK_BOX(OPT_ExtraInfoInMoveHistory, appData.showEvalInMoveHistory);
+    CHECK_BOX(OPT_HighlightMoveArrow, appData.highlightMoveWithArrow);
+
+#undef CHECK_BOX
+
+    EnableWindow(GetDlgItem(hDlg, OPT_AutoFlag),
+                appData.icsActive || !appData.noChessProgram);
+    EnableWindow(GetDlgItem(hDlg, OPT_AutoFlipView),
+                appData.icsActive || !appData.noChessProgram);
+    EnableWindow(GetDlgItem(hDlg, OPT_PonderNextMove),
+                !appData.noChessProgram);
+    EnableWindow(GetDlgItem(hDlg, OPT_PeriodicUpdates), 
+                !appData.noChessProgram && !appData.icsActive);
+    EnableWindow(GetDlgItem(hDlg, OPT_ShowThinking), 
+                !appData.noChessProgram);
+    return TRUE;
+
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* Read changed options from the dialog box */
+      
+#define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))
+
+      alwaysOnTop                  = IS_CHECKED(OPT_AlwaysOnTop);
+      appData.alwaysPromoteToQueen = IS_CHECKED(OPT_AlwaysQueen);
+      appData.animateDragging      = IS_CHECKED(OPT_AnimateDragging);
+      appData.animate              = IS_CHECKED(OPT_AnimateMoving);
+      appData.autoCallFlag         = IS_CHECKED(OPT_AutoFlag);
+      appData.autoFlipView         = IS_CHECKED(OPT_AutoFlipView);
+      appData.autoRaiseBoard       = IS_CHECKED(OPT_AutoRaiseBoard);
+      appData.blindfold            = IS_CHECKED(OPT_Blindfold);
+      appData.highlightDragging    = IS_CHECKED(OPT_HighlightDragging);
+      appData.highlightLastMove    = IS_CHECKED(OPT_HighlightLastMove);
+      PeriodicUpdatesEvent(          IS_CHECKED(OPT_PeriodicUpdates));
+      PonderNextMoveEvent(           IS_CHECKED(OPT_PonderNextMove));
+      appData.popupExitMessage     = IS_CHECKED(OPT_PopupExitMessage);
+      appData.popupMoveErrors      = IS_CHECKED(OPT_PopupMoveErrors);
+      appData.showButtonBar        = IS_CHECKED(OPT_ShowButtonBar);
+      appData.showCoords           = IS_CHECKED(OPT_ShowCoordinates);
+      // [HGM] thinking: next three moved up
+      appData.saveExtendedInfoInPGN= IS_CHECKED(OPT_SaveExtPGN);
+      appData.hideThinkingFromHuman= IS_CHECKED(OPT_HideThinkFromHuman);
+      appData.showEvalInMoveHistory= IS_CHECKED(OPT_ExtraInfoInMoveHistory);
+#if 0
+      ShowThinkingEvent(             IS_CHECKED(OPT_ShowThinking));
+#else
+      appData.showThinking         = IS_CHECKED(OPT_ShowThinking);
+      ShowThinkingEvent(); // [HGM] thinking: tests four options
+#endif
+      appData.testLegality         = IS_CHECKED(OPT_TestLegality);
+      appData.highlightMoveWithArrow=IS_CHECKED(OPT_HighlightMoveArrow);
+
+#undef IS_CHECKED
+
+      SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
+                  0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+#if AOT_CONSOLE
+      if (hwndConsole) {
+       SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
+                    0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+      }
+#endif
+      if (!appData.highlightLastMove) {
+       ClearHighlights();
+       DrawPosition(FALSE, NULL);
+      }
+      /* 
+       * for some reason the redraw seems smoother when we invalidate
+       * the board rect after the call to EndDialog()
+       */
+      EndDialog(hDlg, TRUE);
+
+      if (oldShowButtonBar != appData.showButtonBar) {
+       InitDrawingSizes(boardSize, 0);
+      } else if ((oldShowCoords != appData.showCoords) || 
+                (oldBlindfold != appData.blindfold)) {
+       InvalidateRect(hwndMain, &boardRect, FALSE);
+      }
+
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    }
+    break;
+  }
+  return FALSE;
+}
+
+VOID 
+GeneralOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc;
+
+  lpProc = MakeProcInstance((FARPROC)GeneralOptionsDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_GeneralOptions), hwnd,
+           (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
+/*---------------------------------------------------------------------------*\
+ *
+ * Board Options Dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+
+const int SAMPLE_SQ_SIZE = 54;
+
+VOID
+ChangeBoardSize(BoardSize newSize)
+{
+  if (newSize != boardSize) {
+    boardSize = newSize;
+    InitDrawingSizes(boardSize, 0);
+  }
+}
+
+VOID
+PaintSampleSquare(
+    HWND     hwnd, 
+    int      ctrlid, 
+    COLORREF squareColor, 
+    COLORREF pieceColor,
+    COLORREF squareOutlineColor,
+    COLORREF pieceDetailColor,
+    BOOL     isWhitePiece,
+    BOOL     isMono,
+    HBITMAP  pieces[3] 
+    )
+{
+  HBRUSH  brushSquare;
+  HBRUSH  brushSquareOutline;
+  HBRUSH  brushPiece;
+  HBRUSH  brushPieceDetail;
+  HBRUSH  oldBrushPiece;
+  HBRUSH  oldBrushSquare;
+  HBITMAP oldBitmapMem;
+  HBITMAP oldBitmapTemp;
+  HBITMAP bufferBitmap;
+  RECT    rect;
+  HDC     hdcScreen, hdcMem, hdcTemp;
+  HPEN    pen, oldPen;
+  HWND    hCtrl = GetDlgItem(hwnd, ctrlid);
+  int     x, y;
+
+  const int SOLID   = 0;
+  const int WHITE   = 1;
+  const int OUTLINE = 2;
+  const int BORDER  = 4;
+
+  InvalidateRect(hCtrl, NULL, TRUE);
+  UpdateWindow(hCtrl);
+  GetClientRect(hCtrl, &rect);
+  x = rect.left + (BORDER / 2);
+  y = rect.top  + (BORDER / 2);
+  hdcScreen = GetDC(hCtrl);
+  hdcMem  = CreateCompatibleDC(hdcScreen);
+  hdcTemp = CreateCompatibleDC(hdcScreen);
+
+  bufferBitmap = CreateCompatibleBitmap(hdcScreen, rect.right-rect.left+1,
+                                       rect.bottom-rect.top+1);
+  oldBitmapMem = SelectObject(hdcMem, bufferBitmap);
+  if (!isMono) {
+    SelectPalette(hdcMem, hPal, FALSE);
+  }
+  brushSquare         = CreateSolidBrush(squareColor);
+  brushSquareOutline  = CreateSolidBrush(squareOutlineColor);
+  brushPiece          = CreateSolidBrush(pieceColor);
+  brushPieceDetail    = CreateSolidBrush(pieceDetailColor);
+
+  /* 
+   * first draw the rectangle 
+   */
+  pen      = CreatePen(PS_SOLID, BORDER, squareOutlineColor);
+  oldPen   = (HPEN)  SelectObject(hdcMem, pen);
+  oldBrushSquare = (HBRUSH)SelectObject(hdcMem, brushSquare);
+  Rectangle(hdcMem, rect.left, rect.top, rect.right, rect.bottom);
+
+  /* 
+   * now draw the piece
+   */
+  if (isMono) {
+    oldBitmapTemp = SelectObject(hdcTemp, pieces[OUTLINE]);
+    BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, hdcTemp, 0, 0,
+          isWhitePiece ? SRCCOPY : NOTSRCCOPY);
+    SelectObject(hdcTemp, oldBitmapTemp);
+  } else {
+    if (isWhitePiece) {
+      oldBitmapTemp = SelectObject(hdcTemp, pieces[WHITE]);
+      oldBrushPiece = SelectObject(hdcMem, brushPiece);
+      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, 
+            hdcTemp, 0, 0, 0x00B8074A);
+#if 0
+      /* Use pieceDetailColor for outline of white pieces */
+      SelectObject(hdcTemp, pieces[OUTLINE]);
+      SelectObject(hdcMem, brushPieceDetail);
+      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, 
+            hdcTemp, 0, 0, 0x00B8074A);
+#else
+      /* Use black for outline of white pieces */
+      SelectObject(hdcTemp, pieces[OUTLINE]);
+      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, 
+            hdcTemp, 0, 0, SRCAND);
+#endif
+    } else {
+#if 0
+      /* Use pieceDetailColor for details of black pieces */
+      /* Requires filled-in solid bitmaps (BLACK_PIECE class); the
+        WHITE_PIECE ones aren't always the right shape. */
+      oldBitmapTemp = SelectObject(hdcTemp, pieces[BLACK]);
+      oldBrushPiece = SelectObject(hdcMem, brushPieceDetail);
+      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, 
+            hdcTemp, 0, 0, 0x00B8074A);
+      SelectObject(hdcTemp, pieces[SOLID]);
+      SelectObject(hdcMem, brushPiece);
+      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, 
+            hdcTemp, 0, 0, 0x00B8074A);
+#else
+      /* Use square color for details of black pieces */
+      oldBitmapTemp = SelectObject(hdcTemp, pieces[SOLID]);
+      oldBrushPiece = SelectObject(hdcMem, brushPiece);
+      BitBlt(hdcMem, x, y, SAMPLE_SQ_SIZE, SAMPLE_SQ_SIZE, 
+            hdcTemp, 0, 0, 0x00B8074A);
+#endif
+    }
+    SelectObject(hdcMem, oldBrushPiece);
+    SelectObject(hdcTemp, oldBitmapTemp);
+  }
+  /* 
+   * copy the memory dc to the screen
+   */
+  SelectObject(hdcMem, bufferBitmap);
+  BitBlt(hdcScreen, rect.left, rect.top,
+        rect.right - rect.left,
+        rect.bottom - rect.top,
+        hdcMem, rect.left, rect.top, SRCCOPY);
+  SelectObject(hdcMem, oldBitmapMem);
+  /* 
+   * clean up
+   */
+  SelectObject(hdcMem, oldBrushPiece);
+  SelectObject(hdcMem, oldPen);
+  DeleteObject(brushPiece);
+  DeleteObject(brushPieceDetail);
+  DeleteObject(brushSquare);
+  DeleteObject(brushSquareOutline);
+  DeleteObject(pen);
+  DeleteDC(hdcTemp);
+  DeleteDC(hdcMem);
+  ReleaseDC(hCtrl, hdcScreen);
+}
+
+
+VOID
+PaintColorBlock(HWND hwnd, int ctrlid, COLORREF color)
+{
+  HDC    hdc;
+  HBRUSH brush, oldBrush;
+  RECT   rect;
+  HWND   hCtrl = GetDlgItem(hwnd, ctrlid);
+
+  hdc = GetDC(hCtrl);
+  InvalidateRect(hCtrl, NULL, TRUE);
+  UpdateWindow(hCtrl);
+  GetClientRect(hCtrl, &rect);
+  brush = CreateSolidBrush(color);
+  oldBrush = (HBRUSH)SelectObject(hdc, brush);
+  Rectangle(hdc, rect.left, rect.top, rect.right, rect.bottom);
+  SelectObject(hdc, oldBrush);
+  DeleteObject(brush);
+  ReleaseDC(hCtrl, hdc);
+}
+
+
+VOID
+SetBoardOptionEnables(HWND hDlg)
+{
+  if (IsDlgButtonChecked(hDlg, OPT_Monochrome)) {
+    ShowWindow(GetDlgItem(hDlg, OPT_LightSquareColor), SW_HIDE);
+    ShowWindow(GetDlgItem(hDlg, OPT_DarkSquareColor), SW_HIDE);
+    ShowWindow(GetDlgItem(hDlg, OPT_WhitePieceColor), SW_HIDE);
+    ShowWindow(GetDlgItem(hDlg, OPT_BlackPieceColor), SW_HIDE);
+
+    EnableWindow(GetDlgItem(hDlg, OPT_ChooseLightSquareColor), FALSE);
+    EnableWindow(GetDlgItem(hDlg, OPT_ChooseDarkSquareColor), FALSE);
+    EnableWindow(GetDlgItem(hDlg, OPT_ChooseWhitePieceColor), FALSE);
+    EnableWindow(GetDlgItem(hDlg, OPT_ChooseBlackPieceColor), FALSE);
+  } else {
+    ShowWindow(GetDlgItem(hDlg, OPT_LightSquareColor), SW_SHOW);
+    ShowWindow(GetDlgItem(hDlg, OPT_DarkSquareColor), SW_SHOW);
+    ShowWindow(GetDlgItem(hDlg, OPT_WhitePieceColor), SW_SHOW);
+    ShowWindow(GetDlgItem(hDlg, OPT_BlackPieceColor), SW_SHOW);
+
+    EnableWindow(GetDlgItem(hDlg, OPT_ChooseLightSquareColor), TRUE);
+    EnableWindow(GetDlgItem(hDlg, OPT_ChooseDarkSquareColor), TRUE);
+    EnableWindow(GetDlgItem(hDlg, OPT_ChooseWhitePieceColor), TRUE);
+    EnableWindow(GetDlgItem(hDlg, OPT_ChooseBlackPieceColor), TRUE);
+  }
+}
+
+BoardSize 
+BoardOptionsWhichRadio(HWND hDlg)
+{
+  return (IsDlgButtonChecked(hDlg, OPT_SizeTiny) ? SizeTiny :
+         (IsDlgButtonChecked(hDlg, OPT_SizeTeeny) ? SizeTeeny :
+         (IsDlgButtonChecked(hDlg, OPT_SizeDinky) ? SizeDinky :
+         (IsDlgButtonChecked(hDlg, OPT_SizePetite) ? SizePetite :
+         (IsDlgButtonChecked(hDlg, OPT_SizeSlim) ? SizeSlim :
+         (IsDlgButtonChecked(hDlg, OPT_SizeSmall) ? SizeSmall :
+         (IsDlgButtonChecked(hDlg, OPT_SizeMediocre) ? SizeMediocre :
+         (IsDlgButtonChecked(hDlg, OPT_SizeMiddling) ? SizeMiddling :
+         (IsDlgButtonChecked(hDlg, OPT_SizeAverage) ? SizeAverage :
+         (IsDlgButtonChecked(hDlg, OPT_SizeModerate) ? SizeModerate :
+         (IsDlgButtonChecked(hDlg, OPT_SizeMedium) ? SizeMedium :
+         (IsDlgButtonChecked(hDlg, OPT_SizeBulky) ? SizeBulky :
+         (IsDlgButtonChecked(hDlg, OPT_SizeLarge) ? SizeLarge :
+         (IsDlgButtonChecked(hDlg, OPT_SizeBig) ? SizeBig :
+         (IsDlgButtonChecked(hDlg, OPT_SizeHuge) ? SizeHuge :
+         (IsDlgButtonChecked(hDlg, OPT_SizeGiant) ? SizeGiant :
+         (IsDlgButtonChecked(hDlg, OPT_SizeColossal) ? SizeColossal :
+          SizeTitanic )))))))))))))))));
+}
+
+LRESULT CALLBACK
+BoardOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  static Boolean  mono, white, flip;
+  static BoardSize size;
+  static COLORREF lsc, dsc, wpc, bpc, hsc, phc;
+  static HBITMAP pieces[3];
+
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+    /* Initialize the dialog items */
+    switch (boardSize) {
+    case SizeTiny:
+      CheckDlgButton(hDlg, OPT_SizeTiny, TRUE);
+      break;
+    case SizeTeeny:
+      CheckDlgButton(hDlg, OPT_SizeTeeny, TRUE);
+      break;
+    case SizeDinky:
+      CheckDlgButton(hDlg, OPT_SizeDinky, TRUE);
+      break;
+    case SizePetite:
+      CheckDlgButton(hDlg, OPT_SizePetite, TRUE);
+      break;
+    case SizeSlim:
+      CheckDlgButton(hDlg, OPT_SizeSlim, TRUE);
+      break;
+    case SizeSmall:
+      CheckDlgButton(hDlg, OPT_SizeSmall, TRUE);
+      break;
+    case SizeMediocre:
+      CheckDlgButton(hDlg, OPT_SizeMediocre, TRUE);
+      break;
+    case SizeMiddling:
+      CheckDlgButton(hDlg, OPT_SizeMiddling, TRUE);
+      break;
+    case SizeAverage:
+      CheckDlgButton(hDlg, OPT_SizeAverage, TRUE);
+      break;
+    case SizeModerate:
+      CheckDlgButton(hDlg, OPT_SizeModerate, TRUE);
+      break;
+    case SizeMedium:
+      CheckDlgButton(hDlg, OPT_SizeMedium, TRUE);
+      break;
+    case SizeBulky:
+      CheckDlgButton(hDlg, OPT_SizeBulky, TRUE);
+      break;
+    case SizeLarge:
+      CheckDlgButton(hDlg, OPT_SizeLarge, TRUE);
+      break;
+    case SizeBig:
+      CheckDlgButton(hDlg, OPT_SizeBig, TRUE);
+      break;
+    case SizeHuge:
+      CheckDlgButton(hDlg, OPT_SizeHuge, TRUE);
+      break;
+    case SizeGiant:
+      CheckDlgButton(hDlg, OPT_SizeGiant, TRUE);
+      break;
+    case SizeColossal:
+      CheckDlgButton(hDlg, OPT_SizeColossal, TRUE);
+      break;
+    case SizeTitanic:
+      CheckDlgButton(hDlg, OPT_SizeTitanic, TRUE);
+    }
+
+    if (appData.monoMode)
+      CheckDlgButton(hDlg, OPT_Monochrome, TRUE);
+
+    if (appData.allWhite)
+      CheckDlgButton(hDlg, OPT_AllWhite, TRUE);
+
+    if (appData.upsideDown)
+      CheckDlgButton(hDlg, OPT_UpsideDown, TRUE);
+
+    pieces[0] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "s");
+    pieces[1] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "w");
+    pieces[2] = DoLoadBitmap(hInst, "n", SAMPLE_SQ_SIZE, "o");
+       
+    lsc = lightSquareColor;
+    dsc = darkSquareColor;
+    wpc = whitePieceColor;
+    bpc = blackPieceColor;
+    hsc = highlightSquareColor;
+    phc = premoveHighlightColor;
+    mono = appData.monoMode;
+    white= appData.allWhite;
+    flip = appData.upsideDown;
+    size = boardSize;
+
+    SetBoardOptionEnables(hDlg);
+    return TRUE;
+
+  case WM_PAINT:
+    PaintColorBlock(hDlg, OPT_LightSquareColor, lsc);
+    PaintColorBlock(hDlg, OPT_DarkSquareColor,  dsc);
+    PaintColorBlock(hDlg, OPT_WhitePieceColor,  wpc);
+    PaintColorBlock(hDlg, OPT_BlackPieceColor,  bpc);
+    PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc);
+    PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc);
+    PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,
+       TRUE, mono, pieces);
+    PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,
+       FALSE, mono, pieces);
+
+    return FALSE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* 
+       * if we call EndDialog() after the call to ChangeBoardSize(),
+       * then ChangeBoardSize() does not take effect, although the new
+       * boardSize is saved. Go figure...
+       */
+      EndDialog(hDlg, TRUE);
+
+      size = BoardOptionsWhichRadio(hDlg);
+
+      /*
+       * did any settings change?
+       */
+      if (size != boardSize) {
+       ChangeBoardSize(size);
+      }
+
+      if ((mono != appData.monoMode) ||
+         (lsc  != lightSquareColor) ||
+         (dsc  != darkSquareColor) ||
+         (wpc  != whitePieceColor) ||
+         (bpc  != blackPieceColor) ||
+         (hsc  != highlightSquareColor) ||
+          (flip != appData.upsideDown) ||
+          (white != appData.allWhite) ||
+         (phc  != premoveHighlightColor)) {
+
+         lightSquareColor = lsc;
+         darkSquareColor = dsc;
+         whitePieceColor = wpc;
+         blackPieceColor = bpc;
+         highlightSquareColor = hsc;
+         premoveHighlightColor = phc;
+         appData.monoMode = mono;
+          appData.allWhite = white;
+          appData.upsideDown = flip;
+
+         InitDrawingColors();
+         InitDrawingSizes(boardSize, 0);
+         InvalidateRect(hwndMain, &boardRect, FALSE);
+      }
+      DeleteObject(pieces[0]);
+      DeleteObject(pieces[1]);
+      DeleteObject(pieces[2]);
+      return TRUE;
+
+    case IDCANCEL:
+      DeleteObject(pieces[0]);
+      DeleteObject(pieces[1]);
+      DeleteObject(pieces[2]);
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    case OPT_ChooseLightSquareColor:
+      if (ChangeColor(hDlg, &lsc)) 
+       PaintColorBlock(hDlg, OPT_LightSquareColor, lsc);
+       PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,
+           TRUE, mono, pieces);
+      break;
+
+    case OPT_ChooseDarkSquareColor:
+      if (ChangeColor(hDlg, &dsc)) 
+       PaintColorBlock(hDlg, OPT_DarkSquareColor, dsc);
+       PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,
+           FALSE, mono, pieces);
+      break;
+
+    case OPT_ChooseWhitePieceColor:
+      if (ChangeColor(hDlg, &wpc)) 
+       PaintColorBlock(hDlg, OPT_WhitePieceColor, wpc);
+       PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,
+           TRUE, mono, pieces);
+      break;
+
+    case OPT_ChooseBlackPieceColor:
+      if (ChangeColor(hDlg, &bpc)) 
+       PaintColorBlock(hDlg, OPT_BlackPieceColor, bpc);
+       PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,
+           FALSE, mono, pieces);
+      break;
+
+    case OPT_ChooseHighlightSquareColor:
+      if (ChangeColor(hDlg, &hsc)) 
+       PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc);
+       PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,
+           TRUE, mono, pieces);
+      break;
+
+    case OPT_ChoosePremoveHighlightColor:
+      if (ChangeColor(hDlg, &phc)) 
+       PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc);
+       PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,
+           FALSE, mono, pieces);
+      break;
+
+    case OPT_DefaultBoardColors:
+      lsc = ParseColorName(LIGHT_SQUARE_COLOR);
+      dsc = ParseColorName(DARK_SQUARE_COLOR);
+      wpc = ParseColorName(WHITE_PIECE_COLOR);
+      bpc = ParseColorName(BLACK_PIECE_COLOR);
+      hsc = ParseColorName(HIGHLIGHT_SQUARE_COLOR);
+      phc = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);
+      mono = FALSE;
+      white= FALSE;
+      flip = FALSE;
+      CheckDlgButton(hDlg, OPT_Monochrome, FALSE);
+      CheckDlgButton(hDlg, OPT_AllWhite,   FALSE);
+      CheckDlgButton(hDlg, OPT_UpsideDown, FALSE);
+      PaintColorBlock(hDlg, OPT_LightSquareColor, lsc);
+      PaintColorBlock(hDlg, OPT_DarkSquareColor,  dsc);
+      PaintColorBlock(hDlg, OPT_WhitePieceColor,  wpc);
+      PaintColorBlock(hDlg, OPT_BlackPieceColor,  bpc);
+      PaintColorBlock(hDlg, OPT_HighlightSquareColor, hsc);
+      PaintColorBlock(hDlg, OPT_PremoveHighlightColor, phc);
+      SetBoardOptionEnables(hDlg);
+      PaintSampleSquare(hDlg, OPT_SampleLightSquare, lsc, wpc, hsc, bpc,
+         TRUE, mono, pieces);
+      PaintSampleSquare(hDlg, OPT_SampleDarkSquare, dsc, bpc, phc, wpc,
+         FALSE, mono, pieces);
+      break;
+
+    case OPT_Monochrome:
+      mono = !mono;
+      SetBoardOptionEnables(hDlg);
+      break;
+
+    case OPT_AllWhite:
+      white = !white;
+      SetBoardOptionEnables(hDlg);
+      break;
+
+    case OPT_UpsideDown:
+      flip = !flip;
+      SetBoardOptionEnables(hDlg);
+      break;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+
+VOID
+BoardOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc = MakeProcInstance((FARPROC)BoardOptionsDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_BoardOptions), hwnd,
+         (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
+
+VariantClass
+VariantWhichRadio(HWND hDlg)
+{
+  return (IsDlgButtonChecked(hDlg, OPT_VariantFairy) ? VariantFairy :
+         (IsDlgButtonChecked(hDlg, OPT_VariantGothic) ? VariantGothic :
+         (IsDlgButtonChecked(hDlg, OPT_VariantCrazyhouse) ? VariantCrazyhouse :
+         (IsDlgButtonChecked(hDlg, OPT_VariantBughouse) ? VariantBughouse :
+         (IsDlgButtonChecked(hDlg, OPT_VariantCourier) ? VariantCourier :
+         (IsDlgButtonChecked(hDlg, OPT_VariantShatranj) ? VariantShatranj :
+         (IsDlgButtonChecked(hDlg, OPT_VariantShogi) ? VariantShogi :
+         (IsDlgButtonChecked(hDlg, OPT_VariantXiangqi) ? VariantXiangqi :
+         (IsDlgButtonChecked(hDlg, OPT_VariantCapablanca) ? VariantCapablanca :
+         (IsDlgButtonChecked(hDlg, OPT_VariantTwoKings) ? VariantTwoKings :
+         (IsDlgButtonChecked(hDlg, OPT_VariantKnightmate) ? VariantKnightmate :
+         (IsDlgButtonChecked(hDlg, OPT_VariantLosers) ? VariantLosers :
+         (IsDlgButtonChecked(hDlg, OPT_VariantSuicide) ? VariantSuicide :
+         (IsDlgButtonChecked(hDlg, OPT_VariantAtomic) ? VariantAtomic :
+         (IsDlgButtonChecked(hDlg, OPT_VariantShatranj) ? VariantShatranj :
+         (IsDlgButtonChecked(hDlg, OPT_VariantFRC) ? VariantFischeRandom :
+         (IsDlgButtonChecked(hDlg, OPT_VariantCylinder) ? VariantCylinder :
+         (IsDlgButtonChecked(hDlg, OPT_VariantFalcon) ? VariantFalcon :
+         (IsDlgButtonChecked(hDlg, OPT_VariantCRC) ? VariantCapaRandom :
+         (IsDlgButtonChecked(hDlg, OPT_VariantSuper) ? VariantSuper :
+         (IsDlgButtonChecked(hDlg, OPT_VariantBerolina) ? VariantBerolina :
+         (IsDlgButtonChecked(hDlg, OPT_VariantJanus) ? VariantJanus :
+         (IsDlgButtonChecked(hDlg, OPT_VariantWildcastle) ? VariantWildCastle :
+         (IsDlgButtonChecked(hDlg, OPT_VariantNocastle) ? VariantNoCastle :
+          VariantNormal ))))))))))))))))))))))));
+}
+
+LRESULT CALLBACK
+NewVariantDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  static Boolean  mono;
+  static VariantClass v;
+  static COLORREF lsc, dsc, wpc, bpc, hsc, phc;
+  static HBITMAP pieces[3];
+  static int n1_ok, n2_ok, n3_ok;
+
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+    /* Initialize the dialog items */
+    switch (gameInfo.variant) {
+    case VariantNormal:
+      CheckDlgButton(hDlg, OPT_VariantNormal, TRUE);
+      break;
+    case VariantCrazyhouse:
+      CheckDlgButton(hDlg, OPT_VariantCrazyhouse, TRUE);
+      break;
+    case VariantBughouse:
+      CheckDlgButton(hDlg, OPT_VariantBughouse, TRUE);
+      break;
+    case VariantShogi:
+      CheckDlgButton(hDlg, OPT_VariantShogi, TRUE);
+      break;
+    case VariantXiangqi:
+      CheckDlgButton(hDlg, OPT_VariantXiangqi, TRUE);
+      break;
+    case VariantCapablanca:
+      CheckDlgButton(hDlg, OPT_VariantCapablanca, TRUE);
+      break;
+    case VariantGothic:
+      CheckDlgButton(hDlg, OPT_VariantGothic, TRUE);
+      break;
+    case VariantCourier:
+      CheckDlgButton(hDlg, OPT_VariantCourier, TRUE);
+      break;
+    case VariantKnightmate:
+      CheckDlgButton(hDlg, OPT_VariantKnightmate, TRUE);
+      break;
+    case VariantTwoKings:
+      CheckDlgButton(hDlg, OPT_VariantTwoKings, TRUE);
+      break;
+    case VariantFairy:
+      CheckDlgButton(hDlg, OPT_VariantFairy, TRUE);
+      break;
+    case VariantAtomic:
+      CheckDlgButton(hDlg, OPT_VariantAtomic, TRUE);
+      break;
+    case VariantSuicide:
+      CheckDlgButton(hDlg, OPT_VariantSuicide, TRUE);
+      break;
+    case VariantLosers:
+      CheckDlgButton(hDlg, OPT_VariantLosers, TRUE);
+      break;
+    case VariantShatranj:
+      CheckDlgButton(hDlg, OPT_VariantShatranj, TRUE);
+      break;
+    case VariantFischeRandom:
+      CheckDlgButton(hDlg, OPT_VariantFRC, TRUE);
+      break;
+    case VariantCapaRandom:
+      CheckDlgButton(hDlg, OPT_VariantCRC, TRUE);
+      break;
+    case VariantFalcon:
+      CheckDlgButton(hDlg, OPT_VariantFalcon, TRUE);
+      break;
+    case VariantCylinder:
+      CheckDlgButton(hDlg, OPT_VariantCylinder, TRUE);
+      break;
+    case Variant3Check:
+    case VariantSuper:
+      CheckDlgButton(hDlg, OPT_VariantSuper, TRUE);
+      break;
+    case VariantBerolina:
+      CheckDlgButton(hDlg, OPT_VariantBerolina, TRUE);
+      break;
+    case VariantJanus:
+      CheckDlgButton(hDlg, OPT_VariantJanus, TRUE);
+      break;
+    case VariantWildCastle:
+      CheckDlgButton(hDlg, OPT_VariantWildcastle, TRUE);
+      break;
+    case VariantNoCastle:
+      CheckDlgButton(hDlg, OPT_VariantNocastle, TRUE);
+      break;
+    }
+
+    SetDlgItemInt( hDlg, IDC_Files, -1, TRUE );
+    SendDlgItemMessage( hDlg, IDC_Files, EM_SETSEL, 0, -1 );
+
+    SetDlgItemInt( hDlg, IDC_Ranks, -1, TRUE );
+    SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 );
+
+    SetDlgItemInt( hDlg, IDC_Holdings, -1, TRUE );
+    SendDlgItemMessage( hDlg, IDC_Ranks, EM_SETSEL, 0, -1 );
+
+    n1_ok = n2_ok = n3_ok = FALSE;
+
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* 
+       * if we call EndDialog() after the call to ChangeBoardSize(),
+       * then ChangeBoardSize() does not take effect, although the new
+       * boardSize is saved. Go figure...
+       */
+      EndDialog(hDlg, TRUE);
+
+      v = VariantWhichRadio(hDlg);
+      if(!appData.noChessProgram) { char *name = VariantName(v), buf[MSG_SIZ];
+       if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {
+           /* [HGM] in protocol 2 we check if variant is suported by engine */
+           sprintf(buf, "Variant %s not supported by %s", name, first.tidy);
+           DisplayError(buf, 0);
+           return TRUE; /* treat as "Cancel" if first engine does not support it */
+       } else
+       if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {
+           sprintf(buf, "Warning: second engine (%s) does not support this!", second.tidy);
+           DisplayError(buf, 0);   /* use of second engine is optional; only warn user */
+       }
+      }
+
+      gameInfo.variant = v;
+      appData.variant = VariantName(v);
+
+      appData.NrFiles = (int) GetDlgItemInt(hDlg, IDC_Files, NULL, FALSE );
+      appData.NrRanks = (int) GetDlgItemInt(hDlg, IDC_Ranks, NULL, FALSE );
+      appData.holdingsSize = (int) GetDlgItemInt(hDlg, IDC_Holdings, NULL, FALSE );
+
+      if(!n1_ok) appData.NrFiles = -1;
+      if(!n2_ok) appData.NrRanks = -1;
+      if(!n3_ok) appData.holdingsSize = -1;
+
+      shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */
+      startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */
+      appData.pieceToCharTable = NULL;
+      Reset(TRUE, TRUE);
+
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    case IDC_Ranks:
+    case IDC_Files:
+    case IDC_Holdings:
+        if( HIWORD(wParam) == EN_CHANGE ) {
+
+            GetDlgItemInt(hDlg, IDC_Files, &n1_ok, FALSE );
+            GetDlgItemInt(hDlg, IDC_Ranks, &n2_ok, FALSE );
+            GetDlgItemInt(hDlg, IDC_Holdings, &n3_ok, FALSE );
+
+            /*EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok ? TRUE : FALSE );*/
+        }
+        return TRUE;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+
+VOID
+NewVariantPopup(HWND hwnd)
+{
+  FARPROC lpProc = MakeProcInstance((FARPROC)NewVariantDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_NewVariant), hwnd,
+         (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * ICS Options Dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+
+BOOL APIENTRY
+MyCreateFont(HWND hwnd, MyFont *font)
+{
+  CHOOSEFONT cf;
+  HFONT hf;
+
+  /* Initialize members of the CHOOSEFONT structure. */
+  cf.lStructSize = sizeof(CHOOSEFONT);
+  cf.hwndOwner = hwnd;
+  cf.hDC = (HDC)NULL;
+  cf.lpLogFont = &font->lf;
+  cf.iPointSize = 0;
+  cf.Flags = CF_SCREENFONTS|/*CF_ANSIONLY|*/CF_INITTOLOGFONTSTRUCT;
+  cf.rgbColors = RGB(0,0,0);
+  cf.lCustData = 0L;
+  cf.lpfnHook = (LPCFHOOKPROC)NULL;
+  cf.lpTemplateName = (LPSTR)NULL;
+  cf.hInstance = (HINSTANCE) NULL;
+  cf.lpszStyle = (LPSTR)NULL;
+  cf.nFontType = SCREEN_FONTTYPE;
+  cf.nSizeMin = 0;
+  cf.nSizeMax = 0;
+
+  /* Display the CHOOSEFONT common-dialog box. */
+  if (!ChooseFont(&cf)) {
+    return FALSE;
+  }
+
+  /* Create a logical font based on the user's   */
+  /* selection and return a handle identifying   */
+  /* that font. */
+  hf = CreateFontIndirect(cf.lpLogFont);
+  if (hf == NULL) {
+    return FALSE;
+  }
+
+  font->hf = hf;
+  font->mfp.pointSize = (float) (cf.iPointSize / 10.0);
+  font->mfp.bold = (font->lf.lfWeight >= FW_BOLD);
+  font->mfp.italic = font->lf.lfItalic;
+  font->mfp.underline = font->lf.lfUnderline;
+  font->mfp.strikeout = font->lf.lfStrikeOut;
+  strcpy(font->mfp.faceName, font->lf.lfFaceName);
+  return TRUE;
+}
+
+
+VOID
+UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca)
+{
+  CHARFORMAT cf;
+  cf.cbSize = sizeof(CHARFORMAT);
+  cf.dwMask = 
+    CFM_COLOR|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT|CFM_FACE|CFM_SIZE;
+  cf.crTextColor = mca->color;
+  cf.dwEffects = mca->effects;
+  strcpy(cf.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName);
+  /* 
+   * The 20.0 below is in fact documented. yHeight is expressed in twips.
+   * A twip is 1/20 of a font's point size. See documentation of CHARFORMAT.
+   * --msw
+   */
+  cf.yHeight = (int)(font[boardSize][CONSOLE_FONT]->mfp.pointSize * 20.0 + 0.5);
+  cf.bCharSet = DEFAULT_CHARSET; /* should be ignored anyway */
+  cf.bPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;
+  SendDlgItemMessage(hDlg, id, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+}
+
+LRESULT CALLBACK
+ColorizeTextDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  static MyColorizeAttribs mca;
+  static ColorClass cc;
+  COLORREF background = (COLORREF)0;
+
+  switch (message) {
+  case WM_INITDIALOG:
+    cc = (ColorClass)lParam;
+    mca = colorizeAttribs[cc];
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+    /* Initialize the dialog items */
+    CheckDlgButton(hDlg, OPT_Bold, (mca.effects & CFE_BOLD) != 0);
+    CheckDlgButton(hDlg, OPT_Italic, (mca.effects & CFE_ITALIC) != 0);
+    CheckDlgButton(hDlg, OPT_Underline, (mca.effects & CFE_UNDERLINE) != 0);
+    CheckDlgButton(hDlg, OPT_Strikeout, (mca.effects & CFE_STRIKEOUT) != 0);
+
+    /* get the current background color from the parent window */
+    SendMessage(GetWindow(hDlg, GW_OWNER),WM_COMMAND, 
+               (WPARAM)WM_USER_GetConsoleBackground, 
+               (LPARAM)&background);
+
+    /* set the background color */
+    SendDlgItemMessage(hDlg, OPT_Sample, EM_SETBKGNDCOLOR, FALSE, background);
+
+    SetDlgItemText(hDlg, OPT_Sample, mca.name);
+    UpdateSampleText(hDlg, OPT_Sample, &mca);
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* Read changed options from the dialog box */
+      colorizeAttribs[cc] = mca;
+      textAttribs[cc].color = mca.color;
+      textAttribs[cc].effects = mca.effects;
+      Colorize(currentColorClass, TRUE);
+      if (cc == ColorNormal) {
+       CHARFORMAT cf;
+       cf.cbSize = sizeof(CHARFORMAT);
+       cf.dwMask = CFM_COLOR;
+       cf.crTextColor = mca.color;
+       SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, 
+         EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+      }
+      EndDialog(hDlg, TRUE);
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    case OPT_ChooseColor:
+      ChangeColor(hDlg, &mca.color);
+      UpdateSampleText(hDlg, OPT_Sample, &mca);
+      return TRUE;
+
+    default:
+      mca.effects =
+       (IsDlgButtonChecked(hDlg, OPT_Bold) ? CFE_BOLD : 0) |
+       (IsDlgButtonChecked(hDlg, OPT_Italic) ? CFE_ITALIC : 0) |
+       (IsDlgButtonChecked(hDlg, OPT_Underline) ? CFE_UNDERLINE : 0) |
+       (IsDlgButtonChecked(hDlg, OPT_Strikeout) ? CFE_STRIKEOUT : 0);
+      UpdateSampleText(hDlg, OPT_Sample, &mca);
+      break;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+VOID
+ColorizeTextPopup(HWND hwnd, ColorClass cc)
+{
+  FARPROC lpProc;
+
+  lpProc = MakeProcInstance((FARPROC)ColorizeTextDialog, hInst);
+  DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_Colorize),
+    hwnd, (DLGPROC)lpProc, (LPARAM) cc);
+  FreeProcInstance(lpProc);
+}
+
+VOID
+SetIcsOptionEnables(HWND hDlg)
+{
+#define ENABLE_DLG_ITEM(x,y) EnableWindow(GetDlgItem(hDlg,(x)), (y))
+
+  UINT state = IsDlgButtonChecked(hDlg, OPT_Premove);
+  ENABLE_DLG_ITEM(OPT_PremoveWhite, state);
+  ENABLE_DLG_ITEM(OPT_PremoveWhiteText, state);
+  ENABLE_DLG_ITEM(OPT_PremoveBlack, state);
+  ENABLE_DLG_ITEM(OPT_PremoveBlackText, state);
+
+  ENABLE_DLG_ITEM(OPT_IcsAlarmTime, IsDlgButtonChecked(hDlg, OPT_IcsAlarm));
+
+#undef ENABLE_DLG_ITEM
+}
+
+
+LRESULT CALLBACK
+IcsOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  char buf[MSG_SIZ];
+  int number;
+  int i;
+  static COLORREF cbc;
+  static MyColorizeAttribs *mca;
+  COLORREF *colorref;
+
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+
+    mca = colorizeAttribs;
+
+    for (i=0; i < NColorClasses - 1; i++) {
+      mca[i].color   = textAttribs[i].color;
+      mca[i].effects = textAttribs[i].effects;
+    }
+    cbc = consoleBackgroundColor;
+
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+    /* Initialize the dialog items */
+#define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))
+
+    CHECK_BOX(OPT_AutoComment, appData.autoComment);
+    CHECK_BOX(OPT_AutoObserve, appData.autoObserve);
+    CHECK_BOX(OPT_GetMoveList, appData.getMoveList);
+    CHECK_BOX(OPT_LocalLineEditing, appData.localLineEditing);
+    CHECK_BOX(OPT_QuietPlay, appData.quietPlay);
+    CHECK_BOX(OPT_Premove, appData.premove);
+    CHECK_BOX(OPT_PremoveWhite, appData.premoveWhite);
+    CHECK_BOX(OPT_PremoveBlack, appData.premoveBlack);
+    CHECK_BOX(OPT_IcsAlarm, appData.icsAlarm);
+    CHECK_BOX(OPT_DontColorize, !appData.colorize);
+
+#undef CHECK_BOX
+
+    sprintf(buf, "%d", appData.icsAlarmTime / 1000);
+    SetDlgItemText(hDlg, OPT_IcsAlarmTime, buf);
+    SetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText);
+    SetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText);
+
+    SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);
+    SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);
+    SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);
+    SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);
+    SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);
+    SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);
+    SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);
+    SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);
+    SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);
+    SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);
+
+    SetDlgItemText(hDlg, OPT_SampleShout,     mca[ColorShout].name);
+    SetDlgItemText(hDlg, OPT_SampleSShout,    mca[ColorSShout].name);
+    SetDlgItemText(hDlg, OPT_SampleChannel1,  mca[ColorChannel1].name);
+    SetDlgItemText(hDlg, OPT_SampleChannel,   mca[ColorChannel].name);
+    SetDlgItemText(hDlg, OPT_SampleKibitz,    mca[ColorKibitz].name);
+    SetDlgItemText(hDlg, OPT_SampleTell,      mca[ColorTell].name);
+    SetDlgItemText(hDlg, OPT_SampleChallenge, mca[ColorChallenge].name);
+    SetDlgItemText(hDlg, OPT_SampleRequest,   mca[ColorRequest].name);
+    SetDlgItemText(hDlg, OPT_SampleSeek,      mca[ColorSeek].name);
+    SetDlgItemText(hDlg, OPT_SampleNormal,    mca[ColorNormal].name);
+
+    UpdateSampleText(hDlg, OPT_SampleShout,     &mca[ColorShout]);
+    UpdateSampleText(hDlg, OPT_SampleSShout,    &mca[ColorSShout]);
+    UpdateSampleText(hDlg, OPT_SampleChannel1,  &mca[ColorChannel1]);
+    UpdateSampleText(hDlg, OPT_SampleChannel,   &mca[ColorChannel]);
+    UpdateSampleText(hDlg, OPT_SampleKibitz,    &mca[ColorKibitz]);
+    UpdateSampleText(hDlg, OPT_SampleTell,      &mca[ColorTell]);
+    UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);
+    UpdateSampleText(hDlg, OPT_SampleRequest,   &mca[ColorRequest]);
+    UpdateSampleText(hDlg, OPT_SampleSeek,      &mca[ColorSeek]);
+    UpdateSampleText(hDlg, OPT_SampleNormal,    &mca[ColorNormal]);
+
+    SetIcsOptionEnables(hDlg);
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+
+    case WM_USER_GetConsoleBackground: 
+      /* the ColorizeTextDialog needs the current background color */
+      colorref = (COLORREF *)lParam;
+      *colorref = cbc;
+      return FALSE;
+
+    case IDOK:
+      /* Read changed options from the dialog box */
+      GetDlgItemText(hDlg, OPT_IcsAlarmTime, buf, MSG_SIZ);
+      if (sscanf(buf, "%d", &number) != 1 || (number < 0)){
+         MessageBox(hDlg, "Invalid ICS Alarm Time",
+                    "Option Error", MB_OK|MB_ICONEXCLAMATION);
+         return FALSE;
+      }
+
+#define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))
+
+      appData.icsAlarm         = IS_CHECKED(OPT_IcsAlarm);
+      appData.premove          = IS_CHECKED(OPT_Premove);
+      appData.premoveWhite     = IS_CHECKED(OPT_PremoveWhite);
+      appData.premoveBlack     = IS_CHECKED(OPT_PremoveBlack);
+      appData.autoComment      = IS_CHECKED(OPT_AutoComment);
+      appData.autoObserve      = IS_CHECKED(OPT_AutoObserve);
+      appData.getMoveList      = IS_CHECKED(OPT_GetMoveList);
+      appData.localLineEditing = IS_CHECKED(OPT_LocalLineEditing);
+      appData.quietPlay        = IS_CHECKED(OPT_QuietPlay);
+
+#undef IS_CHECKED
+
+      appData.icsAlarmTime = number * 1000;
+      GetDlgItemText(hDlg, OPT_PremoveWhiteText, appData.premoveWhiteText, 5);
+      GetDlgItemText(hDlg, OPT_PremoveBlackText, appData.premoveBlackText, 5);
+
+      if (appData.localLineEditing) {
+       DontEcho();
+       EchoOn();
+      } else {
+       DoEcho();
+       EchoOff();
+      }
+
+      appData.colorize =
+       (Boolean)!IsDlgButtonChecked(hDlg, OPT_DontColorize);
+
+      if (!appData.colorize) {
+       CHARFORMAT cf;
+       COLORREF background = ParseColorName(COLOR_BKGD);
+       /*
+       SetDefaultTextAttribs();
+        Colorize(currentColorClass);
+       */
+       cf.cbSize = sizeof(CHARFORMAT);
+       cf.dwMask = CFM_COLOR;
+       cf.crTextColor = ParseColorName(COLOR_NORMAL);
+
+       SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, 
+         EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);
+        SendDlgItemMessage(hwndConsole, OPT_ConsoleText, 
+         EM_SETBKGNDCOLOR, FALSE, background);
+       SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, 
+         EM_SETBKGNDCOLOR, FALSE, background);
+      }
+
+      if (cbc != consoleBackgroundColor) {
+       consoleBackgroundColor = cbc;
+       if (appData.colorize) {
+         SendDlgItemMessage(hwndConsole, OPT_ConsoleText, 
+           EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);
+         SendDlgItemMessage(hwndConsole, OPT_ConsoleInput, 
+           EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);
+       }
+      }
+
+      for (i=0; i < NColorClasses - 1; i++) {
+       textAttribs[i].color   = mca[i].color;
+       textAttribs[i].effects = mca[i].effects;
+      }
+
+      EndDialog(hDlg, TRUE);
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    case OPT_ChooseShoutColor:
+      ColorizeTextPopup(hDlg, ColorShout);
+      UpdateSampleText(hDlg, OPT_SampleShout, &mca[ColorShout]);
+      break;
+
+    case OPT_ChooseSShoutColor:
+      ColorizeTextPopup(hDlg, ColorSShout);
+      UpdateSampleText(hDlg, OPT_SampleSShout, &mca[ColorSShout]);
+      break;
+
+    case OPT_ChooseChannel1Color:
+      ColorizeTextPopup(hDlg, ColorChannel1);
+      UpdateSampleText(hDlg, OPT_SampleChannel1, 
+                      &colorizeAttribs[ColorChannel1]);
+      break;
+
+    case OPT_ChooseChannelColor:
+      ColorizeTextPopup(hDlg, ColorChannel);
+      UpdateSampleText(hDlg, OPT_SampleChannel, &mca[ColorChannel]);
+      break;
+
+    case OPT_ChooseKibitzColor:
+      ColorizeTextPopup(hDlg, ColorKibitz);
+      UpdateSampleText(hDlg, OPT_SampleKibitz, &mca[ColorKibitz]);
+      break;
+
+    case OPT_ChooseTellColor:
+      ColorizeTextPopup(hDlg, ColorTell);
+      UpdateSampleText(hDlg, OPT_SampleTell, &mca[ColorTell]);
+      break;
+
+    case OPT_ChooseChallengeColor:
+      ColorizeTextPopup(hDlg, ColorChallenge);
+      UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);
+      break;
+
+    case OPT_ChooseRequestColor:
+      ColorizeTextPopup(hDlg, ColorRequest);
+      UpdateSampleText(hDlg, OPT_SampleRequest, &mca[ColorRequest]);
+      break;
+
+    case OPT_ChooseSeekColor:
+      ColorizeTextPopup(hDlg, ColorSeek);
+      UpdateSampleText(hDlg, OPT_SampleSeek, &mca[ColorSeek]);
+      break;
+
+    case OPT_ChooseNormalColor:
+      ColorizeTextPopup(hDlg, ColorNormal);
+      UpdateSampleText(hDlg, OPT_SampleNormal, &mca[ColorNormal]);
+      break;
+
+    case OPT_ChooseBackgroundColor:
+      if (ChangeColor(hDlg, &cbc)) {
+       SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);
+       SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);
+       SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);
+       SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);
+       SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);
+       SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);
+       SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);
+       SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);
+       SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);
+       SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);
+      }
+      break;
+
+    case OPT_DefaultColors:
+      for (i=0; i < NColorClasses - 1; i++)
+       ParseAttribs(&mca[i].color, 
+                    &mca[i].effects,
+                    defaultTextAttribs[i]);
+
+      cbc = ParseColorName(COLOR_BKGD);
+      SendDlgItemMessage(hDlg, OPT_SampleShout,     EM_SETBKGNDCOLOR, 0, cbc);
+      SendDlgItemMessage(hDlg, OPT_SampleSShout,    EM_SETBKGNDCOLOR, 0, cbc);
+      SendDlgItemMessage(hDlg, OPT_SampleChannel1,  EM_SETBKGNDCOLOR, 0, cbc);
+      SendDlgItemMessage(hDlg, OPT_SampleChannel,   EM_SETBKGNDCOLOR, 0, cbc);
+      SendDlgItemMessage(hDlg, OPT_SampleKibitz,    EM_SETBKGNDCOLOR, 0, cbc);
+      SendDlgItemMessage(hDlg, OPT_SampleTell,      EM_SETBKGNDCOLOR, 0, cbc);
+      SendDlgItemMessage(hDlg, OPT_SampleChallenge, EM_SETBKGNDCOLOR, 0, cbc);
+      SendDlgItemMessage(hDlg, OPT_SampleRequest,   EM_SETBKGNDCOLOR, 0, cbc);
+      SendDlgItemMessage(hDlg, OPT_SampleSeek,      EM_SETBKGNDCOLOR, 0, cbc);
+      SendDlgItemMessage(hDlg, OPT_SampleNormal,    EM_SETBKGNDCOLOR, 0, cbc);
+
+      UpdateSampleText(hDlg, OPT_SampleShout,     &mca[ColorShout]);
+      UpdateSampleText(hDlg, OPT_SampleSShout,    &mca[ColorSShout]);
+      UpdateSampleText(hDlg, OPT_SampleChannel1,  &mca[ColorChannel1]);
+      UpdateSampleText(hDlg, OPT_SampleChannel,   &mca[ColorChannel]);
+      UpdateSampleText(hDlg, OPT_SampleKibitz,    &mca[ColorKibitz]);
+      UpdateSampleText(hDlg, OPT_SampleTell,      &mca[ColorTell]);
+      UpdateSampleText(hDlg, OPT_SampleChallenge, &mca[ColorChallenge]);
+      UpdateSampleText(hDlg, OPT_SampleRequest,   &mca[ColorRequest]);
+      UpdateSampleText(hDlg, OPT_SampleSeek,      &mca[ColorSeek]);
+      UpdateSampleText(hDlg, OPT_SampleNormal,    &mca[ColorNormal]);
+      break;
+
+    default:
+      SetIcsOptionEnables(hDlg);
+      break;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+VOID
+IcsOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc = MakeProcInstance((FARPROC)IcsOptionsDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_IcsOptions), hwnd,
+           (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * Fonts Dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+
+VOID
+SetSampleFontText(HWND hwnd, int id, const MyFont *mf)
+{
+  char buf[MSG_SIZ];
+  HWND hControl;
+  HDC hdc;
+  CHARFORMAT cf;
+  SIZE size;
+  RECT rectClient, rectFormat;
+  HFONT oldFont;
+  POINT center;
+  int len;
+
+  len = sprintf(buf, "%.0f pt. %s%s%s\n",
+               mf->mfp.pointSize, mf->mfp.faceName,
+               mf->mfp.bold ? " bold" : "",
+               mf->mfp.italic ? " italic" : "");
+  SetDlgItemText(hwnd, id, buf);
+
+  hControl = GetDlgItem(hwnd, id);
+  hdc = GetDC(hControl);
+  SetMapMode(hdc, MM_TEXT);    /* 1 pixel == 1 logical unit */
+  oldFont = SelectObject(hdc, mf->hf);
+  
+  /* get number of logical units necessary to display font name */
+  GetTextExtentPoint32(hdc, buf, len, &size);
+
+  /* calculate formatting rectangle in the rich edit control.  
+   * May be larger or smaller than the actual control.
+   */
+  GetClientRect(hControl, &rectClient);
+  center.x = (rectClient.left + rectClient.right) / 2;
+  center.y = (rectClient.top  + rectClient.bottom) / 2;
+  rectFormat.top    = center.y - (size.cy / 2) - 1;
+  rectFormat.bottom = center.y + (size.cy / 2) + 1;
+  rectFormat.left   = center.x - (size.cx / 2) - 1;
+  rectFormat.right  = center.x + (size.cx / 2) + 1;
+
+#if 0
+  fprintf(debugFP, "\nfont: %s\n"
+                   "center.x   %d, centerY %d\n"
+                  "size.cx    %d, size.cy %d\n"
+                  "client.top %d, bottom %d, left %d, right %d\n"
+                  "format.top %d, bottom %d, left %d, right %d\n",
+                  buf,
+                  center.x, center.y,
+                  size.cx, size.cy,
+                  rectClient.top, rectClient.bottom, rectClient.left,
+                  rectClient.right,
+                  rectFormat.top, rectFormat.bottom, rectFormat.left,
+                  rectFormat.right);
+#endif
+
+  cf.cbSize = sizeof(CHARFORMAT);
+  cf.dwMask = CFM_FACE|CFM_SIZE|CFM_CHARSET|CFM_BOLD|CFM_ITALIC;
+  cf.dwEffects = 0;
+  if (mf->lf.lfWeight == FW_BOLD) cf.dwEffects |= CFE_BOLD;
+  if (mf->lf.lfItalic) cf.dwEffects |= CFE_ITALIC;
+  strcpy(cf.szFaceName, mf->mfp.faceName);
+  /*
+   * yHeight is expressed in twips.  A twip is 1/20 of a font's point
+   * size. See documentation of CHARFORMAT.  --msw
+   */
+  cf.yHeight = (int)(mf->mfp.pointSize * 20.0 + 0.5);
+  cf.bCharSet = mf->lf.lfCharSet;
+  cf.bPitchAndFamily = mf->lf.lfPitchAndFamily;
+
+  /* format the text in the rich edit control */
+  SendMessage(hControl, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cf);
+  SendMessage(hControl, EM_SETRECT, (WPARAM)0, (LPARAM) &rectFormat);
+
+  /* clean up */
+  SelectObject(hdc, oldFont);
+  ReleaseDC(hControl, hdc);
+}
+
+VOID
+CopyFont(MyFont *dest, const MyFont *src)
+{
+  dest->mfp.pointSize = src->mfp.pointSize;
+  dest->mfp.bold      = src->mfp.bold;
+  dest->mfp.italic    = src->mfp.italic;
+  dest->mfp.underline = src->mfp.underline;
+  dest->mfp.strikeout = src->mfp.strikeout;
+  lstrcpy(dest->mfp.faceName, src->mfp.faceName);
+  CreateFontInMF(dest);
+}
+
+
+LRESULT CALLBACK
+FontOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  static MyFont workFont[NUM_FONTS];
+  static BOOL firstPaint;
+  int i;
+  RECT rect;
+
+  switch (message) {
+  case WM_INITDIALOG:
+
+    /* copy the current font settings into a working copy */
+    for (i=0; i < NUM_FONTS; i++)
+      CopyFont(&workFont[i], font[boardSize][i]);
+
+    if (!appData.icsActive)
+      EnableWindow(GetDlgItem(hDlg, OPT_ChooseConsoleFont), FALSE);
+
+    firstPaint = TRUE; /* see rant below */
+
+    /* If I don't call SetFocus(), the dialog won't respond to the keyboard
+     * when first drawn. Why is this the only dialog that behaves this way? Is
+     * is the WM_PAINT stuff below?? Sigh...
+     */
+    SetFocus(GetDlgItem(hDlg, IDOK));
+    break;
+
+  case WM_PAINT:
+    /* This should not be necessary. However, if SetSampleFontText() is called
+     * in response to WM_INITDIALOG, the strings are not properly centered in
+     * the controls when the dialog first appears. I can't figure out why, so
+     * this is the workaround.  --msw
+     */
+    if (firstPaint) {
+      SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);
+      firstPaint = FALSE;
+    }
+    break;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+
+    case IDOK:
+      /* again, it seems to avoid redraw problems if we call EndDialog first */
+      EndDialog(hDlg, FALSE);
+
+      /* copy modified settings back to the fonts array */
+      for (i=0; i < NUM_FONTS; i++)
+       CopyFont(font[boardSize][i], &workFont[i]);
+
+      /* a sad necessity due to the original design of having a separate
+       * console font, tags font, and comment font for each board size.  IMHO
+       * these fonts should not be dependent on the current board size.  I'm
+       * running out of time, so I am doing this hack rather than redesign the
+       * data structure. Besides, I think if I redesigned the data structure, I
+       * might break backwards compatibility with old winboard.ini files.
+       * --msw
+       */
+      for (i=0; i < NUM_SIZES; i++) {
+       CopyFont(font[i][EDITTAGS_FONT], &workFont[EDITTAGS_FONT]);
+       CopyFont(font[i][CONSOLE_FONT],  &workFont[CONSOLE_FONT]);
+       CopyFont(font[i][COMMENT_FONT],  &workFont[COMMENT_FONT]);
+       CopyFont(font[i][MOVEHISTORY_FONT],  &workFont[MOVEHISTORY_FONT]);
+      }
+      /* end sad necessity */
+
+      InitDrawingSizes(boardSize, 0);
+      InvalidateRect(hwndMain, NULL, TRUE);
+
+      if (commentDialog) {
+       SendDlgItemMessage(commentDialog, OPT_CommentText,
+         WM_SETFONT, (WPARAM)font[boardSize][COMMENT_FONT]->hf, 
+         MAKELPARAM(TRUE, 0));
+       GetClientRect(GetDlgItem(commentDialog, OPT_CommentText), &rect);
+       InvalidateRect(commentDialog, &rect, TRUE);
+      }
+
+      if (editTagsDialog) {
+       SendDlgItemMessage(editTagsDialog, OPT_TagsText,
+         WM_SETFONT, (WPARAM)font[boardSize][EDITTAGS_FONT]->hf, 
+         MAKELPARAM(TRUE, 0));
+       GetClientRect(GetDlgItem(editTagsDialog, OPT_TagsText), &rect);
+       InvalidateRect(editTagsDialog, &rect, TRUE);
+      }
+
+      if( moveHistoryDialog != NULL ) {
+       SendDlgItemMessage(moveHistoryDialog, IDC_MoveHistory,
+         WM_SETFONT, (WPARAM)font[boardSize][MOVEHISTORY_FONT]->hf, 
+         MAKELPARAM(TRUE, 0));
+       InvalidateRect(editTagsDialog, NULL, TRUE);
+      }
+
+      if (hwndConsole) {
+       ChangedConsoleFont();
+      }
+
+      for (i=0; i<NUM_FONTS; i++)
+       DeleteObject(&workFont[i].hf);
+
+      return TRUE;
+
+    case IDCANCEL:
+      for (i=0; i<NUM_FONTS; i++)
+       DeleteObject(&workFont[i].hf);
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    case OPT_ChooseClockFont:
+      MyCreateFont(hDlg, &workFont[CLOCK_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);
+      break;
+
+    case OPT_ChooseMessageFont:
+      MyCreateFont(hDlg, &workFont[MESSAGE_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);
+      break;
+
+    case OPT_ChooseCoordFont:
+      MyCreateFont(hDlg, &workFont[COORD_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);
+      break;
+
+    case OPT_ChooseTagFont:
+      MyCreateFont(hDlg, &workFont[EDITTAGS_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);
+      break;
+
+    case OPT_ChooseCommentsFont:
+      MyCreateFont(hDlg, &workFont[COMMENT_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);
+      break;
+
+    case OPT_ChooseConsoleFont:
+      MyCreateFont(hDlg, &workFont[CONSOLE_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);
+      break;
+
+    case OPT_ChooseMoveHistoryFont:
+      MyCreateFont(hDlg, &workFont[MOVEHISTORY_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);
+      break;
+
+    case OPT_DefaultFonts:
+      for (i=0; i<NUM_FONTS; i++) {
+       DeleteObject(&workFont[i].hf);
+       ParseFontName(font[boardSize][i]->def, &workFont[i].mfp);
+       CreateFontInMF(&workFont[i]);
+      }
+      SetSampleFontText(hDlg, OPT_SampleClockFont, &workFont[CLOCK_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleMessageFont, &workFont[MESSAGE_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleCoordFont, &workFont[COORD_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleTagFont, &workFont[EDITTAGS_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleCommentsFont, &workFont[COMMENT_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleConsoleFont, &workFont[CONSOLE_FONT]);
+      SetSampleFontText(hDlg, OPT_SampleMoveHistoryFont, &workFont[MOVEHISTORY_FONT]);
+      break;
+    }
+  }
+  return FALSE;
+}
+
+VOID
+FontsOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc = MakeProcInstance((FARPROC)FontOptionsDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_Fonts), hwnd,
+         (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * Sounds Dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+
+
+SoundComboData soundComboData[] = {
+  {"Move", NULL},
+  {"Bell", NULL},
+  {"ICS Alarm", NULL},
+  {"ICS Win", NULL},
+  {"ICS Loss", NULL},
+  {"ICS Draw", NULL},
+  {"ICS Unfinished", NULL},
+  {"Shout", NULL},
+  {"SShout/CShout", NULL},
+  {"Channel 1", NULL},
+  {"Channel", NULL},
+  {"Kibitz", NULL},
+  {"Tell", NULL},
+  {"Challenge", NULL},
+  {"Request", NULL},
+  {"Seek", NULL},
+  {NULL, NULL},
+};
+
+
+void
+InitSoundComboData(SoundComboData *scd)
+{
+  SoundClass sc;
+  ColorClass cc;
+  int index;
+
+  /* copy current sound settings to combo array */
+
+  for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {
+    scd[sc].name = strdup(sounds[sc].name);
+  }
+  for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {
+    index = (int)cc + (int)NSoundClasses;
+    scd[index].name = strdup(textAttribs[cc].sound.name);
+  }
+}
+
+
+void
+ResetSoundComboData(SoundComboData *scd)
+{
+  while (scd->label) {
+    if (scd->name != NULL) {
+      free (scd->name);
+      scd->name = NULL;
+    }
+    scd++;
+  }
+}
+
+void
+InitSoundCombo(HWND hwndCombo, SoundComboData *scd)
+{
+  char buf[255];
+  DWORD err;
+  DWORD cnt = 0;
+  SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);
+
+  /* send the labels to the combo box */
+  while (scd->label) {
+    err = SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) scd->label);
+    if (err != cnt++) {
+      sprintf(buf, "InitSoundCombo(): err '%d', cnt '%d'\n",
+         err, cnt);
+      MessageBox(NULL, buf, NULL, MB_OK);
+    }
+    scd++;
+  }
+  SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);
+}
+
+int
+SoundDialogWhichRadio(HWND hDlg)
+{
+  if (IsDlgButtonChecked(hDlg, OPT_NoSound)) return OPT_NoSound;
+  if (IsDlgButtonChecked(hDlg, OPT_DefaultBeep)) return OPT_DefaultBeep;
+  if (IsDlgButtonChecked(hDlg, OPT_BuiltInSound)) return OPT_BuiltInSound;
+  if (IsDlgButtonChecked(hDlg, OPT_WavFile)) return OPT_WavFile;
+  return -1;
+}
+
+VOID
+SoundDialogSetEnables(HWND hDlg, int radio)
+{
+  EnableWindow(GetDlgItem(hDlg, OPT_BuiltInSoundName),
+              radio == OPT_BuiltInSound);
+  EnableWindow(GetDlgItem(hDlg, OPT_WavFileName), radio == OPT_WavFile);
+  EnableWindow(GetDlgItem(hDlg, OPT_BrowseSound), radio == OPT_WavFile);
+}
+
+char *
+SoundDialogGetName(HWND hDlg, int radio)
+{
+  static char buf[MSG_SIZ], buf2[MSG_SIZ], buf3[MSG_SIZ];
+  char *dummy, *ret;
+  switch (radio) {
+  case OPT_NoSound:
+  default:
+    return "";
+  case OPT_DefaultBeep:
+    return "$";
+  case OPT_BuiltInSound:
+    buf[0] = '!';
+    GetDlgItemText(hDlg, OPT_BuiltInSoundName, buf + 1, sizeof(buf) - 1);
+    return buf;
+  case OPT_WavFile:
+    GetDlgItemText(hDlg, OPT_WavFileName, buf, sizeof(buf));
+    GetCurrentDirectory(MSG_SIZ, buf3);
+    SetCurrentDirectory(installDir);
+    if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) {
+      ret = buf2;
+    } else {
+      ret = buf;
+    }
+    SetCurrentDirectory(buf3);
+    return ret;
+  }
+}
+
+void
+DisplaySelectedSound(HWND hDlg, HWND hCombo, const char *name)
+{
+  int radio;
+  /* 
+   * I think it's best to clear the combo and edit boxes. It looks stupid
+   * to have a value from another sound event sitting there grayed out.
+   */
+  SetDlgItemText(hDlg, OPT_WavFileName, "");
+  SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
+
+  if (appData.debugMode)
+      fprintf(debugFP, "DisplaySelectedSound(,,'%s'):\n", name);
+  switch (name[0]) {
+  case NULLCHAR:
+    radio = OPT_NoSound;
+    break;
+  case '$':
+    if (name[1] == NULLCHAR) {
+      radio = OPT_DefaultBeep;
+    } else {
+      radio = OPT_WavFile;
+      SetDlgItemText(hDlg, OPT_WavFileName, name);
+    }
+    break;
+  case '!':
+    if (name[1] == NULLCHAR) {
+      radio = OPT_NoSound;
+    } else {
+      radio = OPT_BuiltInSound;
+      if (SendMessage(hCombo, CB_SELECTSTRING, (WPARAM) -1, 
+                     (LPARAM) (name + 1)) == CB_ERR) {
+       SendMessage(hCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
+       SendMessage(hCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) (name + 1));
+      }
+    }
+    break;
+  default:
+    radio = OPT_WavFile;
+    SetDlgItemText(hDlg, OPT_WavFileName, name);
+    break;
+  }
+  SoundDialogSetEnables(hDlg, radio);
+  CheckRadioButton(hDlg, OPT_NoSound, OPT_WavFile, radio);
+}
+    
+
+char *builtInSoundNames[] = BUILT_IN_SOUND_NAMES;
+
+LRESULT CALLBACK
+SoundOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  static HWND hSoundCombo;
+  static DWORD index;
+  static HWND hBISN;
+  int radio;
+  MySound tmp;
+  FILE *f;
+  char buf[MSG_SIZ];
+  char *newName;
+  SoundClass sc;
+  ColorClass cc;
+  SoundComboData *scd;
+
+  switch (message) {
+  case WM_INITDIALOG:
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+    /* Initialize the built-in sounds combo */
+    hBISN = GetDlgItem(hDlg, OPT_BuiltInSoundName);
+     InitComboStrings(hBISN, builtInSoundNames);
+
+    /* Initialize the  sound events combo */
+    index = 0;
+    InitSoundComboData(soundComboData);
+    hSoundCombo = GetDlgItem(hDlg, CBO_Sounds);
+    InitSoundCombo(hSoundCombo, soundComboData);
+
+    /* update the dialog */
+    DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+
+    if (((HWND)lParam == hSoundCombo) && 
+       (HIWORD(wParam) == CBN_SELCHANGE)) {
+      /* 
+       * the user has selected a new sound event. We must store the name for
+       * the previously selected event, then retrieve the name for the
+       * newly selected event and update the dialog. 
+       */
+      radio = SoundDialogWhichRadio(hDlg);
+      newName = strdup(SoundDialogGetName(hDlg, radio));
+      
+      if (strcmp(newName, soundComboData[index].name) != 0) {
+       free(soundComboData[index].name);
+       soundComboData[index].name = newName;
+      } else {
+       free(newName);
+       newName = NULL;
+      }
+      /* now get the settings for the newly selected event */
+      index = SendMessage(hSoundCombo, CB_GETCURSEL, (WPARAM)0, (LPARAM)0);
+      DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);
+      
+      return TRUE;
+    }
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* 
+       * save the name for the currently selected sound event 
+       */
+      radio = SoundDialogWhichRadio(hDlg);
+      newName = strdup(SoundDialogGetName(hDlg, radio));
+
+      if (strcmp(soundComboData[index].name, newName) != 0) {
+       free(soundComboData[index].name);
+       soundComboData[index].name = newName;
+      } else {
+       free(newName);
+       newName = NULL;
+      }
+
+      /* save all the sound names that changed and load the sounds */
+
+      for ( sc = (SoundClass)0; sc < NSoundClasses; sc++) {
+       if (strcmp(soundComboData[sc].name, sounds[sc].name) != 0) {
+         free(sounds[sc].name);
+         sounds[sc].name = strdup(soundComboData[sc].name);
+         MyLoadSound(&sounds[sc]);
+       }
+      }
+      for ( cc = (ColorClass)0; cc < NColorClasses - 2; cc++) {
+       index = (int)cc + (int)NSoundClasses;
+       if (strcmp(soundComboData[index].name, 
+                  textAttribs[cc].sound.name) != 0) {
+         free(textAttribs[cc].sound.name);
+         textAttribs[cc].sound.name = strdup(soundComboData[index].name);
+         MyLoadSound(&textAttribs[cc].sound);
+       }
+      }
+
+      ResetSoundComboData(soundComboData);
+      EndDialog(hDlg, TRUE);
+      return TRUE;
+
+    case IDCANCEL:
+      ResetSoundComboData(soundComboData);
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    case OPT_DefaultSounds:
+      /* can't use SetDefaultSounds() because we need to be able to "undo" if
+       * user selects "Cancel" later on. So we do it the hard way here.
+       */
+      scd = &soundComboData[0];
+      while (scd->label != NULL) {
+       if (scd->name != NULL) free(scd->name);
+       scd->name = strdup("");
+       scd++;
+      }
+      free(soundComboData[(int)SoundBell].name);
+      soundComboData[(int)SoundBell].name = strdup(SOUND_BELL);
+      DisplaySelectedSound(hDlg, hBISN, soundComboData[index].name);
+      break;
+
+    case OPT_PlaySound:
+      radio = SoundDialogWhichRadio(hDlg);
+      tmp.name = strdup(SoundDialogGetName(hDlg, radio));
+      tmp.data = NULL;
+      MyLoadSound(&tmp);
+      MyPlaySound(&tmp);
+      if (tmp.data  != NULL) free(tmp.data);
+      if (tmp.name != NULL) free(tmp.name);
+      return TRUE;
+
+    case OPT_BrowseSound:
+      f = OpenFileDialog(hDlg, "rb", NULL, "wav", SOUND_FILT,
+       "Browse for Sound File", NULL, NULL, buf);
+      if (f != NULL) {
+       fclose(f);
+       SetDlgItemText(hDlg, OPT_WavFileName, buf);
+      }
+      return TRUE;
+
+    default:
+      radio = SoundDialogWhichRadio(hDlg);
+      SoundDialogSetEnables(hDlg, radio);
+      break;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+
+VOID SoundOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc;
+
+  lpProc = MakeProcInstance((FARPROC)SoundOptionsDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_Sound), hwnd, (DLGPROC)lpProc);
+  FreeProcInstance(lpProc);
+}
+
+
+/*---------------------------------------------------------------------------*\
+ *
+ * Comm Port dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+
+
+#define FLOW_NONE   0
+#define FLOW_XOFF   1
+#define FLOW_CTS    2
+#define FLOW_DSR    3
+
+#define PORT_NONE
+
+ComboData cdPort[]     = { {"None", PORT_NONE}, {"COM1", 1}, {"COM2", 2},
+                          {"COM3", 3}, {"COM4", 4}, {NULL, 0} };
+ComboData cdDataRate[] = { {"110", 110}, {"300", 300}, {"600", 600}, {"1200", 1200},
+                          {"2400", 2400}, {"4800", 4800}, {"9600", 9600}, {"19200", 19200},
+                          {"38400", 38400}, {NULL, 0} };
+ComboData cdDataBits[] = { {"5", 5}, {"6", 6}, {"7", 7}, {"8", 8}, {NULL, 0} };
+ComboData cdParity[]   = { {"None", NOPARITY}, {"Odd", ODDPARITY}, {"Even", EVENPARITY},
+                          {"Mark", MARKPARITY}, {"Space", SPACEPARITY}, {NULL, 0} };
+ComboData cdStopBits[] = { {"1", ONESTOPBIT}, {"1.5", ONE5STOPBITS},
+                          {"2", TWOSTOPBITS}, {NULL, 0} };
+ComboData cdFlow[]     = { {"None", FLOW_NONE}, {"Xoff/Xon", FLOW_XOFF}, {"CTS", FLOW_CTS},
+                          {"DSR", FLOW_DSR}, {NULL, 0} };
+
+
+VOID
+ParseCommSettings(char *arg, DCB *dcb)
+{
+  int dataRate, count;
+  char bits[MSG_SIZ], parity[MSG_SIZ], stopBits[MSG_SIZ], flow[MSG_SIZ];
+  ComboData *cd;
+  count = sscanf(arg, "%d%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]%*[, ]%[^, ]",
+    &dataRate, bits, parity, stopBits, flow);
+  if (count != 5) goto cant_parse;
+  dcb->BaudRate = dataRate;
+  cd = cdDataBits;
+  while (cd->label != NULL) {
+    if (StrCaseCmp(cd->label, bits) == 0) {
+      dcb->ByteSize = cd->value;
+      break;
+    }
+    cd++;
+  }
+  if (cd->label == NULL) goto cant_parse;
+  cd = cdParity;
+  while (cd->label != NULL) {
+    if (StrCaseCmp(cd->label, parity) == 0) {
+      dcb->Parity = cd->value;
+      break;
+    }
+    cd++;
+  }
+  if (cd->label == NULL) goto cant_parse;
+  cd = cdStopBits;
+  while (cd->label != NULL) {
+    if (StrCaseCmp(cd->label, stopBits) == 0) {
+      dcb->StopBits = cd->value;
+      break;
+    }
+    cd++;
+  }
+  cd = cdFlow;
+  if (cd->label == NULL) goto cant_parse;
+  while (cd->label != NULL) {
+    if (StrCaseCmp(cd->label, flow) == 0) {
+      switch (cd->value) {
+      case FLOW_NONE:
+       dcb->fOutX = FALSE;
+       dcb->fOutxCtsFlow = FALSE;
+       dcb->fOutxDsrFlow = FALSE;
+       break;
+      case FLOW_CTS:
+       dcb->fOutX = FALSE;
+       dcb->fOutxCtsFlow = TRUE;
+       dcb->fOutxDsrFlow = FALSE;
+       break;
+      case FLOW_DSR:
+       dcb->fOutX = FALSE;
+       dcb->fOutxCtsFlow = FALSE;
+       dcb->fOutxDsrFlow = TRUE;
+       break;
+      case FLOW_XOFF:
+       dcb->fOutX = TRUE;
+       dcb->fOutxCtsFlow = FALSE;
+       dcb->fOutxDsrFlow = FALSE;
+       break;
+      }
+      break;
+    }
+    cd++;
+  }
+  if (cd->label == NULL) goto cant_parse;
+  return;
+cant_parse:
+    ExitArgError("Can't parse com port settings", arg);
+}
+
+
+VOID PrintCommSettings(FILE *f, char *name, DCB *dcb)
+{
+  char *flow = "??", *parity = "??", *stopBits = "??";
+  ComboData *cd;
+  
+  cd = cdParity;
+  while (cd->label != NULL) {
+    if (dcb->Parity == cd->value) {
+      parity = cd->label;
+      break;
+    }
+    cd++;
+  }
+  cd = cdStopBits;
+  while (cd->label != NULL) {
+    if (dcb->StopBits == cd->value) {
+      stopBits = cd->label;
+      break;
+    }
+    cd++;
+  }
+  if (dcb->fOutX) {
+    flow = cdFlow[FLOW_XOFF].label;
+  } else if (dcb->fOutxCtsFlow) {
+    flow = cdFlow[FLOW_CTS].label;
+  } else if (dcb->fOutxDsrFlow) {
+    flow = cdFlow[FLOW_DSR].label;
+  } else {
+    flow = cdFlow[FLOW_NONE].label;
+  }
+  fprintf(f, "/%s=%d,%d,%s,%s,%s\n", name,
+    dcb->BaudRate, dcb->ByteSize, parity, stopBits, flow);
+}
+
+
+void
+InitCombo(HANDLE hwndCombo, ComboData *cd)
+{
+  SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);
+
+  while (cd->label != NULL) {
+    SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) cd->label);
+    cd++;
+  }
+}
+
+void
+SelectComboValue(HANDLE hwndCombo, ComboData *cd, unsigned value)
+{
+  int i;
+
+  i = 0;
+  while (cd->label != NULL) {
+    if (cd->value == value) {
+      SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) i, (LPARAM) 0);
+      return;
+    }
+    cd++;
+    i++;
+  }
+}
+
+LRESULT CALLBACK
+CommPortOptionsDialog(HWND hDlg, UINT message, WPARAM wParam,  LPARAM lParam)
+{
+  char buf[MSG_SIZ];
+  HANDLE hwndCombo;
+  char *p;
+  LRESULT index;
+  unsigned value;
+  int err;
+
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow(hDlg, GW_OWNER));
+    /* Initialize the dialog items */
+    /* !! There should probably be some synchronization
+       in accessing hCommPort and dcb.  Or does modal nature
+       of this dialog box do it for us?
+       */
+    hwndCombo = GetDlgItem(hDlg, OPT_Port);
+    InitCombo(hwndCombo, cdPort);
+    p = strrchr(appData.icsCommPort, '\\');
+    if (p++ == NULL) p = appData.icsCommPort;
+    if ((*p == '\0') ||
+       (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) p) == CB_ERR)) {
+      SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) "None");
+    }
+    EnableWindow(hwndCombo, hCommPort == NULL); /*!! don't allow change for now*/
+
+    hwndCombo = GetDlgItem(hDlg, OPT_DataRate);
+    InitCombo(hwndCombo, cdDataRate);
+    sprintf(buf, "%u", dcb.BaudRate);
+    if (SendMessage(hwndCombo, CB_SELECTSTRING, (WPARAM) -1, (LPARAM) buf) == CB_ERR) {
+      SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) -1, (LPARAM) 0);
+      SendMessage(hwndCombo, WM_SETTEXT, (WPARAM) 0, (LPARAM) buf);
+    }
+
+    hwndCombo = GetDlgItem(hDlg, OPT_Bits);
+    InitCombo(hwndCombo, cdDataBits);
+    SelectComboValue(hwndCombo, cdDataBits, dcb.ByteSize);
+
+    hwndCombo = GetDlgItem(hDlg, OPT_Parity);
+    InitCombo(hwndCombo, cdParity);
+    SelectComboValue(hwndCombo, cdParity, dcb.Parity);
+
+    hwndCombo = GetDlgItem(hDlg, OPT_StopBits);
+    InitCombo(hwndCombo, cdStopBits);
+    SelectComboValue(hwndCombo, cdStopBits, dcb.StopBits);
+
+    hwndCombo = GetDlgItem(hDlg, OPT_Flow);
+    InitCombo(hwndCombo, cdFlow);
+    if (dcb.fOutX) {
+      SelectComboValue(hwndCombo, cdFlow, FLOW_XOFF);
+    } else if (dcb.fOutxCtsFlow) {
+      SelectComboValue(hwndCombo, cdFlow, FLOW_CTS);
+    } else if (dcb.fOutxDsrFlow) {
+      SelectComboValue(hwndCombo, cdFlow, FLOW_DSR);
+    } else {
+      SelectComboValue(hwndCombo, cdFlow, FLOW_NONE);
+    }
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* Read changed options from the dialog box */
+#ifdef NOTDEF
+      /* !! Currently we can't change comm ports in midstream */
+      hwndCombo = GetDlgItem(hDlg, OPT_Port);
+      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
+      if (index == PORT_NONE) {
+       appData.icsCommPort = "";
+       if (hCommPort != NULL) {
+         CloseHandle(hCommPort);
+         hCommPort = NULL;
+       }
+       EndDialog(hDlg, TRUE);
+       return TRUE;
+      }
+      SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);
+      appData.icsCommPort = strdup(buf);
+      if (hCommPort != NULL) {
+       CloseHandle(hCommPort);
+       hCommPort = NULL;
+      }
+      /* now what?? can't really do this; have to fix up the ChildProc
+        and InputSource records for the comm port that we gave to the
+        back end. */
+#endif /*NOTDEF*/
+
+      hwndCombo = GetDlgItem(hDlg, OPT_DataRate);
+      SendMessage(hwndCombo, WM_GETTEXT, (WPARAM) MSG_SIZ, (LPARAM) buf);
+      if (sscanf(buf, "%u", &value) != 1) {
+       MessageBox(hDlg, "Invalid data rate",
+                  "Option Error", MB_OK|MB_ICONEXCLAMATION);
+       return TRUE;
+      }
+      dcb.BaudRate = value;
+
+      hwndCombo = GetDlgItem(hDlg, OPT_Bits);
+      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
+      dcb.ByteSize = cdDataBits[index].value;
+
+      hwndCombo = GetDlgItem(hDlg, OPT_Parity);
+      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
+      dcb.Parity = cdParity[index].value;
+
+      hwndCombo = GetDlgItem(hDlg, OPT_StopBits);
+      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
+      dcb.StopBits = cdStopBits[index].value;
+
+      hwndCombo = GetDlgItem(hDlg, OPT_Flow);
+      index = SendMessage(hwndCombo, CB_GETCURSEL, (WPARAM) 0, (LPARAM) 0);
+      switch (cdFlow[index].value) {
+      case FLOW_NONE:
+       dcb.fOutX = FALSE;
+       dcb.fOutxCtsFlow = FALSE;
+       dcb.fOutxDsrFlow = FALSE;
+       break;
+      case FLOW_CTS:
+       dcb.fOutX = FALSE;
+       dcb.fOutxCtsFlow = TRUE;
+       dcb.fOutxDsrFlow = FALSE;
+       break;
+      case FLOW_DSR:
+       dcb.fOutX = FALSE;
+       dcb.fOutxCtsFlow = FALSE;
+       dcb.fOutxDsrFlow = TRUE;
+       break;
+      case FLOW_XOFF:
+       dcb.fOutX = TRUE;
+       dcb.fOutxCtsFlow = FALSE;
+       dcb.fOutxDsrFlow = FALSE;
+       break;
+      }
+      if (!SetCommState(hCommPort, (LPDCB) &dcb)) {
+       err = GetLastError();
+       switch(MessageBox(hDlg, 
+                        "Failed to set comm port state;\r\ninvalid options?",
+                        "Option Error", MB_ABORTRETRYIGNORE|MB_ICONQUESTION)) {
+       case IDABORT:
+         DisplayFatalError("Failed to set comm port state", err, 1);
+         exit(1);  /*is it ok to do this from here?*/
+
+       case IDRETRY:
+         return TRUE;
+
+       case IDIGNORE:
+         EndDialog(hDlg, TRUE);
+         return TRUE;
+       }
+      }
+
+      EndDialog(hDlg, TRUE);
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    default:
+      break;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+VOID
+CommPortOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc = MakeProcInstance((FARPROC)CommPortOptionsDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_CommPort), hwnd, (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * Load Options dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+
+VOID
+SetLoadOptionEnables(HWND hDlg)
+{
+  UINT state;
+
+  state = IsDlgButtonChecked(hDlg, OPT_Autostep);
+  EnableWindow(GetDlgItem(hDlg, OPT_ASTimeDelay), state);
+  EnableWindow(GetDlgItem(hDlg, OPT_AStext1), state);
+}
+
+LRESULT CALLBACK
+LoadOptions(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  char buf[MSG_SIZ];
+  float fnumber;
+
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+    /* Initialize the dialog items */
+    if (appData.timeDelay >= 0.0) {
+      CheckDlgButton(hDlg, OPT_Autostep, TRUE);
+      sprintf(buf, "%.2g", appData.timeDelay);
+      SetDlgItemText(hDlg, OPT_ASTimeDelay, buf);
+    } else {
+      CheckDlgButton(hDlg, OPT_Autostep, FALSE);
+    }
+    SetLoadOptionEnables(hDlg);
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* Read changed options from the dialog box */
+      if (IsDlgButtonChecked(hDlg, OPT_Autostep)) {
+       GetDlgItemText(hDlg, OPT_ASTimeDelay, buf, MSG_SIZ);
+       if (sscanf(buf, "%f", &fnumber) != 1) {
+         MessageBox(hDlg, "Invalid load game step rate",
+                    "Option Error", MB_OK|MB_ICONEXCLAMATION);
+         return FALSE;
+       }
+       appData.timeDelay = fnumber;
+      } else {
+       appData.timeDelay = (float) -1.0;
+      }
+      EndDialog(hDlg, TRUE);
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    default:
+      SetLoadOptionEnables(hDlg);
+      break;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+
+VOID 
+LoadOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc = MakeProcInstance((FARPROC)LoadOptions, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_LoadOptions), hwnd, (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * Save Options dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+
+VOID
+SetSaveOptionEnables(HWND hDlg)
+{
+  UINT state;
+
+  state = IsDlgButtonChecked(hDlg, OPT_Autosave);
+  EnableWindow(GetDlgItem(hDlg, OPT_AVPrompt), state);
+  EnableWindow(GetDlgItem(hDlg, OPT_AVToFile), state);
+  if (state && !IsDlgButtonChecked(hDlg, OPT_AVPrompt) &&
+      !IsDlgButtonChecked(hDlg, OPT_AVToFile)) {
+    CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);
+  }
+
+  state = state && IsDlgButtonChecked(hDlg, OPT_AVToFile);
+  EnableWindow(GetDlgItem(hDlg, OPT_AVFilename), state);
+  EnableWindow(GetDlgItem(hDlg, OPT_AVBrowse), state);
+}
+
+LRESULT CALLBACK
+SaveOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  char buf[MSG_SIZ];
+  FILE *f;
+
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+    /* Initialize the dialog items */
+    if (*appData.saveGameFile != NULLCHAR) {
+      CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);
+      CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVToFile);
+      SetDlgItemText(hDlg, OPT_AVFilename, appData.saveGameFile);
+    } else if (appData.autoSaveGames) {
+      CheckDlgButton(hDlg, OPT_Autosave, (UINT) TRUE);
+      CheckRadioButton(hDlg, OPT_AVPrompt, OPT_AVToFile, OPT_AVPrompt);
+    } else {
+      CheckDlgButton(hDlg, OPT_Autosave, (UINT) FALSE);
+    }
+    if (appData.oldSaveStyle) {
+      CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_Old);
+    } else {
+      CheckRadioButton(hDlg, OPT_PGN, OPT_Old, OPT_PGN);
+    }
+    CheckDlgButton( hDlg, OPT_OutOfBookInfo, appData.saveOutOfBookInfo );
+    SetSaveOptionEnables(hDlg);
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* Read changed options from the dialog box */
+      if (IsDlgButtonChecked(hDlg, OPT_Autosave)) {
+       appData.autoSaveGames = TRUE;
+       if (IsDlgButtonChecked(hDlg, OPT_AVPrompt)) {
+         appData.saveGameFile = "";
+       } else /*if (IsDlgButtonChecked(hDlg, OPT_AVToFile))*/ {
+         GetDlgItemText(hDlg, OPT_AVFilename, buf, MSG_SIZ);
+         if (*buf == NULLCHAR) {
+           MessageBox(hDlg, "Invalid save game file name",
+                      "Option Error", MB_OK|MB_ICONEXCLAMATION);
+           return FALSE;
+         }
+         if ((isalpha(buf[0]) && buf[1] == ':') ||
+           (buf[0] == '\\' && buf[1] == '\\')) {
+           appData.saveGameFile = strdup(buf);
+         } else {
+           char buf2[MSG_SIZ], buf3[MSG_SIZ];
+           char *dummy;
+           GetCurrentDirectory(MSG_SIZ, buf3);
+           SetCurrentDirectory(installDir);
+           if (GetFullPathName(buf, MSG_SIZ, buf2, &dummy)) {
+             appData.saveGameFile = strdup(buf2);
+           } else {
+             appData.saveGameFile = strdup(buf);
+           }
+           SetCurrentDirectory(buf3);
+         }
+       }
+      } else {
+       appData.autoSaveGames = FALSE;
+       appData.saveGameFile = "";
+      }
+      appData.oldSaveStyle = IsDlgButtonChecked(hDlg, OPT_Old);
+      appData.saveOutOfBookInfo = IsDlgButtonChecked( hDlg, OPT_OutOfBookInfo );
+      EndDialog(hDlg, TRUE);
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    case OPT_AVBrowse:
+      f = OpenFileDialog(hDlg, "a", NULL, 
+                        appData.oldSaveStyle ? "gam" : "pgn", 
+                        GAME_FILT, "Browse for Auto Save File", 
+                        NULL, NULL, buf);
+      if (f != NULL) {
+       fclose(f);
+       SetDlgItemText(hDlg, OPT_AVFilename, buf);
+      }
+      break;
+
+    default:
+      SetSaveOptionEnables(hDlg);
+      break;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+VOID
+SaveOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc = MakeProcInstance((FARPROC)SaveOptionsDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_SaveOptions), hwnd, (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * Time Control Options dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+
+VOID
+SetTimeControlEnables(HWND hDlg)
+{
+  UINT state;
+
+  state = IsDlgButtonChecked(hDlg, OPT_TCUseMoves);
+  EnableWindow(GetDlgItem(hDlg, OPT_TCTime), state);
+  EnableWindow(GetDlgItem(hDlg, OPT_TCMoves), state);
+  EnableWindow(GetDlgItem(hDlg, OPT_TCtext1), state);
+  EnableWindow(GetDlgItem(hDlg, OPT_TCtext2), state);
+  EnableWindow(GetDlgItem(hDlg, OPT_TCTime2), !state);
+  EnableWindow(GetDlgItem(hDlg, OPT_TCInc), !state);
+  EnableWindow(GetDlgItem(hDlg, OPT_TCitext1), !state);
+  EnableWindow(GetDlgItem(hDlg, OPT_TCitext2), !state);
+  EnableWindow(GetDlgItem(hDlg, OPT_TCitext3), !state);
+}
+
+
+LRESULT CALLBACK
+TimeControl(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  char buf[MSG_SIZ];
+  int mps, increment, odds1, odds2;
+  BOOL ok, ok2;
+
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+    /* Initialize the dialog items */
+    if (appData.clockMode && !appData.icsActive) {
+      if (appData.timeIncrement == -1) {
+       CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseInc,
+                        OPT_TCUseMoves);
+       SetDlgItemText(hDlg, OPT_TCTime, appData.timeControl);
+       SetDlgItemInt(hDlg, OPT_TCMoves, appData.movesPerSession,
+                     FALSE);
+       SetDlgItemText(hDlg, OPT_TCTime2, "");
+       SetDlgItemText(hDlg, OPT_TCInc, "");
+      } else {
+       CheckRadioButton(hDlg, OPT_TCUseMoves, OPT_TCUseInc,
+                        OPT_TCUseInc);
+       SetDlgItemText(hDlg, OPT_TCTime, "");
+       SetDlgItemText(hDlg, OPT_TCMoves, "");
+       SetDlgItemText(hDlg, OPT_TCTime2, appData.timeControl);
+       SetDlgItemInt(hDlg, OPT_TCInc, appData.timeIncrement, FALSE);
+      }
+      SetDlgItemInt(hDlg, OPT_TCOdds1, 1, FALSE);
+      SetDlgItemInt(hDlg, OPT_TCOdds2, 1, FALSE);
+      SetTimeControlEnables(hDlg);
+    }
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* Read changed options from the dialog box */
+      if (IsDlgButtonChecked(hDlg, OPT_TCUseMoves)) {
+       increment = -1;
+       mps = GetDlgItemInt(hDlg, OPT_TCMoves, &ok, FALSE);
+       if (!ok || mps <= 0) {
+         MessageBox(hDlg, "Invalid moves per time control",
+                    "Option Error", MB_OK|MB_ICONEXCLAMATION);
+         return FALSE;
+       }
+       GetDlgItemText(hDlg, OPT_TCTime, buf, MSG_SIZ);
+       if (!ParseTimeControl(buf, increment, mps)) {
+         MessageBox(hDlg, "Invalid minutes per time control",
+                    "Option Error", MB_OK|MB_ICONEXCLAMATION);
+         return FALSE;
+       }
+      } else {
+       increment = GetDlgItemInt(hDlg, OPT_TCInc, &ok, FALSE);
+       mps = appData.movesPerSession;
+       if (!ok || increment < 0) {
+         MessageBox(hDlg, "Invalid increment",
+                    "Option Error", MB_OK|MB_ICONEXCLAMATION);
+         return FALSE;
+       }
+       GetDlgItemText(hDlg, OPT_TCTime2, buf, MSG_SIZ);
+       if (!ParseTimeControl(buf, increment, mps)) {
+         MessageBox(hDlg, "Invalid initial time",
+                    "Option Error", MB_OK|MB_ICONEXCLAMATION);
+         return FALSE;
+       }
+      }
+      odds1 = GetDlgItemInt(hDlg, OPT_TCOdds1, &ok, FALSE);
+      odds2 = GetDlgItemInt(hDlg, OPT_TCOdds2, &ok2, FALSE);
+      if (!ok || !ok2 || odds1 <= 0 || odds2 <= 0) {
+         MessageBox(hDlg, "Invalid time-odds factor",
+                    "Option Error", MB_OK|MB_ICONEXCLAMATION);
+         return FALSE;
+      }
+      appData.timeControl = strdup(buf);
+      appData.movesPerSession = mps;
+      appData.timeIncrement = increment;
+      appData.firstTimeOdds  = first.timeOdds  = odds1;
+      appData.secondTimeOdds = second.timeOdds = odds2;
+      Reset(TRUE, TRUE);
+      EndDialog(hDlg, TRUE);
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    default:
+      SetTimeControlEnables(hDlg);
+      break;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+VOID
+TimeControlOptionsPopup(HWND hwnd)
+{
+  if (gameMode != BeginningOfGame) {
+    DisplayError("Changing time control during a game is not implemented", 0);
+  } else {
+    FARPROC lpProc = MakeProcInstance((FARPROC)TimeControl, hInst);
+    DialogBox(hInst, MAKEINTRESOURCE(DLG_TimeControl), hwnd, (DLGPROC) lpProc);
+    FreeProcInstance(lpProc);
+  }
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * Engine Options Dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+#define CHECK_BOX(x,y) CheckDlgButton(hDlg, (x), (BOOL)(y))
+#define IS_CHECKED(x) (Boolean)IsDlgButtonChecked(hDlg, (x))
+
+#define INT_ABS( n )    ((n) >= 0 ? (n) : -(n))
+
+LRESULT CALLBACK EnginePlayOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+    /* Initialize the dialog items */
+    CHECK_BOX(IDC_EpPeriodicUpdates, appData.periodicUpdates);
+    CHECK_BOX(IDC_EpPonder, appData.ponderNextMove);
+    CHECK_BOX(IDC_EpShowThinking, appData.showThinking);
+    CHECK_BOX(IDC_EpHideThinkingHuman, appData.hideThinkingFromHuman);
+
+    CHECK_BOX(IDC_TestClaims, appData.testClaims);
+    CHECK_BOX(IDC_DetectMates, appData.checkMates);
+    CHECK_BOX(IDC_MaterialDraws, appData.materialDraws);
+    CHECK_BOX(IDC_TrivialDraws, appData.trivialDraws);
+
+    CHECK_BOX(IDC_ScoreAbs1, appData.firstScoreIsAbsolute);
+    CHECK_BOX(IDC_ScoreAbs2, appData.secondScoreIsAbsolute);
+
+    SetDlgItemInt( hDlg, IDC_EpDrawMoveCount, appData.adjudicateDrawMoves, TRUE );
+    SendDlgItemMessage( hDlg, IDC_EpDrawMoveCount, EM_SETSEL, 0, -1 );
+
+    SetDlgItemInt( hDlg, IDC_EpAdjudicationThreshold, INT_ABS(appData.adjudicateLossThreshold), TRUE );
+    SendDlgItemMessage( hDlg, IDC_EpAdjudicationThreshold, EM_SETSEL, 0, -1 );
+
+    SetDlgItemInt( hDlg, IDC_RuleMoves, appData.ruleMoves, TRUE );
+    SendDlgItemMessage( hDlg, IDC_RuleMoves, EM_SETSEL, 0, -1 );
+
+    SetDlgItemInt( hDlg, IDC_DrawRepeats, INT_ABS(appData.drawRepeats), TRUE );
+    SendDlgItemMessage( hDlg, IDC_DrawRepeats, EM_SETSEL, 0, -1 );
+
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      /* Read changed options from the dialog box */
+      PeriodicUpdatesEvent(          IS_CHECKED(IDC_EpPeriodicUpdates));
+      PonderNextMoveEvent(           IS_CHECKED(IDC_EpPonder));
+      appData.hideThinkingFromHuman= IS_CHECKED(IDC_EpHideThinkingHuman); // [HGM] thinking: moved up
+#if 0
+      ShowThinkingEvent(             IS_CHECKED(IDC_EpShowThinking));
+#else
+      appData.showThinking   = IS_CHECKED(IDC_EpShowThinking);
+      ShowThinkingEvent(); // [HGM] thinking: tests all options that need thinking output
+#endif
+      appData.testClaims    = IS_CHECKED(IDC_TestClaims);
+      appData.checkMates    = IS_CHECKED(IDC_DetectMates);
+      appData.materialDraws = IS_CHECKED(IDC_MaterialDraws);
+      appData.trivialDraws  = IS_CHECKED(IDC_TrivialDraws);
+
+      appData.adjudicateDrawMoves = GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, NULL, FALSE );
+      appData.adjudicateLossThreshold = - (int) GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, NULL, FALSE );
+      appData.ruleMoves = GetDlgItemInt(hDlg, IDC_RuleMoves, NULL, FALSE );
+      appData.drawRepeats = (int) GetDlgItemInt(hDlg, IDC_DrawRepeats, NULL, FALSE );
+
+      appData.firstScoreIsAbsolute  = IS_CHECKED(IDC_ScoreAbs1);
+      appData.secondScoreIsAbsolute = IS_CHECKED(IDC_ScoreAbs2);
+
+      EndDialog(hDlg, TRUE);
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    case IDC_EpDrawMoveCount:
+    case IDC_EpAdjudicationThreshold:
+    case IDC_DrawRepeats:
+    case IDC_RuleMoves:
+        if( HIWORD(wParam) == EN_CHANGE ) {
+            int n1_ok;
+            int n2_ok;
+            int n3_ok;
+            int n4_ok;
+
+            GetDlgItemInt(hDlg, IDC_EpDrawMoveCount, &n1_ok, FALSE );
+            GetDlgItemInt(hDlg, IDC_EpAdjudicationThreshold, &n2_ok, FALSE );
+            GetDlgItemInt(hDlg, IDC_RuleMoves, &n3_ok, FALSE );
+            GetDlgItemInt(hDlg, IDC_DrawRepeats, &n4_ok, FALSE );
+
+            EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok && n3_ok && n4_ok ? TRUE : FALSE );
+        }
+        return TRUE;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+VOID EnginePlayOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc;
+
+  lpProc = MakeProcInstance((FARPROC)EnginePlayOptionsDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_EnginePlayOptions), hwnd, (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * UCI Options Dialog functions
+ *
+\*---------------------------------------------------------------------------*/
+static BOOL BrowseForFolder( const char * title, char * path )
+{
+    BOOL result = FALSE;
+    BROWSEINFO bi;
+    LPITEMIDLIST pidl;
+
+    ZeroMemory( &bi, sizeof(bi) );
+
+    bi.lpszTitle = title == 0 ? "Choose Folder" : title;
+    bi.ulFlags = BIF_RETURNONLYFSDIRS;
+
+    pidl = SHBrowseForFolder( &bi );
+
+    if( pidl != 0 ) {
+        IMalloc * imalloc = 0;
+
+        if( SHGetPathFromIDList( pidl, path ) ) {
+            result = TRUE;
+        }
+
+        if( SUCCEEDED( SHGetMalloc ( &imalloc ) ) ) {
+            imalloc->lpVtbl->Free(imalloc,pidl);
+            imalloc->lpVtbl->Release(imalloc);
+        }
+    }
+
+    return result;
+}
+
+LRESULT CALLBACK UciOptionsDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+  char buf[MAX_PATH];
+  int oldCores;
+
+  switch (message) {
+  case WM_INITDIALOG: /* message: initialize dialog box */
+
+    /* Center the dialog over the application window */
+    CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));
+
+    /* Initialize the dialog items */
+    SetDlgItemText( hDlg, IDC_PolyglotDir, appData.polyglotDir );
+    SetDlgItemInt( hDlg, IDC_HashSize, appData.defaultHashSize, TRUE );
+    SetDlgItemText( hDlg, IDC_PathToEGTB, appData.defaultPathEGTB );
+    SetDlgItemInt( hDlg, IDC_SizeOfEGTB, appData.defaultCacheSizeEGTB, TRUE );
+    CheckDlgButton( hDlg, IDC_UseBook, (BOOL) appData.usePolyglotBook );
+    SetDlgItemText( hDlg, IDC_BookFile, appData.polyglotBook );
+    // [HGM] smp: input field for nr of cores:
+    SetDlgItemInt( hDlg, IDC_Cores, appData.smpCores, TRUE );
+    // [HGM] book: tick boxes for own book use
+    CheckDlgButton( hDlg, IDC_OwnBook1, (BOOL) appData.firstHasOwnBookUCI );
+    CheckDlgButton( hDlg, IDC_OwnBook2, (BOOL) appData.secondHasOwnBookUCI );
+
+    SendDlgItemMessage( hDlg, IDC_PolyglotDir, EM_SETSEL, 0, -1 );
+
+    return TRUE;
+
+  case WM_COMMAND: /* message: received a command */
+    switch (LOWORD(wParam)) {
+    case IDOK:
+      GetDlgItemText( hDlg, IDC_PolyglotDir, buf, sizeof(buf) );
+      appData.polyglotDir = strdup(buf);
+      appData.defaultHashSize = GetDlgItemInt(hDlg, IDC_HashSize, NULL, FALSE );
+      appData.defaultCacheSizeEGTB = GetDlgItemInt(hDlg, IDC_SizeOfEGTB, NULL, FALSE );
+      GetDlgItemText( hDlg, IDC_PathToEGTB, buf, sizeof(buf) );
+      appData.defaultPathEGTB = strdup(buf);
+      GetDlgItemText( hDlg, IDC_BookFile, buf, sizeof(buf) );
+      appData.polyglotBook = strdup(buf);
+      appData.usePolyglotBook = (Boolean) IsDlgButtonChecked( hDlg, IDC_UseBook );
+      // [HGM] smp: get nr of cores:
+      oldCores = appData.smpCores;
+      appData.smpCores = GetDlgItemInt(hDlg, IDC_Cores, NULL, FALSE );
+      if(appData.smpCores != oldCores) NewSettingEvent(FALSE, "cores", appData.smpCores);
+      // [HGM] book: read tick boxes for own book use
+      appData.firstHasOwnBookUCI  = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook1 );
+      appData.secondHasOwnBookUCI = (Boolean) IsDlgButtonChecked( hDlg, IDC_OwnBook2 );
+
+      if(gameMode == BeginningOfGame) Reset(TRUE, TRUE);
+      EndDialog(hDlg, TRUE);
+      return TRUE;
+
+    case IDCANCEL:
+      EndDialog(hDlg, FALSE);
+      return TRUE;
+
+    case IDC_BrowseForBook:
+      {
+          char filter[] = { 
+              'A','l','l',' ','F','i','l','e','s', 0,
+              '*','.','*', 0,
+              'B','I','N',' ','F','i','l','e','s', 0,
+              '*','.','b','i','n', 0,
+              0 };
+
+          OPENFILENAME ofn;
+
+          strcpy( buf, "" );
+
+          ZeroMemory( &ofn, sizeof(ofn) );
+
+          ofn.lStructSize = sizeof(ofn);
+          ofn.hwndOwner = hDlg;
+          ofn.hInstance = hInst;
+          ofn.lpstrFilter = filter;
+          ofn.lpstrFile = buf;
+          ofn.nMaxFile = sizeof(buf);
+          ofn.lpstrTitle = "Choose Book";
+          ofn.Flags = OFN_FILEMUSTEXIST | OFN_LONGNAMES | OFN_HIDEREADONLY;
+
+          if( GetOpenFileName( &ofn ) ) {
+              SetDlgItemText( hDlg, IDC_BookFile, buf );
+          }
+      }
+      return TRUE;
+
+    case IDC_BrowseForPolyglotDir:
+      if( BrowseForFolder( "Choose Polyglot Directory", buf ) ) {
+        SetDlgItemText( hDlg, IDC_PolyglotDir, buf );
+
+        strcat( buf, "\\polyglot.exe" );
+
+        if( GetFileAttributes(buf) == 0xFFFFFFFF ) {
+            MessageBox( hDlg, "Polyglot was not found in the specified folder!", "Warning", MB_OK | MB_ICONWARNING );
+        }
+      }
+      return TRUE;
+
+    case IDC_BrowseForEGTB:
+      if( BrowseForFolder( "Choose EGTB Directory:", buf ) ) {
+        SetDlgItemText( hDlg, IDC_PathToEGTB, buf );
+      }
+      return TRUE;
+
+    case IDC_HashSize:
+    case IDC_SizeOfEGTB:
+        if( HIWORD(wParam) == EN_CHANGE ) {
+            int n1_ok;
+            int n2_ok;
+
+            GetDlgItemInt(hDlg, IDC_HashSize, &n1_ok, FALSE );
+            GetDlgItemInt(hDlg, IDC_SizeOfEGTB, &n2_ok, FALSE );
+
+            EnableWindow( GetDlgItem(hDlg, IDOK), n1_ok && n2_ok ? TRUE : FALSE );
+        }
+        return TRUE;
+    }
+    break;
+  }
+  return FALSE;
+}
+
+VOID UciOptionsPopup(HWND hwnd)
+{
+  FARPROC lpProc;
+
+  lpProc = MakeProcInstance((FARPROC)UciOptionsDialog, hInst);
+  DialogBox(hInst, MAKEINTRESOURCE(DLG_OptionsUCI), hwnd, (DLGPROC) lpProc);
+  FreeProcInstance(lpProc);
+}
index 54718f3..54c457e 100644 (file)
--- a/xboard.c
+++ b/xboard.c
@@ -423,11 +423,14 @@ void EngineMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));
 void UciMenuProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
 void TimeControlProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
 void NewVariantProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
+void FirstSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
+void SecondSettingsProc P((Widget w, XEvent *event, String *prms, Cardinal *nprms));\r
 void ShufflePopDown P(());\r
 void EnginePopDown P(());\r
 void UciPopDown P(());\r
 void TimeControlPopDown P(());\r
 void NewVariantPopDown P(());\r
+void SettingsPopDown P(());\r
 /*\r
 * XBoard depends on Xt R4 or higher\r
 */\r
@@ -606,7 +609,9 @@ MenuItem optionsMenu[] = {
     {"Flip View", FlipViewProc},\r
     {"----", NothingProc},    \r
     {"Adjudications ...", EngineMenuProc},    \r
-    {"Engine Settings ...", UciMenuProc},    \r
+    {"General Settings ...", UciMenuProc},    \r
+    {"Engine #1 Settings ...", FirstSettingsProc},    \r
+    {"Engine #2 Settings ...", SecondSettingsProc},    \r
     {"Time Control ...", TimeControlProc},    \r
     {"----", NothingProc},    \r
     {"Always Queen", AlwaysQueenProc},\r
@@ -1287,6 +1292,9 @@ XtResource clientResources[] = {
     { "smpCores", "smpCores", XtRInt,\r
        sizeof(int), XtOffset(AppDataPtr, smpCores),\r
        XtRImmediate, (XtPointer) 1},\r
+    { "niceEngines", "niceEngines", XtRInt,\r
+       sizeof(int), XtOffset(AppDataPtr, niceEngines),\r
+       XtRImmediate, (XtPointer) 0},\r
 
     // [HGM] Winboard_x UCI options\r
     { "firstIsUCI", "firstIsUCI", XtRBoolean,\r
@@ -1319,6 +1327,12 @@ XtResource clientResources[] = {
     { "defaultPathEGTB", "defaultPathEGTB", XtRString,\r
        sizeof(String), XtOffset(AppDataPtr, defaultPathEGTB),\r
        XtRImmediate, (XtPointer) "/usr/local/share/egtb"},\r
+    { "delayBeforeQuit", "delayBeforeQuit", XtRInt,\r
+       sizeof(int), XtOffset(AppDataPtr, delayBeforeQuit),\r
+       XtRImmediate, (XtPointer) 0},\r
+    { "delayAfterQuit", "delayAfterQuit", XtRInt,\r
+       sizeof(int), XtOffset(AppDataPtr, delayAfterQuit),\r
+       XtRImmediate, (XtPointer) 0},\r
 };\r
 \r
 XrmOptionDescRec shellOptions[] = {\r
@@ -1668,6 +1682,9 @@ XrmOptionDescRec shellOptions[] = {
     { "-smpCores", "smpCores", XrmoptionSepArg, NULL }, \r
     { "-sameColorGames", "sameColorGames", XrmoptionSepArg, NULL }, \r
     { "-rewindIndex", "rewindIndex", XrmoptionSepArg, NULL }, \r
+    { "-niceEngines", "niceEngines", XrmoptionSepArg, NULL }, \r
+    { "-delayBeforeQuit", "delayBeforeQuit", XrmoptionSepArg, NULL }, \r
+    { "-delayAfterQuit", "delayAfterQuit", XrmoptionSepArg, NULL }, \r
 };\r
 \r
 \r
@@ -1791,6 +1808,7 @@ XtActionsRec boardActions[] = {
     { "UciPopDown", (XtActionProc) UciPopDown },\r
     { "TimeControlPopDown", (XtActionProc) TimeControlPopDown },\r
     { "NewVariantPopDown", (XtActionProc) NewVariantPopDown },\r
+    { "SettingsPopDown", (XtActionProc) SettingsPopDown },\r
 };\r
      \r
 char globalTranslations[] =\r
@@ -7997,7 +8015,9 @@ int StartChildProcess(cmdLine, dir, pr)
        if (dir[0] != NULLCHAR && chdir(dir) != 0) {\r
            perror(dir);\r
            exit(1);\r
-       }\r
+       }
+
+       nice(appData.niceEngines); // [HGM] nice: adjust priority of engine proc\r
 \r
         execvp(argv[0], argv);\r
        \r
@@ -8019,22 +8039,37 @@ int StartChildProcess(cmdLine, dir, pr)
     return 0;\r
 }\r
 \r
+// [HGM] kill: implement the 'hard killing' of AS's Winboard_x\r
+static RETSIGTYPE AlarmCallBack(int n)\r
+{\r
+    return;\r
+}\r
+\r
 void\r
-DestroyChildProcess(pr, signal)\r
+DestroyChildProcess(pr, signalType)\r
      ProcRef pr;\r
-     int signal;\r
+     int signalType;\r
 {\r
     ChildProc *cp = (ChildProc *) pr;\r
 \r
     if (cp->kind != CPReal) return;\r
     cp->kind = CPNone;\r
-    if (signal) {\r
-      kill(cp->pid, SIGTERM);\r
+    if (signalType == 10) { // [HGM] kill: if it does not terminate in 3 sec, kill\r
+       signal(SIGALRM, AlarmCallBack);\r
+       alarm(3);\r
+       if(wait((int *) 0) == -1) { // process does not terminate on its own accord\r
+           kill(cp->pid, SIGKILL); // kill it forcefully\r
+           wait((int *) 0);        // and wait again\r
+       }\r
+    } else {\r
+       if (signalType) {\r
+           kill(cp->pid, signalType == 9 ? SIGKILL : SIGTERM); // [HGM] kill: use hard kill if so requested\r
+       }\r
+       /* Process is exiting either because of the kill or because of\r
+          a quit command sent by the backend; either way, wait for it to die.\r
+       */\r
+       wait((int *) 0);\r
     }\r
-    /* Process is exiting either because of the kill or because of\r
-       a quit command sent by the backend; either way, wait for it to die.\r
-    */\r
-    wait((int *) 0);\r
     close(cp->fdFrom);\r
     close(cp->fdTo);\r
 }\r
index 72b6e26..a7d595d 100644 (file)
@@ -124,7 +124,8 @@ static void SetEngineColorIcon( int which );
 #define SHOW_PONDERING\r
 \r
 /* Imports from backend.c */\r
-char * SavePart(char *str);\r
+char * SavePart(char *str);
+extern int opponentKibitzes;\r
 \r
 /* Imports from winboard.c */\r
 //extern HWND engineOutputDialog;\r
@@ -172,7 +173,7 @@ typedef struct {
     int an_move_count;\r
 } EngineOutputData;\r
 \r
-static VerifyDisplayMode();\r
+static int VerifyDisplayMode();\r
 static void UpdateControls( EngineOutputData * ed );\r
 static SetEngineState( int which, int state, char * state_data );\r
 
@@ -844,6 +845,7 @@ void EngineOutputPopDown()
     int j;\r
 \r
     if (!engineOutputDialogUp) return;\r
+    DoClearMemo(1);
     j = 0;\r
     XtSetArg(args[j], XtNx, &engineOutputX); j++;\r
     XtSetArg(args[j], XtNy, &engineOutputY); j++;\r
@@ -930,6 +932,8 @@ void EngineOutputUpdate( FrontEndProgramStats * stats )
         return;\r
     }\r
 \r
+    if(gameMode == IcsObserving) return; // [HGM] kibitz: shut up engine if we are observing an ICS game
+
     which = stats->which;\r
     depth = stats->depth;\r
 \r
@@ -1068,7 +1072,7 @@ static void SetDisplayMode( int mode )
 }\r
 \r
 // pure back end\r
-static VerifyDisplayMode()\r
+int VerifyDisplayMode()\r
 {\r
     int mode;\r
 \r
@@ -1078,9 +1082,11 @@ static VerifyDisplayMode()
     case AnalyzeFile:\r
     case MachinePlaysWhite:\r
     case MachinePlaysBlack:\r
+        mode = 0;\r
+        break;\r
     case IcsPlayingWhite:\r
     case IcsPlayingBlack:\r
-        mode = 0;\r
+        mode = appData.zippyPlay && opponentKibitzes; // [HGM] kibitz\r
         break;\r
     case TwoMachinesPlay:\r
         mode = 1;\r
@@ -1263,4 +1269,25 @@ EngineOutputProc(w, event, prms, nprms)
   }
 //  ToNrEvent(currentMove);
 }
-\r
+
+// [HGM] kibitz: write kibitz line; split window for it if necessary
+void OutputKibitz(int window, char *text)
+{
+       if(!EngineOutputIsUp()) return;
+       if(!opponentKibitzes) { // on first kibitz of game, clear memos
+           DoClearMemo(1);
+           if(gameMode == IcsObserving) DoClearMemo(0);
+       }
+       opponentKibitzes = TRUE; // this causes split window DisplayMode in ICS modes.
+       VerifyDisplayMode();
+       if(gameMode == IcsObserving) {
+           DoSetWindowText(0, nLabel, gameInfo.white);
+           SetIcon( 0, nColorIcon,  nColorWhite);
+           SetIcon( 0, nStateIcon,  nClear);
+       }
+       DoSetWindowText(1, nLabel, gameMode == IcsPlayingBlack ? gameInfo.white : gameInfo.black); // opponent name
+       SetIcon( 1, nColorIcon,  gameMode == IcsPlayingBlack ? nColorWhite : nColorBlack);
+       SetIcon( 1, nStateIcon,  nClear);
+       InsertIntoMemo(window-1, text);
+}
+
index 1165a09..5e4fac8 100644 (file)
-/*\r
- * xoptions.c -- Move list window, part of X front end for XBoard\r
- *\r
- * Copyright 2000 Free Software Foundation, Inc.\r
- *\r
- * The following terms apply to the enhanced version of XBoard distributed\r
- * by the Free Software Foundation:\r
- * ------------------------------------------------------------------------\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License\r
- * along with this program; if not, write to the Free Software\r
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
- * ------------------------------------------------------------------------\r
- *\r
- * See the file ChangeLog for a revision history.\r
- */\r
-\r
-// [HGM] this file is the counterpart of woptions.c, containing xboard popup menus\r
-// similar to those of WinBoard, to set the most common options interactively.\r
-\r
-#include "config.h"\r
-\r
-#include <stdio.h>\r
-#include <ctype.h>\r
-#include <errno.h>\r
-#include <sys/types.h>\r
-\r
-#if STDC_HEADERS\r
-# include <stdlib.h>\r
-# include <string.h>\r
-#else /* not STDC_HEADERS */\r
-extern char *getenv();\r
-# if HAVE_STRING_H\r
-#  include <string.h>\r
-# else /* not HAVE_STRING_H */\r
-#  include <strings.h>\r
-# endif /* not HAVE_STRING_H */\r
-#endif /* not STDC_HEADERS */\r
-\r
-#if HAVE_UNISTD_H\r
-# include <unistd.h>\r
-#endif\r
-\r
-#include <X11/Intrinsic.h>\r
-#include <X11/StringDefs.h>\r
-#include <X11/Shell.h>\r
-#include <X11/Xaw/Dialog.h>\r
-#include <X11/Xaw/Form.h>\r
-#include <X11/Xaw/List.h>\r
-#include <X11/Xaw/Label.h>\r
-#include <X11/Xaw/SimpleMenu.h>\r
-#include <X11/Xaw/SmeBSB.h>\r
-#include <X11/Xaw/SmeLine.h>\r
-#include <X11/Xaw/Box.h>\r
-#include <X11/Xaw/Paned.h>\r
-#include <X11/Xaw/MenuButton.h>\r
-#include <X11/cursorfont.h>\r
-#include <X11/Xaw/Text.h>\r
-#include <X11/Xaw/AsciiText.h>\r
-#include <X11/Xaw/Viewport.h>\r
-#include <X11/Xaw/Toggle.h>\r
-\r
-#include "common.h"\r
-#include "backend.h"\r
-#include "xboard.h"\r
-\r
-extern Widget formWidget, shellWidget, boardWidget, menuBarWidget;\r
-extern Display *xDisplay;\r
-extern int squareSize;\r
-extern Pixmap xMarkPixmap;\r
-extern char *layoutName;\r
-extern Window xBoardWindow;\r
-extern Arg layoutArgs[2], formArgs[2];\r
-Pixel timerForegroundPixel, timerBackgroundPixel;\r
-\r
-// [HGM] the following code for makng menu popups was cloned from the FileNamePopUp routines\r
-\r
-static Widget previous = NULL;\r
-\r
-void SetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b)\r
-{\r
-    Arg args;\r
-\r
-    if(previous) {\r
-       XtSetArg(args, XtNdisplayCaret, False);\r
-       XtSetValues(previous, &args, 1);\r
-    }\r
-    XtSetArg(args, XtNdisplayCaret, True);\r
-    XtSetValues(w, &args, 1);\r
-    XtSetKeyboardFocus((Widget) data, w);\r
-    previous = w;\r
-}\r
-\r
-//--------------------------- New Shuffle Game --------------------------------------------\r
-extern int shuffleOpenings;\r
-extern int startedFromPositionFile;\r
-int shuffleUp;\r
-Widget shuffleShell;\r
-\r
-void ShufflePopDown()\r
-{\r
-    if (!shuffleUp) return;\r
-    XtPopdown(shuffleShell);\r
-    XtDestroyWidget(shuffleShell);\r
-    shuffleUp = False;\r
-    ModeHighlight();\r
-}\r
-\r
-void ShuffleCallback(w, client_data, call_data)\r
-     Widget w;\r
-     XtPointer client_data, call_data;\r
-{\r
-    String name;\r
-    Widget w2;\r
-    Arg args[16];\r
-    char buf[80];\r
-    \r
-    XtSetArg(args[0], XtNlabel, &name);\r
-    XtGetValues(w, args, 1);\r
-    \r
-    if (strcmp(name, "cancel") == 0) {\r
-        ShufflePopDown();\r
-        return;\r
-    }\r
-    if (strcmp(name, "off") == 0) {\r
-        ShufflePopDown();\r
-       shuffleOpenings = False; // [HGM] should be moved to New Variant menu, once we have it!\r
-       ResetGameEvent();\r
-       AnalysisPopDown();\r
-        return;\r
-    }\r
-    if (strcmp(name, "random") == 0) {\r
-       sprintf(buf, "%d", rand());\r
-       XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value\r
-       XtSetValues(XtParent(w), args, 1);\r
-        return;\r
-    }\r
-    if (strcmp(name, "ok") == 0) {\r
-       int nr; String name;\r
-        name = XawDialogGetValueString(w2 = XtParent(w));\r
-       if(sscanf(name ,"%d",&nr) != 1) {\r
-           sprintf(buf, "%d", appData.defaultFrcPosition);\r
-           XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value\r
-           XtSetValues(w2, args, 1);\r
-           return;\r
-       }\r
-       appData.defaultFrcPosition = nr;\r
-       shuffleOpenings = True;\r
-        ShufflePopDown();\r
-       ResetGameEvent();\r
-       AnalysisPopDown();\r
-        return;\r
-    }\r
-}\r
-\r
-void ShufflePopUp()\r
-{\r
-    Arg args[16];\r
-    Widget popup, layout, dialog, edit;\r
-    Window root, child;\r
-    int x, y, i;\r
-    int win_x, win_y;\r
-    unsigned int mask;\r
-    char def[80];\r
-    \r
-    i = 0;\r
-    XtSetArg(args[i], XtNresizable, True); i++;\r
-    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
-    shuffleShell = popup =\r
-      XtCreatePopupShell("New Shuffle Game", transientShellWidgetClass,\r
-                        shellWidget, args, i);\r
-    \r
-    layout =\r
-      XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
-                           layoutArgs, XtNumber(layoutArgs));\r
-  \r
-    sprintf(def, "%d\n", appData.defaultFrcPosition);\r
-    i = 0;\r
-    XtSetArg(args[i], XtNlabel, "Start-position number:"); i++;\r
-    XtSetArg(args[i], XtNvalue, def); i++;\r
-    XtSetArg(args[i], XtNborderWidth, 0); i++;\r
-    dialog = XtCreateManagedWidget("Shuffle", dialogWidgetClass,\r
-                                  layout, args, i);\r
-    \r
-//    XtSetArg(args[0], XtNeditType, XawtextEdit);  // [HGM] can't get edit to work decently\r
-//    XtSetArg(args[1], XtNuseStringInPlace, False);\r
-//    XtSetValues(dialog, args, 2);\r
-\r
-    XawDialogAddButton(dialog, "ok", ShuffleCallback, (XtPointer) dialog);\r
-    XawDialogAddButton(dialog, "cancel", ShuffleCallback, (XtPointer) dialog);\r
-    XawDialogAddButton(dialog, "random", ShuffleCallback, (XtPointer) dialog);\r
-    XawDialogAddButton(dialog, "off", ShuffleCallback, (XtPointer) dialog);\r
-    \r
-    XtRealizeWidget(popup);\r
-    CatchDeleteWindow(popup, "ShufflePopDown");\r
-    \r
-    XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
-                 &x, &y, &win_x, &win_y, &mask);\r
-    \r
-    XtSetArg(args[0], XtNx, x - 10);\r
-    XtSetArg(args[1], XtNy, y - 30);\r
-    XtSetValues(popup, args, 2);\r
-    \r
-    XtPopup(popup, XtGrabExclusive);\r
-    shuffleUp = True;\r
-    \r
-    edit = XtNameToWidget(dialog, "*value");\r
-\r
-    XtSetKeyboardFocus(popup, edit);\r
-}\r
-\r
-void ShuffleMenuProc(w, event, prms, nprms)\r
-     Widget w;\r
-     XEvent *event;\r
-     String *prms;\r
-     Cardinal *nprms;\r
-{\r
-//    if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {\r
-//     Reset(FALSE, TRUE);\r
-//    }\r
-    ShufflePopUp();\r
-}\r
-\r
-//--------------------------- Time-Control Menu Popup ----------------------------------\r
-int TimeControlUp;\r
-Widget TimeControlShell;\r
-int tcInc;\r
-Widget tcMess1, tcMess2, tcData, tcTime, tcOdds1, tcOdds2;\r
-int tcIncrement, tcMoves;\r
-\r
-void TimeControlPopDown()\r
-{\r
-    if (!TimeControlUp) return;\r
-    XtPopdown(TimeControlShell);\r
-    XtDestroyWidget(TimeControlShell);\r
-    TimeControlUp = False;\r
-    ModeHighlight();\r
-}\r
-\r
-void TimeControlCallback(w, client_data, call_data)\r
+/*
+ * xoptions.c -- Move list window, part of X front end for XBoard
+ *
+ * Copyright 2000 Free Software Foundation, Inc.
+ *
+ * The following terms apply to the enhanced version of XBoard distributed
+ * by the Free Software Foundation:
+ * ------------------------------------------------------------------------
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * ------------------------------------------------------------------------
+ *
+ * See the file ChangeLog for a revision history.
+ */
+
+// [HGM] this file is the counterpart of woptions.c, containing xboard popup menus
+// similar to those of WinBoard, to set the most common options interactively.
+
+#include "config.h"
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/types.h>
+
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <string.h>
+#else /* not STDC_HEADERS */
+extern char *getenv();
+# if HAVE_STRING_H
+#  include <string.h>
+# else /* not HAVE_STRING_H */
+#  include <strings.h>
+# endif /* not HAVE_STRING_H */
+#endif /* not STDC_HEADERS */
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include <X11/Intrinsic.h>
+#include <X11/StringDefs.h>
+#include <X11/Shell.h>
+#include <X11/Xaw/Dialog.h>
+#include <X11/Xaw/Form.h>
+#include <X11/Xaw/List.h>
+#include <X11/Xaw/Label.h>
+#include <X11/Xaw/SimpleMenu.h>
+#include <X11/Xaw/SmeBSB.h>
+#include <X11/Xaw/SmeLine.h>
+#include <X11/Xaw/Box.h>
+#include <X11/Xaw/Paned.h>
+#include <X11/Xaw/MenuButton.h>
+#include <X11/cursorfont.h>
+#include <X11/Xaw/Text.h>
+#include <X11/Xaw/AsciiText.h>
+#include <X11/Xaw/Viewport.h>
+#include <X11/Xaw/Toggle.h>
+
+#include "common.h"
+#include "backend.h"
+#include "xboard.h"
+
+extern Widget formWidget, shellWidget, boardWidget, menuBarWidget;
+extern Display *xDisplay;
+extern int squareSize;
+extern Pixmap xMarkPixmap;
+extern char *layoutName;
+extern Window xBoardWindow;
+extern Arg layoutArgs[2], formArgs[2];
+Pixel timerForegroundPixel, timerBackgroundPixel;
+
+// [HGM] the following code for makng menu popups was cloned from the FileNamePopUp routines
+
+static Widget previous = NULL;
+
+void SetFocus(Widget w, XtPointer data, XEvent *event, Boolean *b)
+{
+    Arg args;
+
+    if(previous) {
+       XtSetArg(args, XtNdisplayCaret, False);
+       XtSetValues(previous, &args, 1);
+    }
+    XtSetArg(args, XtNdisplayCaret, True);
+    XtSetValues(w, &args, 1);
+    XtSetKeyboardFocus((Widget) data, w);
+    previous = w;
+}
+
+//--------------------------- New Shuffle Game --------------------------------------------
+extern int shuffleOpenings;
+extern int startedFromPositionFile;
+int shuffleUp;
+Widget shuffleShell;
+
+void ShufflePopDown()
+{
+    if (!shuffleUp) return;
+    XtPopdown(shuffleShell);
+    XtDestroyWidget(shuffleShell);
+    shuffleUp = False;
+    ModeHighlight();
+}
+
+void ShuffleCallback(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data, call_data;
+{
+    String name;
+    Widget w2;
+    Arg args[16];
+    char buf[80];
+    
+    XtSetArg(args[0], XtNlabel, &name);
+    XtGetValues(w, args, 1);
+    
+    if (strcmp(name, "cancel") == 0) {
+        ShufflePopDown();
+        return;
+    }
+    if (strcmp(name, "off") == 0) {
+        ShufflePopDown();
+       shuffleOpenings = False; // [HGM] should be moved to New Variant menu, once we have it!
+       ResetGameEvent();
+       AnalysisPopDown();
+        return;
+    }
+    if (strcmp(name, "random") == 0) {
+       sprintf(buf, "%d", rand());
+       XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value
+       XtSetValues(XtParent(w), args, 1);
+        return;
+    }
+    if (strcmp(name, "ok") == 0) {
+       int nr; String name;
+        name = XawDialogGetValueString(w2 = XtParent(w));
+       if(sscanf(name ,"%d",&nr) != 1) {
+           sprintf(buf, "%d", appData.defaultFrcPosition);
+           XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value
+           XtSetValues(w2, args, 1);
+           return;
+       }
+       appData.defaultFrcPosition = nr;
+       shuffleOpenings = True;
+        ShufflePopDown();
+       ResetGameEvent();
+       AnalysisPopDown();
+        return;
+    }
+}
+
+void ShufflePopUp()
+{
+    Arg args[16];
+    Widget popup, layout, dialog, edit;
+    Window root, child;
+    int x, y, i;
+    int win_x, win_y;
+    unsigned int mask;
+    char def[80];
+    
+    i = 0;
+    XtSetArg(args[i], XtNresizable, True); i++;
+    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
+    shuffleShell = popup =
+      XtCreatePopupShell("New Shuffle Game", transientShellWidgetClass,
+                        shellWidget, args, i);
+    
+    layout =
+      XtCreateManagedWidget(layoutName, formWidgetClass, popup,
+                           layoutArgs, XtNumber(layoutArgs));
+  
+    sprintf(def, "%d\n", appData.defaultFrcPosition);
+    i = 0;
+    XtSetArg(args[i], XtNlabel, "Start-position number:"); i++;
+    XtSetArg(args[i], XtNvalue, def); i++;
+    XtSetArg(args[i], XtNborderWidth, 0); i++;
+    dialog = XtCreateManagedWidget("Shuffle", dialogWidgetClass,
+                                  layout, args, i);
+    
+//    XtSetArg(args[0], XtNeditType, XawtextEdit);  // [HGM] can't get edit to work decently
+//    XtSetArg(args[1], XtNuseStringInPlace, False);
+//    XtSetValues(dialog, args, 2);
+
+    XawDialogAddButton(dialog, "ok", ShuffleCallback, (XtPointer) dialog);
+    XawDialogAddButton(dialog, "cancel", ShuffleCallback, (XtPointer) dialog);
+    XawDialogAddButton(dialog, "random", ShuffleCallback, (XtPointer) dialog);
+    XawDialogAddButton(dialog, "off", ShuffleCallback, (XtPointer) dialog);
+    
+    XtRealizeWidget(popup);
+    CatchDeleteWindow(popup, "ShufflePopDown");
+    
+    XQueryPointer(xDisplay, xBoardWindow, &root, &child,
+                 &x, &y, &win_x, &win_y, &mask);
+    
+    XtSetArg(args[0], XtNx, x - 10);
+    XtSetArg(args[1], XtNy, y - 30);
+    XtSetValues(popup, args, 2);
+    
+    XtPopup(popup, XtGrabExclusive);
+    shuffleUp = True;
+    
+    edit = XtNameToWidget(dialog, "*value");
+
+    XtSetKeyboardFocus(popup, edit);
+}
+
+void ShuffleMenuProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+//    if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {
+//     Reset(FALSE, TRUE);
+//    }
+    ShufflePopUp();
+}
+
+//--------------------------- Time-Control Menu Popup ----------------------------------
+int TimeControlUp;
+Widget TimeControlShell;
+int tcInc;
+Widget tcMess1, tcMess2, tcData, tcTime, tcOdds1, tcOdds2;
+int tcIncrement, tcMoves;
+
+void TimeControlPopDown()
+{
+    if (!TimeControlUp) return;
+    XtPopdown(TimeControlShell);
+    XtDestroyWidget(TimeControlShell);
+    TimeControlUp = False;
+    ModeHighlight();
+}
+
+void TimeControlCallback(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data, call_data;
+{
+    String name, txt;
+    Widget w2;
+    Arg args[16];
+    char buf[80];
+    int j;
+
+    XtSetArg(args[0], XtNlabel, &name);
+    XtGetValues(w, args, 1);
+    
+    if (strcmp(name, "classical") == 0) {
+       if(!tcInc) return;
+       j=0;
+       XtSetArg(args[j], XtNlabel, "minutes for each"); j++;
+       XtSetValues(tcMess1, args, j);
+       j=0;
+       XtSetArg(args[j], XtNlabel, "moves"); j++;
+       XtSetValues(tcMess2, args, j);
+       j=0;
+       XtSetArg(args[j], XtNstring, &name); j++;
+       XtGetValues(tcData, args, j);
+       tcIncrement = 0; sscanf(name, "%d", &tcIncrement);
+       sprintf(buf, "%d", tcMoves);
+       j=0;
+       XtSetArg(args[j], XtNstring, buf); j++;
+       XtSetValues(tcData, args, j);
+       tcInc = False;
+        return;
+    }
+    if (strcmp(name, "incremental") == 0) {
+       if(tcInc) return;
+       j=0;
+       XtSetArg(args[j], XtNlabel, "minutes, plus"); j++;
+       XtSetValues(tcMess1, args, j);
+       j=0;
+       XtSetArg(args[j], XtNlabel, "sec/move"); j++;
+       XtSetValues(tcMess2, args, j);
+       j=0;
+       XtSetArg(args[j], XtNstring, &name); j++;
+       XtGetValues(tcData, args, j);
+       tcMoves = appData.movesPerSession; sscanf(name, "%d", &tcMoves);
+       sprintf(buf, "%d", tcIncrement);
+       j=0;
+       XtSetArg(args[j], XtNstring, buf); j++;
+       XtSetValues(tcData, args, j);
+       tcInc = True;
+        return;
+    }
+    if (strcmp(name, " OK ") == 0) {
+       int inc, mps, tc, ok;
+       XtSetArg(args[0], XtNstring, &txt);
+       XtGetValues(tcData, args, 1);
+       if(tcInc) {
+           ok = sscanf(txt, "%d", &inc); mps = 0;
+           if(!ok && txt[0] == 0) { inc = 0; ok = 1; } // accept empty string as zero
+           ok &= (inc >= 0);
+       } else {
+           ok = sscanf(txt, "%d", &mps); inc = -1;
+           ok &= (mps > 0);
+       }
+       if(ok != 1) {
+           XtSetArg(args[0], XtNstring, ""); // erase any offending input
+           XtSetValues(tcData, args, 1);
+           return;
+       }
+       XtSetArg(args[0], XtNstring, &txt);
+       XtGetValues(tcTime, args, 1);
+       if(!ParseTimeControl(txt, inc, mps)) {
+           XtSetArg(args[0], XtNstring, ""); // erase any offending input
+           XtSetValues(tcTime, args, 1);
+           DisplayError("Bad Time-Control String", 0);
+           return;
+       }
+       appData.movesPerSession = mps;
+       appData.timeIncrement = inc;
+       appData.timeControl = strdup(txt);
+       XtSetArg(args[0], XtNstring, &txt);
+       XtGetValues(tcOdds1, args, 1);
+       appData.firstTimeOdds = first.timeOdds 
+               = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1;
+       XtGetValues(tcOdds2, args, 1);
+       appData.secondTimeOdds = second.timeOdds 
+               = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1;
+
+       Reset(True, True);
+        TimeControlPopDown();
+        return;
+    }
+}
+
+void TimeControlPopUp()
+{
+    Arg args[16];
+    Widget popup, layout, form, edit, b_ok, b_cancel, b_clas, b_inc, mess;
+    Window root, child;
+    int x, y, i, j;
+    int win_x, win_y;
+    unsigned int mask;
+    char def[80];
+    
+    tcInc = (appData.timeIncrement >= 0);
+    tcMoves = appData.movesPerSession; tcIncrement = appData.timeIncrement;
+    if(!tcInc) tcIncrement = 0;
+    sprintf(def, "%d", tcInc ? tcIncrement : tcMoves);
+
+    i = 0;
+    XtSetArg(args[i], XtNresizable, True); i++;
+//    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
+    TimeControlShell = popup =
+      XtCreatePopupShell("TimeControl Menu", transientShellWidgetClass,
+                        shellWidget, args, i);
+    
+    layout =
+      XtCreateManagedWidget(layoutName, formWidgetClass, popup,
+                           layoutArgs, XtNumber(layoutArgs));
+  
+    form =
+      XtCreateManagedWidget(layoutName, formWidgetClass, layout,
+                           formArgs, XtNumber(formArgs));
+  
+    j = 0;
+//    XtSetArg(args[j], XtNwidth,     (XtArgVal) 300); j++;
+//    XtSetArg(args[j], XtNheight,    (XtArgVal) 85); j++;
+    XtSetValues(popup, args, j);
+
+    j= 0;
+    XtSetArg(args[j], XtNborderWidth, 1); j++;
+    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+    XtSetArg(args[j], XtNstring, appData.timeControl);  j++;
+    XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    XtSetArg(args[j], XtNresizable, True);  j++;
+    XtSetArg(args[j], XtNwidth,  85);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    tcTime = XtCreateManagedWidget("TC", asciiTextWidgetClass, form, args, j);
+    XtAddEventHandler(tcTime, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+
+    j= 0;
+    XtSetArg(args[j], XtNlabel, tcInc ? "   minutes, plus   " : "minutes for each"); j++;
+    XtSetArg(args[j], XtNborderWidth, 0); j++;
+    XtSetArg(args[j], XtNfromHoriz, tcTime); j++;
+    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+  //  XtSetArg(args[j], XtNwidth,  100);  j++;
+  //  XtSetArg(args[j], XtNheight, 20);  j++;
+    tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);
+
+    j= 0;
+    XtSetArg(args[j], XtNborderWidth, 1); j++;
+    XtSetArg(args[j], XtNfromHoriz, tcMess1); j++;
+    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+    XtSetArg(args[j], XtNstring, def);  j++;
+    XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    XtSetArg(args[j], XtNresizable, True);  j++;
+    XtSetArg(args[j], XtNwidth,  40);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    tcData = XtCreateManagedWidget("MPS", asciiTextWidgetClass, form, args, j);
+    XtAddEventHandler(tcData, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+
+    j= 0;
+    XtSetArg(args[j], XtNlabel, tcInc ? "sec/move" : "moves     "); j++;
+    XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
+    XtSetArg(args[j], XtNborderWidth, 0); j++;
+    XtSetArg(args[j], XtNfromHoriz, tcData); j++;
+    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+//    XtSetArg(args[j], XtNwidth,  80);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass,
+                                  form, args, j);
+
+    j= 0;
+    XtSetArg(args[j], XtNborderWidth, 1); j++;
+    XtSetArg(args[j], XtNfromVert, tcTime); j++;
+    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+    XtSetArg(args[j], XtNstring, "1");  j++;
+    XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNresizable, True);  j++;
+    XtSetArg(args[j], XtNwidth,  40);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    tcOdds1 = XtCreateManagedWidget("Odds1", asciiTextWidgetClass, form, args, j);
+    XtAddEventHandler(tcOdds1, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+
+    j= 0;
+    XtSetArg(args[j], XtNborderWidth, 1); j++;
+    XtSetArg(args[j], XtNfromVert, tcTime); j++;
+    XtSetArg(args[j], XtNfromHoriz, tcOdds1); j++;
+    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+    XtSetArg(args[j], XtNstring, "1");  j++;
+    XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNresizable, True);  j++;
+    XtSetArg(args[j], XtNwidth,  40);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    tcOdds2 = XtCreateManagedWidget("Odds2", asciiTextWidgetClass, form, args, j);
+    XtAddEventHandler(tcOdds2, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+
+    j= 0;
+    XtSetArg(args[j], XtNlabel, "Engine #1 and #2 Time-Odds Factors"); j++;
+    XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
+    XtSetArg(args[j], XtNborderWidth, 0); j++;
+    XtSetArg(args[j], XtNfromVert, tcTime); j++;
+    XtSetArg(args[j], XtNfromHoriz, tcOdds2); j++;
+    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+//    XtSetArg(args[j], XtNwidth,  200);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    mess = XtCreateManagedWidget("Oddstext", labelWidgetClass,
+                                  form, args, j);
+    j=0;
+    XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    b_clas= XtCreateManagedWidget("classical", commandWidgetClass,
+                                  form, args, j);   
+    XtAddCallback(b_clas, XtNcallback, TimeControlCallback, (XtPointer) 0);
+
+    j=0;
+    XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;
+    XtSetArg(args[j], XtNfromHoriz, b_clas);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    b_inc = XtCreateManagedWidget("incremental", commandWidgetClass,
+                                  form, args, j);   
+    XtAddCallback(b_inc, XtNcallback, TimeControlCallback, (XtPointer) 0);
+
+    j=0;
+    XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;
+    XtSetArg(args[j], XtNfromHoriz, tcData);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    b_ok= XtCreateManagedWidget(" OK ", commandWidgetClass,
+                                  form, args, j);   
+    XtAddCallback(b_ok, XtNcallback, TimeControlCallback, (XtPointer) 0);
+
+    j=0;
+    XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;
+    XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    b_cancel= XtCreateManagedWidget("cancel", commandWidgetClass,
+                                  form, args, j);   
+    XtAddCallback(b_cancel, XtNcallback, TimeControlPopDown, (XtPointer) 0);
+
+    XtRealizeWidget(popup);
+    CatchDeleteWindow(popup, "TimeControlPopDown");
+    
+    XQueryPointer(xDisplay, xBoardWindow, &root, &child,
+                 &x, &y, &win_x, &win_y, &mask);
+    
+    XtSetArg(args[0], XtNx, x - 10);
+    XtSetArg(args[1], XtNy, y - 30);
+    XtSetValues(popup, args, 2);
+    
+    XtPopup(popup, XtGrabExclusive);
+    TimeControlUp = True;
+    
+    previous = NULL;
+    SetFocus(tcTime, popup, (XEvent*) NULL, False);
+//    XtSetKeyboardFocus(popup, tcTime);
+}
+
+void TimeControlProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+   TimeControlPopUp();
+}
+
+//--------------------------- Engine-Options Menu Popup ----------------------------------
+int EngineUp;
+Widget EngineShell;
+extern int adjudicateLossThreshold;
+
+Widget engDrawMoves, engThreshold, engRule, engRepeat;
+
+void EnginePopDown()
+{
+    if (!EngineUp) return;
+    XtPopdown(EngineShell);
+    XtDestroyWidget(EngineShell);
+    EngineUp = False;
+    ModeHighlight();
+}
+
+int ReadToggle(Widget w)
+{
+    Arg args; Boolean res;
+
+    XtSetArg(args, XtNstate, &res);
+    XtGetValues(w, &args, 1);
+
+    return res;
+}
+
+Widget w1, w2, w3, w4, w5, w6, w7, w8;
+
+void EngineCallback(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data, call_data;
+{
+    String name;
+    Widget s2;
+    Arg args[16];
+    char buf[80];
+    int j;
+    
+    XtSetArg(args[0], XtNlabel, &name);
+    XtGetValues(w, args, 1);
+    
+    if (strcmp(name, "OK") == 0) {
+       // read all switches
+       appData.periodicUpdates = ReadToggle(w1);
+//     appData.hideThinkingFromHuman = ReadToggle(w2);
+       appData.firstScoreIsAbsolute  = ReadToggle(w3);
+       appData.secondScoreIsAbsolute = ReadToggle(w4);
+       appData.testClaims    = ReadToggle(w5);
+       appData.checkMates    = ReadToggle(w6);
+       appData.materialDraws = ReadToggle(w7);
+       appData.trivialDraws  = ReadToggle(w8);
+
+       // adjust setting in other menu for duplicates 
+       // (perhaps duplicates should be removed from general Option Menu?)
+//     XtSetArg(args[0], XtNleftBitmap, appData.showThinking ? xMarkPixmap : None);
+//     XtSetValues(XtNameToWidget(menuBarWidget,
+//                                "menuOptions.Show Thinking"), args, 1);
+
+       // read out numeric controls, simply ignore bad formats for now
+       XtSetArg(args[0], XtNstring, &name);
+       XtGetValues(engDrawMoves, args, 1);
+       if(sscanf(name, "%d", &j) == 1) appData.adjudicateDrawMoves = j;
+       XtGetValues(engThreshold, args, 1);
+       if(sscanf(name, "%d", &j) == 1) 
+               adjudicateLossThreshold = appData.adjudicateLossThreshold = -j; // inverted!
+       XtGetValues(engRule, args, 1);
+       if(sscanf(name, "%d", &j) == 1) appData.ruleMoves = j;
+       XtGetValues(engRepeat, args, 1);
+       if(sscanf(name, "%d", &j) == 1) appData.drawRepeats = j;
+
+        EnginePopDown();
+       ShowThinkingEvent(); // [HGM] thinking: score adjudication might need thinking output
+        return;
+    }
+}
+
+void EnginePopUp()
+{
+    Arg args[16];
+    Widget popup, layout, form, edit, b_ok, b_cancel, b_clas, b_inc, s1; 
+    Window root, child;
+    int x, y, i, j, width;
+    int win_x, win_y;
+    unsigned int mask;
+    char def[80];
+    
+    tcInc = (appData.timeIncrement >= 0);
+    tcMoves = appData.movesPerSession; tcIncrement = appData.timeIncrement;
+    if(!tcInc) tcIncrement = 0;
+    sprintf(def, "%d", tcInc ? tcIncrement : tcMoves);
+
+    i = 0;
+    XtSetArg(args[i], XtNresizable, True); i++;
+//    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
+    EngineShell = popup =
+      XtCreatePopupShell("Adjudications", transientShellWidgetClass,
+                        shellWidget, args, i);
+    
+    layout =
+      XtCreateManagedWidget(layoutName, formWidgetClass, popup,
+                           layoutArgs, XtNumber(layoutArgs));
+  
+    form =
+      XtCreateManagedWidget(layoutName, formWidgetClass, layout,
+                           formArgs, XtNumber(formArgs));
+  
+    j = 0;
+//    XtSetArg(args[j], XtNwidth,     (XtArgVal) 250); j++;
+//    XtSetArg(args[j], XtNheight,    (XtArgVal) 400); j++;
+//    XtSetValues(popup, args, j);
+
+    j = 0;
+//    XtSetArg(args[j], XtNwidth,       (XtArgVal) 250); j++;
+//    XtSetArg(args[j], XtNheight,      (XtArgVal) 20); j++;
+    XtSetArg(args[j], XtNleft,        (XtArgVal) XtChainLeft); j++;
+    XtSetArg(args[j], XtNright,       (XtArgVal) XtChainRight); j++;
+    XtSetArg(args[j], XtNstate,       appData.periodicUpdates); j++;
+//    XtSetArg(args[j], XtNjustify,     (XtArgVal) XtJustifyLeft); j++;
+    w1 = XtCreateManagedWidget("Periodic Updates (Analysis Mode)", toggleWidgetClass, form, args, j);
+
+    XtSetArg(args[j], XtNwidth,       (XtArgVal) &width);
+    XtGetValues(w1, &args[j], 1);
+
+//    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w1);
+//    XtSetArg(args[j-3], XtNstate,       appData.hideThinkingFromHuman);
+//    w2 = XtCreateManagedWidget("Hide Thinking from Human", toggleWidgetClass, form, args, j);
+
+    XtSetArg(args[j], XtNwidth,       (XtArgVal) width); j++;
+    XtSetArg(args[j-2], XtNstate,     appData.firstScoreIsAbsolute);
+    XtSetArg(args[j], XtNfromVert,    (XtArgVal) w1); j++;
+    w3 = XtCreateManagedWidget("Engine #1 Score is Absolute", toggleWidgetClass, form, args, j);
+
+    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w3);
+    XtSetArg(args[j-3], XtNstate,       appData.secondScoreIsAbsolute);
+    w4 = XtCreateManagedWidget("Engine #2 Score is Absolute", toggleWidgetClass, form, args, j);
+
+    s1 = XtCreateManagedWidget("\nEngine-Engine Adjudications:", labelWidgetClass, form, args, 3);
+
+    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) s1);
+    XtSetArg(args[j-3], XtNstate,       appData.testClaims);
+    w5 = XtCreateManagedWidget("Verify Engine Result Claims", toggleWidgetClass, form, args, j);
+
+    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w5);
+    XtSetArg(args[j-3], XtNstate,       appData.checkMates);
+    w6 = XtCreateManagedWidget("Detect All Mates", toggleWidgetClass, form, args, j);
+
+    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w6);
+    XtSetArg(args[j-3], XtNstate,       appData.materialDraws);
+    w7 = XtCreateManagedWidget("Draw when Insuff. Mating Material", toggleWidgetClass, form, args, j);
+
+    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w7);
+    XtSetArg(args[j-3], XtNstate,       appData.trivialDraws);
+    w8 = XtCreateManagedWidget("Adjudicate Trivial Draws", toggleWidgetClass, form, args, j);
+
+    XtSetArg(args[0], XtNfromVert,  (XtArgVal) w4);
+    XtSetArg(args[1], XtNborderWidth, (XtArgVal) 0);
+    XtSetValues(s1, args, 2);
+
+    sprintf(def, "%d", appData.adjudicateDrawMoves);
+    j= 0;
+    XtSetArg(args[j], XtNborderWidth, 1); j++;
+    XtSetArg(args[j], XtNfromVert, w8); j++;
+    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+    XtSetArg(args[j], XtNstring, def);  j++;
+    XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNresizable, True);  j++;
+    XtSetArg(args[j], XtNwidth,  60);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    engDrawMoves = XtCreateManagedWidget("Length", asciiTextWidgetClass, form, args, j);
+    XtAddEventHandler(engDrawMoves, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+
+    j= 0;
+    XtSetArg(args[j], XtNlabel, " moves maximum, then draw"); j++;
+    XtSetArg(args[j], XtNjustify,     (XtArgVal) XtJustifyLeft); j++;
+    XtSetArg(args[j], XtNborderWidth, 0); j++;
+    XtSetArg(args[j], XtNfromVert, w8); j++;
+    XtSetArg(args[j], XtNfromHoriz, engDrawMoves); j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+//    XtSetArg(args[j], XtNwidth,  170);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);
+
+    sprintf(def, "%d", -appData.adjudicateLossThreshold); // inverted!
+    j= 0;
+    XtSetArg(args[j], XtNborderWidth, 1); j++;
+    XtSetArg(args[j], XtNfromVert, engDrawMoves); j++;
+    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+    XtSetArg(args[j], XtNstring, def);  j++;
+    XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNresizable, True);  j++;
+    XtSetArg(args[j], XtNwidth,  60);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    engThreshold = XtCreateManagedWidget("Threshold", asciiTextWidgetClass, form, args, j);
+    XtAddEventHandler(engThreshold, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+
+    j= 0;
+    XtSetArg(args[j], XtNlabel, "-centiPawn lead is win"); j++;
+    XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
+    XtSetArg(args[j], XtNborderWidth, 0); j++;
+    XtSetArg(args[j], XtNfromVert, engDrawMoves); j++;
+    XtSetArg(args[j], XtNfromHoriz, engThreshold); j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+//    XtSetArg(args[j], XtNwidth,  150);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass, form, args, j);
+
+    sprintf(def, "%d", appData.ruleMoves);
+    j= 0;
+    XtSetArg(args[j], XtNborderWidth, 1); j++;
+    XtSetArg(args[j], XtNfromVert, engThreshold); j++;
+    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+    XtSetArg(args[j], XtNstring, def);  j++;
+    XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNresizable, True);  j++;
+    XtSetArg(args[j], XtNwidth,  30);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    engRule = XtCreateManagedWidget("Rule", asciiTextWidgetClass, form, args, j);
+    XtAddEventHandler(engRule, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+
+    j= 0;
+    XtSetArg(args[j], XtNlabel, "-move rule applied"); j++;
+    XtSetArg(args[j], XtNjustify,     (XtArgVal) XtJustifyLeft); j++;
+    XtSetArg(args[j], XtNborderWidth, 0); j++;
+    XtSetArg(args[j], XtNfromVert, engThreshold); j++;
+    XtSetArg(args[j], XtNfromHoriz, engRule); j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+//    XtSetArg(args[j], XtNwidth,  130);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);
+
+    sprintf(def, "%d", appData.drawRepeats);
+    j= 0;
+    XtSetArg(args[j], XtNborderWidth, 1); j++;
+    XtSetArg(args[j], XtNfromVert, engRule); j++;
+    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+    XtSetArg(args[j], XtNstring, def);  j++;
+    XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNresizable, True);  j++;
+    XtSetArg(args[j], XtNwidth,  30);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    engRepeat = XtCreateManagedWidget("Repeats", asciiTextWidgetClass, form, args, j);
+    XtAddEventHandler(engRepeat, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+
+    j= 0;
+    XtSetArg(args[j], XtNlabel, "-fold repeat is draw"); j++;
+    XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
+    XtSetArg(args[j], XtNborderWidth, 0); j++;
+    XtSetArg(args[j], XtNfromVert, engRule); j++;
+    XtSetArg(args[j], XtNfromHoriz, engRepeat); j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+//    XtSetArg(args[j], XtNwidth,  130);  j++;
+//    XtSetArg(args[j], XtNheight, 20);  j++;
+    tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass, form, args, j);
+
+    j=0;
+    XtSetArg(args[j], XtNfromVert, engRepeat);  j++;
+    XtSetArg(args[j], XtNfromHoriz, tcMess2);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    b_ok= XtCreateManagedWidget("OK", commandWidgetClass, form, args, j);   
+    XtAddCallback(b_ok, XtNcallback, EngineCallback, (XtPointer) 0);
+
+    j=0;
+    XtSetArg(args[j], XtNfromVert, engRepeat);  j++;
+    XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    b_cancel= XtCreateManagedWidget("cancel", commandWidgetClass,
+                                  form, args, j);   
+    XtAddCallback(b_cancel, XtNcallback, EnginePopDown, (XtPointer) 0);
+
+    XtRealizeWidget(popup);
+    CatchDeleteWindow(popup, "EnginePopDown");
+    
+    XQueryPointer(xDisplay, xBoardWindow, &root, &child,
+                 &x, &y, &win_x, &win_y, &mask);
+    
+    XtSetArg(args[0], XtNx, x - 10);
+    XtSetArg(args[1], XtNy, y - 30);
+    XtSetValues(popup, args, 2);
+    
+    XtPopup(popup, XtGrabExclusive);
+    EngineUp = True;
+    
+    previous = NULL;
+    SetFocus(engThreshold, popup, (XEvent*) NULL, False);
+}
+
+void EngineMenuProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+   EnginePopUp();
+}
+
+//--------------------------- New-Variant Menu PopUp -----------------------------------
+struct NewVarButton {
+  char   *name;
+  char *color;
+  Widget handle;
+  VariantClass variant;
+};
+
+struct NewVarButton buttonDesc[] = {
+    {"normal",            "#FFFFFF", 0, VariantNormal},
+    {"FRC",               "#FFFFFF", 0, VariantFischeRandom},
+    {"wild castle",       "#FFFFFF", 0, VariantWildCastle},
+    {"no castle",         "#FFFFFF", 0, VariantNoCastle},
+    {"knightmate",        "#FFFFFF", 0, VariantKnightmate},
+    {"berolina",          "#FFFFFF", 0, VariantBerolina},
+    {"cylinder",          "#FFFFFF", 0, VariantCylinder},
+    {"shatranj",          "#FFFFFF", 0, VariantShatranj},
+    {"atomic",            "#FFFFFF", 0, VariantAtomic},
+    {"two kings",         "#FFFFFF", 0, VariantTwoKings},
+    {"3-checks",          "#FFFFFF", 0, Variant3Check},
+    {"suicide",           "#FFFFBF", 0, VariantSuicide},
+    {"give-away",         "#FFFFBF", 0, VariantGiveaway},
+    {"losers",            "#FFFFBF", 0, VariantLosers},
+    {"fairy",             "#BFBFBF", 0, VariantFairy},
+    {"Superchess",        "#FFBFBF", 0, VariantSuper},
+    {"crazyhouse",        "#FFBFBF", 0, VariantCrazyhouse},
+    {"bughouse",          "#FFBFBF", 0, VariantBughouse},
+    {"shogi (9x9)",       "#BFFFFF", 0, VariantShogi},
+    {"xiangqi (9x10)",    "#BFFFFF", 0, VariantXiangqi},
+    {"courier (12x8)",    "#BFFFBF", 0, VariantCourier},
+    {"janus (10x8)",      "#BFBFFF", 0, VariantJanus},
+    {"Capablanca (10x8)", "#BFBFFF", 0, VariantCapablanca},
+    {"CRC (10x8)",        "#BFBFFF", 0, VariantCapaRandom},
+#ifdef GOTHIC
+    {"Gothic (10x8)",     "#BFBFFF", 0, VariantGothic},
+#endif
+#ifdef FALCON
+    {"Falcon (10x8)",     "#BFBFFF", 0, VariantFalcon},
+#endif
+    {NULL,                0, 0, (VariantClass) 0}
+};
+
+int NewVariantUp;
+Widget NewVariantShell;
+
+void NewVariantPopDown()
+{
+    if (!NewVariantUp) return;
+    XtPopdown(NewVariantShell);
+    XtDestroyWidget(NewVariantShell);
+    NewVariantUp = False;
+    ModeHighlight();
+}
+
+void NewVariantCallback(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data, call_data;
+{
+    String name;
+    Widget w2;
+    Arg args[16];
+    char buf[80];
+    VariantClass v;
+    
+    XtSetArg(args[0], XtNlabel, &name);
+    XtGetValues(w, args, 1);
+    
+    if (strcmp(name, "  OK  ") == 0) {
+       int nr = (int) XawToggleGetCurrent(buttonDesc[0].handle) - 1;
+       if(nr < 0) return;
+       v = buttonDesc[nr].variant;
+       if(!appData.noChessProgram) { 
+           char *name = VariantName(v), buf[MSG_SIZ];
+           if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {
+               /* [HGM] in protocol 2 we check if variant is suported by engine */
+               sprintf(buf, "Variant %s not supported by %s", name, first.tidy);
+               DisplayError(buf, 0);
+//             NewVariantPopDown();
+               return; /* ignore OK if first engine does not support it */
+           } else
+           if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {
+               sprintf(buf, "Warning: second engine (%s) does not support this!", second.tidy);
+               DisplayError(buf, 0);   /* use of second engine is optional; only warn user */
+           }
+       }
+
+       gameInfo.variant = v;
+       appData.variant = VariantName(v);
+
+       shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */
+       startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */
+       appData.pieceToCharTable = NULL;
+       Reset(True, True);
+        NewVariantPopDown();
+        return;
+    }
+}
+
+void NewVariantPopUp()
+{
+    Arg args[16];
+    Widget popup, layout, dialog, edit, form, last = NULL, b_ok, b_cancel;
+    Window root, child;
+    int x, y, i, j;
+    int win_x, win_y;
+    unsigned int mask;
+    char def[80];
+    XrmValue vFrom, vTo;
+
+    i = 0;
+    XtSetArg(args[i], XtNresizable, True); i++;
+//    XtSetArg(args[i], XtNwidth, 250); i++;
+//    XtSetArg(args[i], XtNheight, 300); i++;
+    NewVariantShell = popup =
+      XtCreatePopupShell("NewVariant Menu", transientShellWidgetClass,
+                        shellWidget, args, i);
+    
+    layout =
+      XtCreateManagedWidget(layoutName, formWidgetClass, popup,
+                           layoutArgs, XtNumber(layoutArgs));
+  
+    form =
+      XtCreateManagedWidget("form", formWidgetClass, layout,
+                           formArgs, XtNumber(formArgs));
+  
+    for(i = 0; buttonDesc[i].name != NULL; i++) {
+       Pixel buttonColor;
+       if (!appData.monoMode) {
+           vFrom.addr = (caddr_t) buttonDesc[i].color;
+           vFrom.size = strlen(buttonDesc[i].color);
+           XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);
+           if (vTo.addr == NULL) {
+               buttonColor = (Pixel) -1;
+           } else {
+               buttonColor = *(Pixel *) vTo.addr;
+           }
+       }
+    
+       j = 0;
+       XtSetArg(args[j], XtNradioGroup, last); j++;
+       XtSetArg(args[j], XtNwidth, 125); j++;
+//     XtSetArg(args[j], XtNheight, 16); j++;
+       XtSetArg(args[j], XtNfromVert, i == 15 ? NULL : last); j++;
+       XtSetArg(args[j], XtNfromHoriz, i < 15 ? NULL : buttonDesc[i-15].handle); j++;
+       XtSetArg(args[j], XtNradioData, i+1); j++;
+       XtSetArg(args[j], XtNbackground, buttonColor); j++;
+       XtSetArg(args[j], XtNstate, gameInfo.variant == buttonDesc[i].variant); j++;
+       buttonDesc[i].handle = last =
+           XtCreateManagedWidget(buttonDesc[i].name, toggleWidgetClass, form, args, j);
+    }
+
+    j=0;
+    XtSetArg(args[j], XtNfromVert, buttonDesc[12].handle);  j++;
+    XtSetArg(args[j], XtNfromHoriz, buttonDesc[12].handle);  j++;
+    XtSetArg(args[j], XtNheight, 35); j++;
+//    XtSetArg(args[j], XtNwidth, 60); j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    b_cancel= XtCreateManagedWidget("CANCEL", commandWidgetClass, form, args, j);   
+    XtAddCallback(b_cancel, XtNcallback, NewVariantPopDown, (XtPointer) 0);
+
+    j=0;
+    XtSetArg(args[j], XtNfromHoriz, b_cancel);  j++;
+    XtSetArg(args[j], XtNfromVert, buttonDesc[12].handle);  j++;
+    XtSetArg(args[j], XtNheight, 35); j++;
+//    XtSetArg(args[j], XtNwidth, 60); j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    b_ok= XtCreateManagedWidget("  OK  ", commandWidgetClass, form, args, j);   
+    XtAddCallback(b_ok, XtNcallback, NewVariantCallback, (XtPointer) 0);
+
+    XtRealizeWidget(popup);
+    CatchDeleteWindow(popup, "NewVariantPopDown");
+    
+    XQueryPointer(xDisplay, xBoardWindow, &root, &child,
+                 &x, &y, &win_x, &win_y, &mask);
+    
+    XtSetArg(args[0], XtNx, x - 10);
+    XtSetArg(args[1], XtNy, y - 30);
+    XtSetValues(popup, args, 2);
+    
+    XtPopup(popup, XtGrabExclusive);
+    NewVariantUp = True;
+}
+
+void NewVariantProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+   NewVariantPopUp();
+}
+
+//--------------------------- UCI Menu Popup ------------------------------------------
+int UciUp;
+Widget UciShell;
+
+struct UciControl {
+  char *name;
+  Widget handle;
+  void *ptr;
+};
+
+struct UciControl controlDesc[] = {
+  {"maximum nr of CPUs:", 0, &appData.smpCores},
+  {"Polyglot Directory:", 0, &appData.polyglotDir},
+  {"Hash Size (MB):",     0, &appData.defaultHashSize},
+  {"EGTB Path:",          0, &appData.defaultPathEGTB},
+  {"EGTB Cache (MB):",    0, &appData.defaultCacheSizeEGTB},
+  {"Polyglot Book:",      0, &appData.polyglotBook},
+  {NULL, 0, NULL},
+};
+
+void UciPopDown()
+{
+    if (!UciUp) return;
+    XtPopdown(UciShell);
+    XtDestroyWidget(UciShell);
+    UciUp = False;
+    ModeHighlight();
+}
+
+void UciCallback(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data, call_data;
+{
+    String name;
+    Arg args[16];
+    char buf[80];
+    int oldCores = appData.smpCores, ponder = 0;
+    
+    XtSetArg(args[0], XtNlabel, &name);
+    XtGetValues(w, args, 1);
+    
+    if (strcmp(name, "OK") == 0) {
+       int nr, i, j; String name;
+       for(i=0; i<6; i++) {
+           XtSetArg(args[0], XtNstring, &name);
+           XtGetValues(controlDesc[i].handle, args, 1);
+           if(i&1) {
+               if(name)
+                   *(char**) controlDesc[i].ptr = strdup(name);
+           } else {
+               if(sscanf(name, "%d", &j) == 1) 
+                   *(int*) controlDesc[i].ptr = j;
+           }
+       }
+       XtSetArg(args[0], XtNstate, &appData.usePolyglotBook);
+       XtGetValues(w1, args, 1);
+       XtSetArg(args[0], XtNstate, &appData.firstHasOwnBookUCI);
+       XtGetValues(w2, args, 1);
+       XtSetArg(args[0], XtNstate, &appData.secondHasOwnBookUCI);
+       XtGetValues(w3, args, 1);
+       XtSetArg(args[0], XtNstate, &ponder);
+       XtGetValues(w4, args, 1);
+
+       // adjust setting in other menu for duplicates 
+       // (perhaps duplicates should be removed from general Option Menu?)
+       XtSetArg(args[0], XtNleftBitmap, ponder ? xMarkPixmap : None);
+       XtSetValues(XtNameToWidget(menuBarWidget,
+                                  "menuOptions.Ponder Next Move"), args, 1);
+
+       // make sure changes are sent to first engine by re-initializing it
+       // if it was already started pre-emptively at end of previous game
+       if(gameMode == BeginningOfGame) Reset(True, True); else {
+           // Some changed setting need immediate sending always.
+           PonderNextMoveEvent(ponder);
+           if(oldCores != appData.smpCores)
+               NewSettingEvent(False, "cores", appData.smpCores);
+      }
+      UciPopDown();
+      return;
+    }
+}
+
+void UciPopUp()
+{
+    Arg args[16];
+    Widget popup, layout, dialog, edit, form, b_ok, b_cancel, last = NULL, new, upperLeft;
+    Window root, child;
+    int x, y, i, j;
+    int win_x, win_y;
+    unsigned int mask;
+    char def[80];
+    
+    i = 0;
+    XtSetArg(args[i], XtNresizable, True); i++;
+//    XtSetArg(args[i], XtNwidth, 300); i++;
+    UciShell = popup =
+      XtCreatePopupShell("Engine Settings", transientShellWidgetClass,
+                        shellWidget, args, i);
+    
+    layout =
+      XtCreateManagedWidget(layoutName, formWidgetClass, popup,
+                           layoutArgs, XtNumber(layoutArgs));
+  
+    
+    form =
+      XtCreateManagedWidget("form", formWidgetClass, layout,
+                           formArgs, XtNumber(formArgs));
+  
+    j = 0;
+    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+//    XtSetArg(args[j], XtNheight, 20); j++;
+    for(i = 0; controlDesc[i].name != NULL; i++) {
+       j = 3;
+       XtSetArg(args[j], XtNfromVert, last); j++;
+//     XtSetArg(args[j], XtNwidth, 130); j++;
+       XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;
+       XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+       XtSetArg(args[j], XtNborderWidth, 0); j++;
+       new = XtCreateManagedWidget(controlDesc[i].name, labelWidgetClass, form, args, j);
+       if(i==0) upperLeft = new;
+
+       j = 4;
+       XtSetArg(args[j], XtNborderWidth, 1); j++;
+       XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+       XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+       XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+       XtSetArg(args[j], XtNright, XtChainRight);  j++;
+       XtSetArg(args[j], XtNresizable, True);  j++;
+       XtSetArg(args[j], XtNwidth, i&1 ? 245 : 50); j++;
+       if(i&1) {
+           XtSetArg(args[j], XtNstring, * (char**) controlDesc[i].ptr ? 
+                                        * (char**) controlDesc[i].ptr : ""); j++;
+       } else {
+           sprintf(def, "%d", * (int*) controlDesc[i].ptr);
+           XtSetArg(args[j], XtNstring, def); j++;
+       }
+       XtSetArg(args[j], XtNfromHoriz, upperLeft); j++;
+       controlDesc[i].handle = last =
+           XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);
+       XtAddEventHandler(last, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+    }
+
+    j=0;
+    XtSetArg(args[j], XtNfromHoriz, controlDesc[0].handle);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;
+    XtSetArg(args[j], XtNtop, XtChainTop);  j++;
+    XtSetArg(args[j], XtNleft, XtChainRight);  j++;
+    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    XtSetArg(args[j], XtNstate, appData.ponderNextMove);  j++;
+    w4 = XtCreateManagedWidget("Ponder", toggleWidgetClass, form, args, j);   
+
+    j=0;
+    XtSetArg(args[j], XtNfromVert, last);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    b_ok = XtCreateManagedWidget("OK", commandWidgetClass, form, args, j);   
+    XtAddCallback(b_ok, XtNcallback, UciCallback, (XtPointer) 0);
+
+    XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;
+    b_cancel = XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j);   
+    XtAddCallback(b_cancel, XtNcallback, UciPopDown, (XtPointer) 0);
+
+    j = 5;
+    XtSetArg(args[j], XtNfromHoriz, upperLeft);  j++;
+    XtSetArg(args[j], XtNstate, appData.usePolyglotBook);  j++;
+    w1 = XtCreateManagedWidget(" use book ", toggleWidgetClass, form, args, j);   
+//    XtAddCallback(w1, XtNcallback, UciCallback, (XtPointer) 0);
+
+    j = 5;
+    XtSetArg(args[j], XtNfromHoriz, w1);  j++;
+    XtSetArg(args[j], XtNstate, appData.firstHasOwnBookUCI);  j++;
+    w2 = XtCreateManagedWidget("own book 1", toggleWidgetClass, form, args, j);   
+//    XtAddCallback(w2, XtNcallback, UciCallback, (XtPointer) 0);
+
+    j = 5;
+    XtSetArg(args[j], XtNfromHoriz, w2);  j++;
+    XtSetArg(args[j], XtNstate, appData.secondHasOwnBookUCI);  j++;
+    w3 = XtCreateManagedWidget("own book 2", toggleWidgetClass, form, args, j);   
+//    XtAddCallback(w3, XtNcallback, UciCallback, (XtPointer) 0);
+
+    XtRealizeWidget(popup);
+    CatchDeleteWindow(popup, "UciPopDown");
+    
+    XQueryPointer(xDisplay, xBoardWindow, &root, &child,
+                 &x, &y, &win_x, &win_y, &mask);
+    
+    XtSetArg(args[0], XtNx, x - 10);
+    XtSetArg(args[1], XtNy, y - 30);
+    XtSetValues(popup, args, 2);
+    
+    XtPopup(popup, XtGrabExclusive);
+    UciUp = True;
+
+    previous = NULL;
+    SetFocus(controlDesc[2].handle, popup, (XEvent*) NULL, False);
+//    XtSetKeyboardFocus(popup, controlDesc[1].handle);
+}
+
+void UciMenuProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+   UciPopUp();
+}
+
+//--------------------------- Engine-specific options menu ----------------------------------
+
+int SettingsUp;
+Widget SettingsShell;
+int values[MAX_OPTIONS];
+ChessProgramState *currentCps;
+
+void SettingsPopDown()
+{
+    if (!SettingsUp) return;
+    XtPopdown(SettingsShell);
+    XtDestroyWidget(SettingsShell);
+    SettingsUp = False;
+    ModeHighlight();
+}
+
+void SpinCallback(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data, call_data;
+{
+    String name, val;
+    Widget w2;
+    Arg args[16];
+    char buf[MSG_SIZ];
+    int i, j;
+    
+    XtSetArg(args[0], XtNlabel, &name);
+    XtGetValues(w, args, 1);
+    
+    j = 0;
+    XtSetArg(args[0], XtNstring, &val);
+    XtGetValues(currentCps->option[(int)client_data].handle, args, 1);
+    sscanf(val, "%d", &j);
+    if (strcmp(name, "+") == 0) {
+       if(++j > currentCps->option[(int)client_data].max) return;
+    } else
+    if (strcmp(name, "-") == 0) {
+       if(--j < currentCps->option[(int)client_data].min) return;
+    } else return;
+    sprintf(buf, "%d", j);
+    XtSetArg(args[0], XtNstring, buf);
+    XtSetValues(currentCps->option[(int)client_data].handle, args, 1);
+}
+
+void SettingsCallback(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data, call_data;
+{
+    String name, val;
+    Widget w2;
+    Arg args[16];
+    char buf[MSG_SIZ];
+    int i, j;
+    
+    XtSetArg(args[0], XtNlabel, &name);
+    XtGetValues(w, args, 1);
+    
+    if (strcmp(name, "cancel") == 0) {
+        SettingsPopDown();
+        return;
+    }
+    if (strcmp(name, "OK") == 0 || (int)client_data) { // save buttons imply OK
+       int nr;
+
+       for(i=0; i<currentCps->nrOptions; i++) { // send all options that had to be OK-ed to engine
+           switch(currentCps->option[i].type) {
+               case TextBox:
+                   XtSetArg(args[0], XtNstring, &val);
+                   XtGetValues(currentCps->option[i].handle, args, 1);
+                   if(strcmp(currentCps->option[i].textValue, val)) {
+                       strcpy(currentCps->option[i].textValue, val);
+                       sprintf(buf, "option %s %s\n", currentCps->option[i].name, val);
+                       SendToProgram(buf, currentCps);
+                   }
+                   break;
+               case Spin:
+                   XtSetArg(args[0], XtNstring, &val);
+                   XtGetValues(currentCps->option[i].handle, args, 1);
+                   sscanf(val, "%d", &j);
+                   if(j > currentCps->option[i].max) j = currentCps->option[i].max;
+                   if(j < currentCps->option[i].min) j = currentCps->option[i].min;
+                   if(currentCps->option[i].value != j) {
+                       currentCps->option[i].value = j;
+                       sprintf(buf, "option %s %d\n", currentCps->option[i].name, j);
+                       SendToProgram(buf, currentCps);
+                   }
+                   break;
+               case CheckBox:
+                   j = 0;
+                   XtSetArg(args[0], XtNstate, &j);
+                   XtGetValues(currentCps->option[i].handle, args, 1);
+                   if(currentCps->option[i].value != j) {
+                       currentCps->option[i].value = j;
+                       sprintf(buf, "option %s %d\n", currentCps->option[i].name, j);
+                       SendToProgram(buf, currentCps);
+                   }
+                   break;
+               case ComboBox:
+                   if(currentCps->option[i].value != values[i]) {
+                       currentCps->option[i].value = values[i];
+                       sprintf(buf, "option %s %s\n", currentCps->option[i].name, 
+                               ((char**)currentCps->option[i].textValue)[values[i]]);
+                       SendToProgram(buf, currentCps);
+                   }
+                   break;
+           }
+       }
+       if((int)client_data) { // send save-button command to engine
+           sprintf(buf, "option %s\n", name);
+           SendToProgram(buf, currentCps);
+       }
+        SettingsPopDown();
+        return;
+    }
+    sprintf(buf, "option %s\n", name);
+    SendToProgram(buf, currentCps);
+}
+
+void ComboSelect(w, addr, index) // callback for all combo items
      Widget w;\r
-     XtPointer client_data, call_data;\r
-{\r
-    String name, txt;\r
-    Widget w2;\r
-    Arg args[16];\r
-    char buf[80];\r
-    int j;\r
-\r
-    XtSetArg(args[0], XtNlabel, &name);\r
-    XtGetValues(w, args, 1);\r
-    \r
-    if (strcmp(name, "classical") == 0) {\r
-       if(!tcInc) return;\r
-       j=0;\r
-       XtSetArg(args[j], XtNlabel, "minutes for each"); j++;\r
-       XtSetValues(tcMess1, args, j);\r
-       j=0;\r
-       XtSetArg(args[j], XtNlabel, "moves"); j++;\r
-       XtSetValues(tcMess2, args, j);\r
-       j=0;\r
-       XtSetArg(args[j], XtNstring, &name); j++;\r
-       XtGetValues(tcData, args, j);\r
-       tcIncrement = 0; sscanf(name, "%d", &tcIncrement);\r
-       sprintf(buf, "%d", tcMoves);\r
-       j=0;\r
-       XtSetArg(args[j], XtNstring, buf); j++;\r
-       XtSetValues(tcData, args, j);\r
-       tcInc = False;\r
-        return;\r
-    }\r
-    if (strcmp(name, "incremental") == 0) {\r
-       if(tcInc) return;\r
-       j=0;\r
-       XtSetArg(args[j], XtNlabel, "minutes, plus"); j++;\r
-       XtSetValues(tcMess1, args, j);\r
-       j=0;\r
-       XtSetArg(args[j], XtNlabel, "sec/move"); j++;\r
-       XtSetValues(tcMess2, args, j);\r
-       j=0;\r
-       XtSetArg(args[j], XtNstring, &name); j++;\r
-       XtGetValues(tcData, args, j);\r
-       tcMoves = appData.movesPerSession; sscanf(name, "%d", &tcMoves);\r
-       sprintf(buf, "%d", tcIncrement);\r
-       j=0;\r
-       XtSetArg(args[j], XtNstring, buf); j++;\r
-       XtSetValues(tcData, args, j);\r
-       tcInc = True;\r
-        return;\r
-    }\r
-    if (strcmp(name, " OK ") == 0) {\r
-       int inc, mps, tc, ok;\r
-       XtSetArg(args[0], XtNstring, &txt);\r
-       XtGetValues(tcData, args, 1);\r
-       if(tcInc) {\r
-           ok = sscanf(txt, "%d", &inc); mps = 0;\r
-           if(!ok && txt[0] == 0) { inc = 0; ok = 1; } // accept empty string as zero\r
-           ok &= (inc >= 0);\r
-       } else {\r
-           ok = sscanf(txt, "%d", &mps); inc = -1;\r
-           ok &= (mps > 0);\r
-       }\r
-       if(ok != 1) {\r
-           XtSetArg(args[0], XtNstring, ""); // erase any offending input\r
-           XtSetValues(tcData, args, 1);\r
-           return;\r
-       }\r
-       XtSetArg(args[0], XtNstring, &txt);\r
-       XtGetValues(tcTime, args, 1);\r
-       if(!ParseTimeControl(txt, inc, mps)) {\r
-           XtSetArg(args[0], XtNstring, ""); // erase any offending input\r
-           XtSetValues(tcTime, args, 1);\r
-           DisplayError("Bad Time-Control String", 0);\r
-           return;\r
-       }\r
-       appData.movesPerSession = mps;\r
-       appData.timeIncrement = inc;\r
-       appData.timeControl = strdup(txt);\r
-       XtSetArg(args[0], XtNstring, &txt);\r
-       XtGetValues(tcOdds1, args, 1);\r
-       appData.firstTimeOdds = first.timeOdds \r
-               = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1;\r
-       XtGetValues(tcOdds2, args, 1);\r
-       appData.secondTimeOdds = second.timeOdds \r
-               = (sscanf(txt, "%d", &j) == 1 && j > 0) ? j : 1;\r
-\r
-       Reset(True, True);\r
-        TimeControlPopDown();\r
-        return;\r
-    }\r
-}\r
-\r
-void TimeControlPopUp()\r
+     caddr_t addr;\r
+     caddr_t index;\r
+{
+    Arg args[16];
+    int i = ((int)addr)>>8;
+    int j = 255 & (int) addr;
+
+    values[i] = j; // store in temporary, for transfer at OK
+    XtSetArg(args[0], XtNlabel, ((char**)currentCps->option[i].textValue)[j]);
+    XtSetValues(currentCps->option[i].handle, args, 1);\r
+}
+
+void CreateComboPopup(parent, name, n, mb)\r
+     Widget parent;
+     String name;
+     int n;\r
+     char *mb[];\r
 {\r
+    int i=0, j;\r
+    Widget menu, entry;\r
     Arg args[16];\r
-    Widget popup, layout, form, edit, b_ok, b_cancel, b_clas, b_inc, mess;\r
-    Window root, child;\r
-    int x, y, i, j;\r
-    int win_x, win_y;\r
-    unsigned int mask;\r
-    char def[80];\r
-    \r
-    tcInc = (appData.timeIncrement >= 0);\r
-    tcMoves = appData.movesPerSession; tcIncrement = appData.timeIncrement;\r
-    if(!tcInc) tcIncrement = 0;\r
-    sprintf(def, "%d", tcInc ? tcIncrement : tcMoves);\r
 \r
-    i = 0;\r
-    XtSetArg(args[i], XtNresizable, True); i++;\r
-//    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
-    TimeControlShell = popup =\r
-      XtCreatePopupShell("TimeControl Menu", transientShellWidgetClass,\r
-                        shellWidget, args, i);\r
-    \r
-    layout =\r
-      XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
-                           layoutArgs, XtNumber(layoutArgs));\r
-  \r
-    form =\r
-      XtCreateManagedWidget(layoutName, formWidgetClass, layout,\r
-                           formArgs, XtNumber(formArgs));\r
-  \r
+    menu = XtCreatePopupShell(name, simpleMenuWidgetClass,\r
+                             parent, NULL, 0);\r
     j = 0;\r
-//    XtSetArg(args[j], XtNwidth,     (XtArgVal) 300); j++;\r
-//    XtSetArg(args[j], XtNheight,    (XtArgVal) 85); j++;\r
-    XtSetValues(popup, args, j);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNborderWidth, 1); j++;\r
-    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
-    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
-    XtSetArg(args[j], XtNstring, appData.timeControl);  j++;\r
-    XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNresizable, True);  j++;\r
-    XtSetArg(args[j], XtNwidth,  85);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcTime = XtCreateManagedWidget("TC", asciiTextWidgetClass, form, args, j);\r
-    XtAddEventHandler(tcTime, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNlabel, tcInc ? "   minutes, plus   " : "minutes for each"); j++;\r
-    XtSetArg(args[j], XtNborderWidth, 0); j++;\r
-    XtSetArg(args[j], XtNfromHoriz, tcTime); j++;\r
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-  //  XtSetArg(args[j], XtNwidth,  100);  j++;\r
-  //  XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNborderWidth, 1); j++;\r
-    XtSetArg(args[j], XtNfromHoriz, tcMess1); j++;\r
-    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
-    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
-    XtSetArg(args[j], XtNstring, def);  j++;\r
-    XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNresizable, True);  j++;\r
-    XtSetArg(args[j], XtNwidth,  40);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcData = XtCreateManagedWidget("MPS", asciiTextWidgetClass, form, args, j);\r
-    XtAddEventHandler(tcData, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNlabel, tcInc ? "sec/move" : "moves     "); j++;\r
-    XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
-    XtSetArg(args[j], XtNborderWidth, 0); j++;\r
-    XtSetArg(args[j], XtNfromHoriz, tcData); j++;\r
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-//    XtSetArg(args[j], XtNwidth,  80);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass,\r
-                                  form, args, j);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNborderWidth, 1); j++;\r
-    XtSetArg(args[j], XtNfromVert, tcTime); j++;\r
-    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
-    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
-    XtSetArg(args[j], XtNstring, "1");  j++;\r
-    XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNresizable, True);  j++;\r
-    XtSetArg(args[j], XtNwidth,  40);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcOdds1 = XtCreateManagedWidget("Odds1", asciiTextWidgetClass, form, args, j);\r
-    XtAddEventHandler(tcOdds1, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNborderWidth, 1); j++;\r
-    XtSetArg(args[j], XtNfromVert, tcTime); j++;\r
-    XtSetArg(args[j], XtNfromHoriz, tcOdds1); j++;\r
-    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
-    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
-    XtSetArg(args[j], XtNstring, "1");  j++;\r
-    XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNresizable, True);  j++;\r
-    XtSetArg(args[j], XtNwidth,  40);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcOdds2 = XtCreateManagedWidget("Odds2", asciiTextWidgetClass, form, args, j);\r
-    XtAddEventHandler(tcOdds2, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNlabel, "Engine #1 and #2 Time-Odds Factors"); j++;\r
-    XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
-    XtSetArg(args[j], XtNborderWidth, 0); j++;\r
-    XtSetArg(args[j], XtNfromVert, tcTime); j++;\r
-    XtSetArg(args[j], XtNfromHoriz, tcOdds2); j++;\r
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-//    XtSetArg(args[j], XtNwidth,  200);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    mess = XtCreateManagedWidget("Oddstext", labelWidgetClass,\r
-                                  form, args, j);\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-    b_clas= XtCreateManagedWidget("classical", commandWidgetClass,\r
-                                  form, args, j);   \r
-    XtAddCallback(b_clas, XtNcallback, TimeControlCallback, (XtPointer) 0);\r
-\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;\r
-    XtSetArg(args[j], XtNfromHoriz, b_clas);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-    b_inc = XtCreateManagedWidget("incremental", commandWidgetClass,\r
-                                  form, args, j);   \r
-    XtAddCallback(b_inc, XtNcallback, TimeControlCallback, (XtPointer) 0);\r
-\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;\r
-    XtSetArg(args[j], XtNfromHoriz, tcData);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-    b_ok= XtCreateManagedWidget(" OK ", commandWidgetClass,\r
-                                  form, args, j);   \r
-    XtAddCallback(b_ok, XtNcallback, TimeControlCallback, (XtPointer) 0);\r
-\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromVert, tcOdds1);  j++;\r
-    XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-    b_cancel= XtCreateManagedWidget("cancel", commandWidgetClass,\r
-                                  form, args, j);   \r
-    XtAddCallback(b_cancel, XtNcallback, TimeControlPopDown, (XtPointer) 0);\r
-\r
-    XtRealizeWidget(popup);\r
-    CatchDeleteWindow(popup, "TimeControlPopDown");\r
-    \r
-    XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
-                 &x, &y, &win_x, &win_y, &mask);\r
-    \r
-    XtSetArg(args[0], XtNx, x - 10);\r
-    XtSetArg(args[1], XtNy, y - 30);\r
-    XtSetValues(popup, args, 2);\r
-    \r
-    XtPopup(popup, XtGrabExclusive);\r
-    TimeControlUp = True;\r
-    \r
-    previous = NULL;\r
-    SetFocus(tcTime, popup, (XEvent*) NULL, False);\r
-//    XtSetKeyboardFocus(popup, tcTime);\r
-}\r
-\r
-void TimeControlProc(w, event, prms, nprms)\r
-     Widget w;\r
-     XEvent *event;\r
-     String *prms;\r
-     Cardinal *nprms;\r
-{\r
-   TimeControlPopUp();\r
-}\r
-\r
-//--------------------------- Engine-Options Menu Popup ----------------------------------\r
-int EngineUp;\r
-Widget EngineShell;\r
-extern int adjudicateLossThreshold;\r
-\r
-Widget engDrawMoves, engThreshold, engRule, engRepeat;\r
-\r
-void EnginePopDown()\r
-{\r
-    if (!EngineUp) return;\r
-    XtPopdown(EngineShell);\r
-    XtDestroyWidget(EngineShell);\r
-    EngineUp = False;\r
-    ModeHighlight();\r
-}\r
-\r
-int ReadToggle(Widget w)\r
-{\r
-    Arg args; Boolean res;\r
-\r
-    XtSetArg(args, XtNstate, &res);\r
-    XtGetValues(w, &args, 1);\r
-\r
-    return res;\r
-}\r
-\r
-Widget w1, w2, w3, w4, w5, w6, w7, w8;\r
-\r
-void EngineCallback(w, client_data, call_data)\r
-     Widget w;\r
-     XtPointer client_data, call_data;\r
-{\r
-    String name;\r
-    Widget s2;\r
-    Arg args[16];\r
-    char buf[80];\r
-    int j;\r
-    \r
-    XtSetArg(args[0], XtNlabel, &name);\r
-    XtGetValues(w, args, 1);\r
-    \r
-    if (strcmp(name, "OK") == 0) {\r
-       // read all switches\r
-       appData.periodicUpdates = ReadToggle(w1);\r
-//     appData.hideThinkingFromHuman = ReadToggle(w2);\r
-       appData.firstScoreIsAbsolute  = ReadToggle(w3);\r
-       appData.secondScoreIsAbsolute = ReadToggle(w4);\r
-       appData.testClaims    = ReadToggle(w5);\r
-       appData.checkMates    = ReadToggle(w6);\r
-       appData.materialDraws = ReadToggle(w7);\r
-       appData.trivialDraws  = ReadToggle(w8);\r
-\r
-       // adjust setting in other menu for duplicates \r
-       // (perhaps duplicates should be removed from general Option Menu?)\r
-//     XtSetArg(args[0], XtNleftBitmap, appData.showThinking ? xMarkPixmap : None);\r
-//     XtSetValues(XtNameToWidget(menuBarWidget,\r
-//                                "menuOptions.Show Thinking"), args, 1);\r
-\r
-       // read out numeric controls, simply ignore bad formats for now\r
-       XtSetArg(args[0], XtNstring, &name);\r
-       XtGetValues(engDrawMoves, args, 1);\r
-       if(sscanf(name, "%d", &j) == 1) appData.adjudicateDrawMoves = j;\r
-       XtGetValues(engThreshold, args, 1);\r
-       if(sscanf(name, "%d", &j) == 1) \r
-               adjudicateLossThreshold = appData.adjudicateLossThreshold = -j; // inverted!\r
-       XtGetValues(engRule, args, 1);\r
-       if(sscanf(name, "%d", &j) == 1) appData.ruleMoves = j;\r
-       XtGetValues(engRepeat, args, 1);\r
-       if(sscanf(name, "%d", &j) == 1) appData.drawRepeats = j;\r
-\r
-        EnginePopDown();\r
-       ShowThinkingEvent(); // [HGM] thinking: score adjudication might need thinking output\r
-        return;\r
+    XtSetArg(args[j], XtNwidth, 100);  j++;
+//    XtSetArg(args[j], XtNright, XtChainRight);  j++;
+    while (mb[i] != NULL) {
+           entry = XtCreateManagedWidget(mb[i], smeBSBObjectClass,\r
+                                         menu, args, j);\r
+           XtAddCallback(entry, XtNcallback,\r
+                         (XtCallbackProc) ComboSelect,\r
+                         (caddr_t) (256*n+i));\r
+       i++;\r
     }\r
-}\r
-\r
-void EnginePopUp()\r
-{\r
-    Arg args[16];\r
-    Widget popup, layout, form, edit, b_ok, b_cancel, b_clas, b_inc, s1; \r
-    Window root, child;\r
-    int x, y, i, j, width;\r
-    int win_x, win_y;\r
-    unsigned int mask;\r
-    char def[80];\r
-    \r
-    tcInc = (appData.timeIncrement >= 0);\r
-    tcMoves = appData.movesPerSession; tcIncrement = appData.timeIncrement;\r
-    if(!tcInc) tcIncrement = 0;\r
-    sprintf(def, "%d", tcInc ? tcIncrement : tcMoves);\r
-\r
-    i = 0;\r
-    XtSetArg(args[i], XtNresizable, True); i++;\r
-//    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
-    EngineShell = popup =\r
-      XtCreatePopupShell("Adjudications", transientShellWidgetClass,\r
-                        shellWidget, args, i);\r
-    \r
-    layout =\r
-      XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
-                           layoutArgs, XtNumber(layoutArgs));\r
-  \r
-    form =\r
-      XtCreateManagedWidget(layoutName, formWidgetClass, layout,\r
-                           formArgs, XtNumber(formArgs));\r
-  \r
-    j = 0;\r
-//    XtSetArg(args[j], XtNwidth,     (XtArgVal) 250); j++;\r
-//    XtSetArg(args[j], XtNheight,    (XtArgVal) 400); j++;\r
-//    XtSetValues(popup, args, j);\r
-\r
-    j = 0;\r
-//    XtSetArg(args[j], XtNwidth,       (XtArgVal) 250); j++;\r
-//    XtSetArg(args[j], XtNheight,      (XtArgVal) 20); j++;\r
-    XtSetArg(args[j], XtNleft,        (XtArgVal) XtChainLeft); j++;\r
-    XtSetArg(args[j], XtNright,       (XtArgVal) XtChainRight); j++;\r
-    XtSetArg(args[j], XtNstate,       appData.periodicUpdates); j++;\r
-//    XtSetArg(args[j], XtNjustify,     (XtArgVal) XtJustifyLeft); j++;\r
-    w1 = XtCreateManagedWidget("Periodic Updates (Analysis Mode)", toggleWidgetClass, form, args, j);\r
-\r
-    XtSetArg(args[j], XtNwidth,       (XtArgVal) &width);\r
-    XtGetValues(w1, &args[j], 1);\r
-\r
-//    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w1);\r
-//    XtSetArg(args[j-3], XtNstate,       appData.hideThinkingFromHuman);\r
-//    w2 = XtCreateManagedWidget("Hide Thinking from Human", toggleWidgetClass, form, args, j);\r
-\r
-    XtSetArg(args[j], XtNwidth,       (XtArgVal) width); j++;\r
-    XtSetArg(args[j-2], XtNstate,     appData.firstScoreIsAbsolute);\r
-    XtSetArg(args[j], XtNfromVert,    (XtArgVal) w1); j++;\r
-    w3 = XtCreateManagedWidget("Engine #1 Score is Absolute", toggleWidgetClass, form, args, j);\r
-\r
-    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w3);\r
-    XtSetArg(args[j-3], XtNstate,       appData.secondScoreIsAbsolute);\r
-    w4 = XtCreateManagedWidget("Engine #2 Score is Absolute", toggleWidgetClass, form, args, j);\r
-\r
-    s1 = XtCreateManagedWidget("\nEngine-Engine Adjudications:", labelWidgetClass, form, args, 3);\r
-\r
-    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) s1);\r
-    XtSetArg(args[j-3], XtNstate,       appData.testClaims);\r
-    w5 = XtCreateManagedWidget("Verify Engine Result Claims", toggleWidgetClass, form, args, j);\r
-\r
-    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w5);\r
-    XtSetArg(args[j-3], XtNstate,       appData.checkMates);\r
-    w6 = XtCreateManagedWidget("Detect All Mates", toggleWidgetClass, form, args, j);\r
-\r
-    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w6);\r
-    XtSetArg(args[j-3], XtNstate,       appData.materialDraws);\r
-    w7 = XtCreateManagedWidget("Draw when Insuff. Mating Material", toggleWidgetClass, form, args, j);\r
-\r
-    XtSetArg(args[j-1], XtNfromVert,  (XtArgVal) w7);\r
-    XtSetArg(args[j-3], XtNstate,       appData.trivialDraws);\r
-    w8 = XtCreateManagedWidget("Adjudicate Trivial Draws", toggleWidgetClass, form, args, j);\r
-\r
-    XtSetArg(args[0], XtNfromVert,  (XtArgVal) w4);\r
-    XtSetArg(args[1], XtNborderWidth, (XtArgVal) 0);\r
-    XtSetValues(s1, args, 2);\r
-\r
-    sprintf(def, "%d", appData.adjudicateDrawMoves);\r
-    j= 0;\r
-    XtSetArg(args[j], XtNborderWidth, 1); j++;\r
-    XtSetArg(args[j], XtNfromVert, w8); j++;\r
-    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
-    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
-    XtSetArg(args[j], XtNstring, def);  j++;\r
-    XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNresizable, True);  j++;\r
-    XtSetArg(args[j], XtNwidth,  60);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    engDrawMoves = XtCreateManagedWidget("Length", asciiTextWidgetClass, form, args, j);\r
-    XtAddEventHandler(engDrawMoves, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNlabel, " moves maximum, then draw"); j++;\r
-    XtSetArg(args[j], XtNjustify,     (XtArgVal) XtJustifyLeft); j++;\r
-    XtSetArg(args[j], XtNborderWidth, 0); j++;\r
-    XtSetArg(args[j], XtNfromVert, w8); j++;\r
-    XtSetArg(args[j], XtNfromHoriz, engDrawMoves); j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-//    XtSetArg(args[j], XtNwidth,  170);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);\r
-\r
-    sprintf(def, "%d", -appData.adjudicateLossThreshold); // inverted!\r
-    j= 0;\r
-    XtSetArg(args[j], XtNborderWidth, 1); j++;\r
-    XtSetArg(args[j], XtNfromVert, engDrawMoves); j++;\r
-    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
-    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
-    XtSetArg(args[j], XtNstring, def);  j++;\r
-    XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNresizable, True);  j++;\r
-    XtSetArg(args[j], XtNwidth,  60);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    engThreshold = XtCreateManagedWidget("Threshold", asciiTextWidgetClass, form, args, j);\r
-    XtAddEventHandler(engThreshold, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNlabel, "-centiPawn lead is win"); j++;\r
-    XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
-    XtSetArg(args[j], XtNborderWidth, 0); j++;\r
-    XtSetArg(args[j], XtNfromVert, engDrawMoves); j++;\r
-    XtSetArg(args[j], XtNfromHoriz, engThreshold); j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-//    XtSetArg(args[j], XtNwidth,  150);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass, form, args, j);\r
-\r
-    sprintf(def, "%d", appData.ruleMoves);\r
-    j= 0;\r
-    XtSetArg(args[j], XtNborderWidth, 1); j++;\r
-    XtSetArg(args[j], XtNfromVert, engThreshold); j++;\r
-    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
-    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
-    XtSetArg(args[j], XtNstring, def);  j++;\r
-    XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNresizable, True);  j++;\r
-    XtSetArg(args[j], XtNwidth,  30);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    engRule = XtCreateManagedWidget("Rule", asciiTextWidgetClass, form, args, j);\r
-    XtAddEventHandler(engRule, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNlabel, "-move rule applied"); j++;\r
-    XtSetArg(args[j], XtNjustify,     (XtArgVal) XtJustifyLeft); j++;\r
-    XtSetArg(args[j], XtNborderWidth, 0); j++;\r
-    XtSetArg(args[j], XtNfromVert, engThreshold); j++;\r
-    XtSetArg(args[j], XtNfromHoriz, engRule); j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-//    XtSetArg(args[j], XtNwidth,  130);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcMess1 = XtCreateManagedWidget("TCtext", labelWidgetClass, form, args, j);\r
-\r
-    sprintf(def, "%d", appData.drawRepeats);\r
-    j= 0;\r
-    XtSetArg(args[j], XtNborderWidth, 1); j++;\r
-    XtSetArg(args[j], XtNfromVert, engRule); j++;\r
-    XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
-    XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
-    XtSetArg(args[j], XtNstring, def);  j++;\r
-    XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNresizable, True);  j++;\r
-    XtSetArg(args[j], XtNwidth,  30);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    engRepeat = XtCreateManagedWidget("Repeats", asciiTextWidgetClass, form, args, j);\r
-    XtAddEventHandler(engRepeat, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
-\r
-    j= 0;\r
-    XtSetArg(args[j], XtNlabel, "-fold repeat is draw"); j++;\r
-    XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
-    XtSetArg(args[j], XtNborderWidth, 0); j++;\r
-    XtSetArg(args[j], XtNfromVert, engRule); j++;\r
-    XtSetArg(args[j], XtNfromHoriz, engRepeat); j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-//    XtSetArg(args[j], XtNwidth,  130);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20);  j++;\r
-    tcMess2 = XtCreateManagedWidget("MPStext", labelWidgetClass, form, args, j);\r
-\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromVert, engRepeat);  j++;\r
-    XtSetArg(args[j], XtNfromHoriz, tcMess2);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-    b_ok= XtCreateManagedWidget("OK", commandWidgetClass, form, args, j);   \r
-    XtAddCallback(b_ok, XtNcallback, EngineCallback, (XtPointer) 0);\r
-\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromVert, engRepeat);  j++;\r
-    XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-    b_cancel= XtCreateManagedWidget("cancel", commandWidgetClass,\r
-                                  form, args, j);   \r
-    XtAddCallback(b_cancel, XtNcallback, EnginePopDown, (XtPointer) 0);\r
-\r
-    XtRealizeWidget(popup);\r
-    CatchDeleteWindow(popup, "EnginePopDown");\r
-    \r
-    XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
-                 &x, &y, &win_x, &win_y, &mask);\r
-    \r
-    XtSetArg(args[0], XtNx, x - 10);\r
-    XtSetArg(args[1], XtNy, y - 30);\r
-    XtSetValues(popup, args, 2);\r
-    \r
-    XtPopup(popup, XtGrabExclusive);\r
-    EngineUp = True;\r
-    \r
-    previous = NULL;\r
-    SetFocus(engThreshold, popup, (XEvent*) NULL, False);\r
-}\r
-\r
-void EngineMenuProc(w, event, prms, nprms)\r
-     Widget w;\r
-     XEvent *event;\r
-     String *prms;\r
-     Cardinal *nprms;\r
-{\r
-   EnginePopUp();\r
-}\r
-\r
-//--------------------------- New-Variant Menu PopUp -----------------------------------\r
-struct NewVarButton {\r
-  char   *name;\r
-  char *color;\r
-  Widget handle;\r
-  VariantClass variant;\r
-};\r
-\r
-struct NewVarButton buttonDesc[] = {\r
-    {"normal",            "#FFFFFF", 0, VariantNormal},\r
-    {"FRC",               "#FFFFFF", 0, VariantFischeRandom},\r
-    {"wild castle",       "#FFFFFF", 0, VariantWildCastle},\r
-    {"no castle",         "#FFFFFF", 0, VariantNoCastle},\r
-    {"knightmate",        "#FFFFFF", 0, VariantKnightmate},\r
-    {"berolina",          "#FFFFFF", 0, VariantBerolina},\r
-    {"cylinder",          "#FFFFFF", 0, VariantCylinder},\r
-    {"shatranj",          "#FFFFFF", 0, VariantShatranj},\r
-    {"atomic",            "#FFFFFF", 0, VariantAtomic},\r
-    {"two kings",         "#FFFFFF", 0, VariantTwoKings},\r
-    {"3-checks",          "#FFFFFF", 0, Variant3Check},\r
-    {"suicide",           "#FFFFBF", 0, VariantSuicide},\r
-    {"give-away",         "#FFFFBF", 0, VariantGiveaway},\r
-    {"losers",            "#FFFFBF", 0, VariantLosers},\r
-    {"fairy",             "#BFBFBF", 0, VariantFairy},\r
-    {"Superchess",        "#FFBFBF", 0, VariantSuper},\r
-    {"crazyhouse",        "#FFBFBF", 0, VariantCrazyhouse},\r
-    {"bughouse",          "#FFBFBF", 0, VariantBughouse},\r
-    {"shogi (9x9)",       "#BFFFFF", 0, VariantShogi},\r
-    {"xiangqi (9x10)",    "#BFFFFF", 0, VariantXiangqi},\r
-    {"courier (12x8)",    "#BFFFBF", 0, VariantCourier},\r
-    {"janus (10x8)",      "#BFBFFF", 0, VariantJanus},\r
-    {"Capablanca (10x8)", "#BFBFFF", 0, VariantCapablanca},\r
-    {"CRC (10x8)",        "#BFBFFF", 0, VariantCapaRandom},\r
-#ifdef GOTHIC\r
-    {"Gothic (10x8)",     "#BFBFFF", 0, VariantGothic},\r
-#endif\r
-#ifdef FALCON\r
-    {"Falcon (10x8)",     "#BFBFFF", 0, VariantFalcon},\r
-#endif\r
-    {NULL,                0, 0, (VariantClass) 0}\r
-};\r
-\r
-int NewVariantUp;\r
-Widget NewVariantShell;\r
-\r
-void NewVariantPopDown()\r
-{\r
-    if (!NewVariantUp) return;\r
-    XtPopdown(NewVariantShell);\r
-    XtDestroyWidget(NewVariantShell);\r
-    NewVariantUp = False;\r
-    ModeHighlight();\r
-}\r
-\r
-void NewVariantCallback(w, client_data, call_data)\r
-     Widget w;\r
-     XtPointer client_data, call_data;\r
-{\r
-    String name;\r
-    Widget w2;\r
-    Arg args[16];\r
-    char buf[80];\r
-    VariantClass v;\r
-    \r
-    XtSetArg(args[0], XtNlabel, &name);\r
-    XtGetValues(w, args, 1);\r
-    \r
-    if (strcmp(name, "  OK  ") == 0) {\r
-       int nr = (int) XawToggleGetCurrent(buttonDesc[0].handle) - 1;\r
-       if(nr < 0) return;\r
-       v = buttonDesc[nr].variant;\r
-       if(!appData.noChessProgram) { \r
-           char *name = VariantName(v), buf[MSG_SIZ];\r
-           if (first.protocolVersion > 1 && StrStr(first.variants, name) == NULL) {\r
-               /* [HGM] in protocol 2 we check if variant is suported by engine */\r
-               sprintf(buf, "Variant %s not supported by %s", name, first.tidy);\r
-               DisplayError(buf, 0);\r
-//             NewVariantPopDown();\r
-               return; /* ignore OK if first engine does not support it */\r
-           } else\r
-           if (second.initDone && second.protocolVersion > 1 && StrStr(second.variants, name) == NULL) {\r
-               sprintf(buf, "Warning: second engine (%s) does not support this!", second.tidy);\r
-               DisplayError(buf, 0);   /* use of second engine is optional; only warn user */\r
-           }\r
-       }\r
-\r
-       gameInfo.variant = v;\r
-       appData.variant = VariantName(v);\r
-\r
-       shuffleOpenings = FALSE; /* [HGM] shuffle: possible shuffle reset when we switch */\r
-       startedFromPositionFile = FALSE; /* [HGM] loadPos: no longer valid in new variant */\r
-       appData.pieceToCharTable = NULL;\r
-       Reset(True, True);\r
-        NewVariantPopDown();\r
-        return;\r
-    }\r
-}\r
-\r
-void NewVariantPopUp()\r
-{\r
-    Arg args[16];\r
-    Widget popup, layout, dialog, edit, form, last = NULL, b_ok, b_cancel;\r
-    Window root, child;\r
-    int x, y, i, j;\r
-    int win_x, win_y;\r
-    unsigned int mask;\r
-    char def[80];\r
-    XrmValue vFrom, vTo;\r
-\r
-    i = 0;\r
-    XtSetArg(args[i], XtNresizable, True); i++;\r
-//    XtSetArg(args[i], XtNwidth, 250); i++;\r
-//    XtSetArg(args[i], XtNheight, 300); i++;\r
-    NewVariantShell = popup =\r
-      XtCreatePopupShell("NewVariant Menu", transientShellWidgetClass,\r
-                        shellWidget, args, i);\r
-    \r
-    layout =\r
-      XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
-                           layoutArgs, XtNumber(layoutArgs));\r
-  \r
-    form =\r
-      XtCreateManagedWidget("form", formWidgetClass, layout,\r
-                           formArgs, XtNumber(formArgs));\r
-  \r
-    for(i = 0; buttonDesc[i].name != NULL; i++) {\r
-       Pixel buttonColor;\r
-       if (!appData.monoMode) {\r
-           vFrom.addr = (caddr_t) buttonDesc[i].color;\r
-           vFrom.size = strlen(buttonDesc[i].color);\r
-           XtConvert(shellWidget, XtRString, &vFrom, XtRPixel, &vTo);\r
-           if (vTo.addr == NULL) {\r
-               buttonColor = (Pixel) -1;\r
-           } else {\r
-               buttonColor = *(Pixel *) vTo.addr;\r
-           }\r
-       }\r
-    \r
-       j = 0;\r
-       XtSetArg(args[j], XtNradioGroup, last); j++;\r
-       XtSetArg(args[j], XtNwidth, 125); j++;\r
-//     XtSetArg(args[j], XtNheight, 16); j++;\r
-       XtSetArg(args[j], XtNfromVert, i == 15 ? NULL : last); j++;\r
-       XtSetArg(args[j], XtNfromHoriz, i < 15 ? NULL : buttonDesc[i-15].handle); j++;\r
-       XtSetArg(args[j], XtNradioData, i+1); j++;\r
-       XtSetArg(args[j], XtNbackground, buttonColor); j++;\r
-       XtSetArg(args[j], XtNstate, gameInfo.variant == buttonDesc[i].variant); j++;\r
-       buttonDesc[i].handle = last =\r
-           XtCreateManagedWidget(buttonDesc[i].name, toggleWidgetClass, form, args, j);\r
-    }\r
-\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromVert, buttonDesc[12].handle);  j++;\r
-    XtSetArg(args[j], XtNfromHoriz, buttonDesc[12].handle);  j++;\r
-    XtSetArg(args[j], XtNheight, 35); j++;\r
-//    XtSetArg(args[j], XtNwidth, 60); j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-    b_cancel= XtCreateManagedWidget("CANCEL", commandWidgetClass, form, args, j);   \r
-    XtAddCallback(b_cancel, XtNcallback, NewVariantPopDown, (XtPointer) 0);\r
-\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromHoriz, b_cancel);  j++;\r
-    XtSetArg(args[j], XtNfromVert, buttonDesc[12].handle);  j++;\r
-    XtSetArg(args[j], XtNheight, 35); j++;\r
-//    XtSetArg(args[j], XtNwidth, 60); j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-    b_ok= XtCreateManagedWidget("  OK  ", commandWidgetClass, form, args, j);   \r
-    XtAddCallback(b_ok, XtNcallback, NewVariantCallback, (XtPointer) 0);\r
-\r
-    XtRealizeWidget(popup);\r
-    CatchDeleteWindow(popup, "NewVariantPopDown");\r
-    \r
-    XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
-                 &x, &y, &win_x, &win_y, &mask);\r
-    \r
-    XtSetArg(args[0], XtNx, x - 10);\r
-    XtSetArg(args[1], XtNy, y - 30);\r
-    XtSetValues(popup, args, 2);\r
-    \r
-    XtPopup(popup, XtGrabExclusive);\r
-    NewVariantUp = True;\r
-}\r
-\r
-void NewVariantProc(w, event, prms, nprms)\r
-     Widget w;\r
-     XEvent *event;\r
-     String *prms;\r
-     Cardinal *nprms;\r
-{\r
-   NewVariantPopUp();\r
-}\r
-\r
-//--------------------------- UCI Menu Popup ------------------------------------------\r
-int UciUp;\r
-Widget UciShell;\r
-\r
-struct UciControl {\r
-  char *name;\r
-  Widget handle;\r
-  void *ptr;\r
-};\r
-\r
-struct UciControl controlDesc[] = {\r
-  {"maximum nr of CPUs:", 0, &appData.smpCores},\r
-  {"Polyglot Directory:", 0, &appData.polyglotDir},\r
-  {"Hash Size (MB):",     0, &appData.defaultHashSize},\r
-  {"EGTB Path:",          0, &appData.defaultPathEGTB},\r
-  {"EGTB Cache (MB):",    0, &appData.defaultCacheSizeEGTB},\r
-  {"Polyglot Book:",      0, &appData.polyglotBook},\r
-  {NULL, 0, NULL},\r
-};\r
-\r
-void UciPopDown()\r
-{\r
-    if (!UciUp) return;\r
-    XtPopdown(UciShell);\r
-    XtDestroyWidget(UciShell);\r
-    UciUp = False;\r
-    ModeHighlight();\r
-}\r
-\r
-void UciCallback(w, client_data, call_data)\r
-     Widget w;\r
-     XtPointer client_data, call_data;\r
-{\r
-    String name;\r
-    Arg args[16];\r
-    char buf[80];\r
-    int oldCores = appData.smpCores, ponder = 0;\r
-    \r
-    XtSetArg(args[0], XtNlabel, &name);\r
-    XtGetValues(w, args, 1);\r
-    \r
-    if (strcmp(name, "OK") == 0) {\r
-       int nr, i, j; String name;\r
-       for(i=0; i<6; i++) {\r
-           XtSetArg(args[0], XtNstring, &name);\r
-           XtGetValues(controlDesc[i].handle, args, 1);\r
-           if(i&1) {\r
-               if(name)\r
-                   *(char**) controlDesc[i].ptr = strdup(name);\r
-           } else {\r
-               if(sscanf(name, "%d", &j) == 1) \r
-                   *(int*) controlDesc[i].ptr = j;\r
-           }\r
-       }\r
-       XtSetArg(args[0], XtNstate, &appData.usePolyglotBook);\r
-       XtGetValues(w1, args, 1);\r
-       XtSetArg(args[0], XtNstate, &appData.firstHasOwnBookUCI);\r
-       XtGetValues(w2, args, 1);\r
-       XtSetArg(args[0], XtNstate, &appData.secondHasOwnBookUCI);\r
-       XtGetValues(w3, args, 1);\r
-       XtSetArg(args[0], XtNstate, &ponder);\r
-       XtGetValues(w4, args, 1);\r
-\r
-       // adjust setting in other menu for duplicates \r
-       // (perhaps duplicates should be removed from general Option Menu?)\r
-       XtSetArg(args[0], XtNleftBitmap, ponder ? xMarkPixmap : None);\r
-       XtSetValues(XtNameToWidget(menuBarWidget,\r
-                                  "menuOptions.Ponder Next Move"), args, 1);\r
-\r
-       // make sure changes are sent to first engine by re-initializing it\r
-       // if it was already started pre-emptively at end of previous game\r
-       if(gameMode == BeginningOfGame) Reset(True, True); else {\r
-           // Some changed setting need immediate sending always.\r
-           PonderNextMoveEvent(ponder);\r
-           if(oldCores != appData.smpCores)\r
-               NewSettingEvent(False, "cores", appData.smpCores);\r
-      }\r
-      UciPopDown();\r
-      return;\r
-    }\r
-}\r
-\r
-void UciPopUp()\r
-{\r
-    Arg args[16];\r
-    Widget popup, layout, dialog, edit, form, b_ok, b_cancel, last = NULL, new, upperLeft;\r
-    Window root, child;\r
-    int x, y, i, j;\r
-    int win_x, win_y;\r
-    unsigned int mask;\r
-    char def[80];\r
-    \r
-    i = 0;\r
-    XtSetArg(args[i], XtNresizable, True); i++;\r
-//    XtSetArg(args[i], XtNwidth, 300); i++;\r
-    UciShell = popup =\r
-      XtCreatePopupShell("Engine Settings", transientShellWidgetClass,\r
-                        shellWidget, args, i);\r
-    \r
-    layout =\r
-      XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
-                           layoutArgs, XtNumber(layoutArgs));\r
-  \r
-    \r
-    form =\r
-      XtCreateManagedWidget("form", formWidgetClass, layout,\r
-                           formArgs, XtNumber(formArgs));\r
-  \r
-    j = 0;\r
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-//    XtSetArg(args[j], XtNheight, 20); j++;\r
-    for(i = 0; controlDesc[i].name != NULL; i++) {\r
-       j = 3;\r
-       XtSetArg(args[j], XtNfromVert, last); j++;\r
-//     XtSetArg(args[j], XtNwidth, 130); j++;\r
-       XtSetArg(args[j], XtNjustify, XtJustifyLeft); j++;\r
-       XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-       XtSetArg(args[j], XtNborderWidth, 0); j++;\r
-       new = XtCreateManagedWidget(controlDesc[i].name, labelWidgetClass, form, args, j);\r
-       if(i==0) upperLeft = new;\r
-\r
-       j = 4;\r
-       XtSetArg(args[j], XtNborderWidth, 1); j++;\r
-       XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;\r
-       XtSetArg(args[j], XtNuseStringInPlace, False);  j++;\r
-       XtSetArg(args[j], XtNdisplayCaret, False);  j++;\r
-       XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-       XtSetArg(args[j], XtNresizable, True);  j++;\r
-       XtSetArg(args[j], XtNwidth, i&1 ? 245 : 50); j++;\r
-       if(i&1) {\r
-           XtSetArg(args[j], XtNstring, * (char**) controlDesc[i].ptr ? \r
-                                        * (char**) controlDesc[i].ptr : ""); j++;\r
-       } else {\r
-           sprintf(def, "%d", * (int*) controlDesc[i].ptr);\r
-           XtSetArg(args[j], XtNstring, def); j++;\r
-       }\r
-       XtSetArg(args[j], XtNfromHoriz, upperLeft); j++;\r
-       controlDesc[i].handle = last =\r
-           XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j);\r
-       XtAddEventHandler(last, ButtonPressMask, False, SetFocus, (XtPointer) popup);\r
-    }\r
-\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromHoriz, controlDesc[0].handle);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainTop);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainRight);  j++;\r
-    XtSetArg(args[j], XtNstate, appData.ponderNextMove);  j++;\r
-    w4 = XtCreateManagedWidget("Ponder", toggleWidgetClass, form, args, j);   \r
-\r
-    j=0;\r
-    XtSetArg(args[j], XtNfromVert, last);  j++;\r
-    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;\r
-    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;\r
-    XtSetArg(args[j], XtNright, XtChainLeft);  j++;\r
-    b_ok = XtCreateManagedWidget("OK", commandWidgetClass, form, args, j);   \r
-    XtAddCallback(b_ok, XtNcallback, UciCallback, (XtPointer) 0);\r
-\r
-    XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;\r
-    b_cancel = XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j);   \r
-    XtAddCallback(b_cancel, XtNcallback, UciPopDown, (XtPointer) 0);\r
-\r
-    j = 5;\r
-    XtSetArg(args[j], XtNfromHoriz, upperLeft);  j++;\r
-    XtSetArg(args[j], XtNstate, appData.usePolyglotBook);  j++;\r
-    w1 = XtCreateManagedWidget(" use book ", toggleWidgetClass, form, args, j);   \r
-//    XtAddCallback(w1, XtNcallback, UciCallback, (XtPointer) 0);\r
-\r
-    j = 5;\r
-    XtSetArg(args[j], XtNfromHoriz, w1);  j++;\r
-    XtSetArg(args[j], XtNstate, appData.firstHasOwnBookUCI);  j++;\r
-    w2 = XtCreateManagedWidget("own book 1", toggleWidgetClass, form, args, j);   \r
-//    XtAddCallback(w2, XtNcallback, UciCallback, (XtPointer) 0);\r
-\r
-    j = 5;\r
-    XtSetArg(args[j], XtNfromHoriz, w2);  j++;\r
-    XtSetArg(args[j], XtNstate, appData.secondHasOwnBookUCI);  j++;\r
-    w3 = XtCreateManagedWidget("own book 2", toggleWidgetClass, form, args, j);   \r
-//    XtAddCallback(w3, XtNcallback, UciCallback, (XtPointer) 0);\r
-\r
-    XtRealizeWidget(popup);\r
-    CatchDeleteWindow(popup, "UciPopDown");\r
-    \r
-    XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
-                 &x, &y, &win_x, &win_y, &mask);\r
-    \r
-    XtSetArg(args[0], XtNx, x - 10);\r
-    XtSetArg(args[1], XtNy, y - 30);\r
-    XtSetValues(popup, args, 2);\r
-    \r
-    XtPopup(popup, XtGrabExclusive);\r
-    UciUp = True;\r
-\r
-    previous = NULL;\r
-    SetFocus(controlDesc[2].handle, popup, (XEvent*) NULL, False);\r
-//    XtSetKeyboardFocus(popup, controlDesc[1].handle);\r
-}\r
-\r
-void UciMenuProc(w, event, prms, nprms)\r
-     Widget w;\r
-     XEvent *event;\r
-     String *prms;\r
-     Cardinal *nprms;\r
-{\r
-   UciPopUp();\r
-}\r
-\r
-//--------------------------- General Popup for Cloning ----------------------------------\r
-#if 0\r
-int XXXUp;\r
-Widget XXXShell;\r
-\r
-void XXXPopDown()\r
-{\r
-    if (!XXXUp) return;\r
-    XtPopdown(XXXShell);\r
-    XtDestroyWidget(XXXShell);\r
-    XXXUp = False;\r
-    ModeHighlight();\r
-}\r
-\r
-void XXXCallback(w, client_data, call_data)\r
-     Widget w;\r
-     XtPointer client_data, call_data;\r
-{\r
-    String name;\r
-    Widget w2;\r
-    Arg args[16];\r
-    char buf[80];\r
-    \r
-    XtSetArg(args[0], XtNlabel, &name);\r
-    XtGetValues(w, args, 1);\r
-    \r
-    if (strcmp(name, "cancel") == 0) {\r
-        XXXPopDown();\r
-        return;\r
-    }\r
-    if (strcmp(name, "ok") == 0) {\r
-       int nr; String name;\r
-        name = XawDialogGetValueString(w2 = XtParent(w));\r
-       if(sscanf(name ,"%d",&nr) != 1) {\r
-           sprintf(buf, "%d", appData.defaultFrcPosition);\r
-           XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value\r
-           XtSetValues(w2, args, 1);\r
-           return;\r
-       }\r
-        XXXPopDown();\r
-        return;\r
-    }\r
-}\r
-\r
-void XXXPopUp()\r
-{\r
-    Arg args[16];\r
-    Widget popup, layout, dialog, edit;\r
-    Window root, child;\r
-    int x, y, i;\r
-    int win_x, win_y;\r
-    unsigned int mask;\r
-    char def[80];\r
-    \r
-    i = 0;\r
-    XtSetArg(args[i], XtNresizable, True); i++;\r
-    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;\r
-    XXXShell = popup =\r
-      XtCreatePopupShell("XXX Menu", transientShellWidgetClass,\r
-                        shellWidget, args, i);\r
-    \r
-    layout =\r
-      XtCreateManagedWidget(layoutName, formWidgetClass, popup,\r
-                           layoutArgs, XtNumber(layoutArgs));\r
-  \r
-    sprintf(def, "%d\n", appData.defaultFrcPosition);\r
-    i = 0;\r
-    XtSetArg(args[i], XtNlabel, ""); i++;\r
-    XtSetArg(args[i], XtNvalue, def); i++;\r
-    XtSetArg(args[i], XtNborderWidth, 0); i++;\r
-    dialog = XtCreateManagedWidget("XXX", dialogWidgetClass,\r
-                                  layout, args, i);\r
-    \r
-    XawDialogAddButton(dialog, "ok", XXXCallback, (XtPointer) dialog);\r
-    XawDialogAddButton(dialog, "cancel", XXXCallback, (XtPointer) dialog);\r
-    \r
-    XtRealizeWidget(popup);\r
-    CatchDeleteWindow(popup, "XXXPopDown");\r
-    \r
-    XQueryPointer(xDisplay, xBoardWindow, &root, &child,\r
-                 &x, &y, &win_x, &win_y, &mask);\r
-    \r
-    XtSetArg(args[0], XtNx, x - 10);\r
-    XtSetArg(args[1], XtNy, y - 30);\r
-    XtSetValues(popup, args, 2);\r
-    \r
-    XtPopup(popup, XtGrabExclusive);\r
-    XXXUp = True;\r
-    \r
-    edit = XtNameToWidget(dialog, "*value");\r
-\r
-    previous = NULL;\r
-    SetFocus(engThreshold, popup, (XEvent*) NULL, False);\r
-}\r
-\r
-void XXXMenuProc(w, event, prms, nprms)\r
-     Widget w;\r
-     XEvent *event;\r
-     String *prms;\r
-     Cardinal *nprms;\r
-{\r
-   XXXPopUp();\r
-}\r
-#endif\r
-\r
+}      \r
+\r
+void SettingsPopUp(ChessProgramState *cps)
+{
+    Arg args[16];
+    Widget popup, layout, dialog, edit, form, oldform, last, b_ok, b_cancel;
+    Window root, child;
+    int x, y, i, j;
+    int win_x, win_y;
+    unsigned int mask;
+    char def[80], *p, *q;
+
+    // to do: start up second engine if needed
+    if(!cps->initDone || !cps->nrOptions) return; // nothing to be done
+    currentCps = cps;
+
+    i = 0;
+    XtSetArg(args[i], XtNresizable, True); i++;
+    SettingsShell = popup =
+      XtCreatePopupShell("Settings Menu", transientShellWidgetClass,
+                        shellWidget, args, i);
+    
+    layout =
+      XtCreateManagedWidget(layoutName, formWidgetClass, popup,
+                           layoutArgs, XtNumber(layoutArgs));
+  
+    form =
+      XtCreateManagedWidget(layoutName, formWidgetClass, layout,
+                           formArgs, XtNumber(formArgs));
+  
+    last = NULL;
+    for(i=0; i<cps->nrOptions; i++) {
+       Widget box;
+       switch(cps->option[i].type) {
+         case Spin:
+           sprintf(def, "%d", cps->option[i].value);
+         case TextBox:
+           j=0;
+           XtSetArg(args[j], XtNfromVert, last);  j++;
+           XtSetArg(args[j], XtNborderWidth, 0);  j++;
+           XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
+           dialog = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j);   
+           j=0;
+           XtSetArg(args[j], XtNfromVert, last);  j++;
+           XtSetArg(args[j], XtNfromHoriz, dialog);  j++;
+           XtSetArg(args[j], XtNborderWidth, 1); j++;
+           XtSetArg(args[j], XtNwidth, cps->option[i].type == Spin ? 40 : 100); j++;
+           XtSetArg(args[j], XtNeditType, XawtextEdit);  j++;
+           XtSetArg(args[j], XtNuseStringInPlace, False);  j++;
+           XtSetArg(args[j], XtNdisplayCaret, False);  j++;
+           XtSetArg(args[j], XtNright, XtChainRight);  j++;
+           XtSetArg(args[j], XtNresizable, True);  j++;
+           XtSetArg(args[j], XtNstring, cps->option[i].type==Spin ? def : cps->option[i].textValue);  j++;
+           edit = last;
+           cps->option[i].handle = (void*)
+               (last = XtCreateManagedWidget("text", asciiTextWidgetClass, form, args, j));   
+           XtAddEventHandler(box, ButtonPressMask, False, SetFocus, (XtPointer) popup);
+           if(cps->option[i].type == TextBox) break;
+           // add increment and decrement controls for spin
+           j=0;
+           XtSetArg(args[j], XtNfromVert, edit);  j++;
+           XtSetArg(args[j], XtNfromHoriz, box);  j++;
+           XtSetArg(args[j], XtNheight, 10);  j++;
+           XtSetArg(args[j], XtNwidth, 20);  j++;
+           edit = XtCreateManagedWidget("+", commandWidgetClass, form, args, j);
+           XtAddCallback(edit, XtNcallback, SpinCallback, (XtPointer) i);
+           j=0;
+           XtSetArg(args[j], XtNfromVert, edit);  j++;
+           XtSetArg(args[j], XtNfromHoriz, last);  j++;
+           XtSetArg(args[j], XtNheight, 10);  j++;
+           XtSetArg(args[j], XtNwidth, 20);  j++;
+           last = XtCreateManagedWidget("-", commandWidgetClass, form, args, j);
+           XtAddCallback(last, XtNcallback, SpinCallback, (XtPointer) i);
+           break;
+         case CheckBox:
+           j=0;
+           XtSetArg(args[j], XtNfromVert, last);  j++;
+           XtSetArg(args[j], XtNwidth, 10);  j++;
+           XtSetArg(args[j], XtNheight, 10);  j++;
+           XtSetArg(args[j], XtNstate, cps->option[i].value);  j++;
+           cps->option[i].handle = (void*) 
+               (dialog = XtCreateManagedWidget(" ", toggleWidgetClass, form, args, j));   
+           j=0;
+           XtSetArg(args[j], XtNfromVert, last);  j++;
+           XtSetArg(args[j], XtNfromHoriz, dialog);  j++;
+           XtSetArg(args[j], XtNborderWidth, 0);  j++;
+           XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
+           last = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j);
+           break;
+         case SaveButton:
+         case Button:
+           j=0;
+           XtSetArg(args[j], XtNfromVert, last);  j++;
+           XtSetArg(args[j], XtNstate, cps->option[i].value);  j++;
+           cps->option[i].handle = (void*) 
+               (last = XtCreateManagedWidget(cps->option[i].name, commandWidgetClass, form, args, j));   
+           XtAddCallback(last, XtNcallback, SettingsCallback, (XtPointer) (cps->option[i].type == SaveButton));
+           break;
+         case ComboBox:
+           j=0;
+           XtSetArg(args[j], XtNfromVert, last);  j++;
+           XtSetArg(args[j], XtNborderWidth, 0);  j++;
+           XtSetArg(args[j], XtNjustify, XtJustifyLeft);  j++;
+           dialog = XtCreateManagedWidget(cps->option[i].name, labelWidgetClass, form, args, j);
+
+           j=0;
+           XtSetArg(args[j], XtNfromVert, last);  j++;
+           XtSetArg(args[j], XtNfromHoriz, dialog);  j++;
+           XtSetArg(args[j], XtNwidth, 100);  j++;
+           XtSetArg(args[j], XtNmenuName, XtNewString(cps->option[i].name));  j++;
+           XtSetArg(args[j], XtNlabel, ((char**)cps->option[i].textValue)[cps->option[i].value]);  j++;
+           cps->option[i].handle = (void*) 
+               (last = XtCreateManagedWidget(" ", menuButtonWidgetClass, form, args, j));   
+           CreateComboPopup(last, cps->option[i].name, i, (char **) cps->option[i].textValue);
+           values[i] = cps->option[i].value;
+           break;
+       }
+    }
+
+    j=0;
+    XtSetArg(args[j], XtNfromVert, last);  j++;
+    XtSetArg(args[j], XtNbottom, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNtop, XtChainBottom);  j++;
+    XtSetArg(args[j], XtNleft, XtChainLeft);  j++;
+    XtSetArg(args[j], XtNright, XtChainLeft);  j++;
+    b_ok = XtCreateManagedWidget("OK", commandWidgetClass, form, args, j);   
+    XtAddCallback(b_ok, XtNcallback, SettingsCallback, (XtPointer) 0);
+
+    XtSetArg(args[j], XtNfromHoriz, b_ok);  j++;
+    b_cancel = XtCreateManagedWidget("cancel", commandWidgetClass, form, args, j);   
+    XtAddCallback(b_cancel, XtNcallback, SettingsPopDown, (XtPointer) 0);
+
+    XtRealizeWidget(popup);
+    CatchDeleteWindow(popup, "SettingsPopDown");
+    
+    XQueryPointer(xDisplay, xBoardWindow, &root, &child,
+                 &x, &y, &win_x, &win_y, &mask);
+    
+    XtSetArg(args[0], XtNx, x - 10);
+    XtSetArg(args[1], XtNy, y - 30);
+    XtSetValues(popup, args, 2);
+    
+    XtPopup(popup, XtGrabExclusive);
+    SettingsUp = True;
+
+    previous = NULL;
+    SetFocus(edit, popup, (XEvent*) NULL, False);
+}
+
+void FirstSettingsProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+   SettingsPopUp(&first);
+}
+
+void SecondSettingsProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+   SettingsPopUp(&second);
+}
+
+//--------------------------- General Popup for Cloning ----------------------------------
+#if 0
+int XXXUp;
+Widget XXXShell;
+
+void XXXPopDown()
+{
+    if (!XXXUp) return;
+    XtPopdown(XXXShell);
+    XtDestroyWidget(XXXShell);
+    XXXUp = False;
+    ModeHighlight();
+}
+
+void XXXCallback(w, client_data, call_data)
+     Widget w;
+     XtPointer client_data, call_data;
+{
+    String name;
+    Widget w2;
+    Arg args[16];
+    char buf[80];
+    
+    XtSetArg(args[0], XtNlabel, &name);
+    XtGetValues(w, args, 1);
+    
+    if (strcmp(name, "cancel") == 0) {
+        XXXPopDown();
+        return;
+    }
+    if (strcmp(name, "ok") == 0) {
+       int nr; String name;
+        name = XawDialogGetValueString(w2 = XtParent(w));
+       if(sscanf(name ,"%d",&nr) != 1) {
+           sprintf(buf, "%d", appData.defaultFrcPosition);
+           XtSetArg(args[0],XtNvalue, buf); // erase bad (non-numeric) value
+           XtSetValues(w2, args, 1);
+           return;
+       }
+        XXXPopDown();
+        return;
+    }
+}
+
+void XXXPopUp()
+{
+    Arg args[16];
+    Widget popup, layout, dialog, edit;
+    Window root, child;
+    int x, y, i;
+    int win_x, win_y;
+    unsigned int mask;
+    char def[80];
+    
+    i = 0;
+    XtSetArg(args[i], XtNresizable, True); i++;
+    XtSetArg(args[i], XtNwidth, DIALOG_SIZE); i++;
+    XXXShell = popup =
+      XtCreatePopupShell("XXX Menu", transientShellWidgetClass,
+                        shellWidget, args, i);
+    
+    layout =
+      XtCreateManagedWidget(layoutName, formWidgetClass, popup,
+                           layoutArgs, XtNumber(layoutArgs));
+  
+    sprintf(def, "%d\n", appData.defaultFrcPosition);
+    i = 0;
+    XtSetArg(args[i], XtNlabel, ""); i++;
+    XtSetArg(args[i], XtNvalue, def); i++;
+    XtSetArg(args[i], XtNborderWidth, 0); i++;
+    dialog = XtCreateManagedWidget("XXX", dialogWidgetClass,
+                                  layout, args, i);
+    
+    XawDialogAddButton(dialog, "ok", XXXCallback, (XtPointer) dialog);
+    XawDialogAddButton(dialog, "cancel", XXXCallback, (XtPointer) dialog);
+    
+    XtRealizeWidget(popup);
+    CatchDeleteWindow(popup, "XXXPopDown");
+    
+    XQueryPointer(xDisplay, xBoardWindow, &root, &child,
+                 &x, &y, &win_x, &win_y, &mask);
+    
+    XtSetArg(args[0], XtNx, x - 10);
+    XtSetArg(args[1], XtNy, y - 30);
+    XtSetValues(popup, args, 2);
+    
+    XtPopup(popup, XtGrabExclusive);
+    XXXUp = True;
+    
+    edit = XtNameToWidget(dialog, "*value");
+
+    previous = NULL;
+    SetFocus(engThreshold, popup, (XEvent*) NULL, False);
+}
+
+void XXXMenuProc(w, event, prms, nprms)
+     Widget w;
+     XEvent *event;
+     String *prms;
+     Cardinal *nprms;
+{
+   XXXPopUp();
+}
+#endif
+
diff --git a/zippy.c b/zippy.c
index f75ecb2..c77276f 100644 (file)
--- a/zippy.c
+++ b/zippy.c
@@ -88,6 +88,8 @@ extern char *getenv();
 #include "backend.h"\r
 #include "backendz.h"\r
 \r
+char *SendMoveToBookUser P((int nr, ChessProgramState *cps, int initial)); // [HGM] book
+
 static char zippyPartner[MSG_SIZ];\r
 static char zippyLastOpp[MSG_SIZ];\r
 static int zippyConsecGames;\r
@@ -964,7 +966,8 @@ void ZippyFirstBoard(moveNum, basetime, increment)
     char buf[MSG_SIZ];\r
     int w, b;\r
     char *opp = (gameMode==IcsPlayingWhite ? gameInfo.black : gameInfo.white);\r
-    Boolean sentPos = FALSE;\r
+    Boolean sentPos = FALSE;
+    char *bookHit = NULL; // [HGM] book\r
 \r
     if (!first.initDone) {\r
       /* Game is starting prematurely.  We can't deal with this */\r
@@ -1035,7 +1038,7 @@ void ZippyFirstBoard(moveNum, basetime, increment)
                  SendTimeRemaining(&first, TRUE);\r
                }\r
              }\r
-             SendToProgram("go\n", &first);\r
+             bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: send go or retrieve book move\r
            } else {\r
                /* Engine's opponent is on move now */\r
                if (first.usePlayother) {\r
@@ -1061,7 +1064,8 @@ void ZippyFirstBoard(moveNum, basetime, increment)
                  SendTimeRemaining(&first, TRUE);\r
                }\r
              }\r
-             SendToProgram("go\n", &first);\r
+//           SendToProgram("go\n", &first);\r
+             bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: send go or retrieve book move\r
            }\r
        }\r
     } else if (gameMode == IcsPlayingBlack) {\r
@@ -1085,7 +1089,8 @@ void ZippyFirstBoard(moveNum, basetime, increment)
                  SendTimeRemaining(&first, FALSE);\r
                }\r
              }\r
-             SendToProgram("go\n", &first);\r
+//           SendToProgram("go\n", &first);\r
+             bookHit = SendMoveToBookUser(forwardMostMove-1, &first, TRUE); // [HGM] book: send go or retrieve book move\r
            } else {\r
                /* Engine's opponent is on move now */\r
                if (first.usePlayother) {\r
@@ -1103,6 +1108,18 @@ void ZippyFirstBoard(moveNum, basetime, increment)
            /* Nothing needs to be done here */\r
        }       \r
     }\r
+
+    if(bookHit) { // [HGM] book: simulate book reply
+       static char bookMove[MSG_SIZ]; // a bit generous?
+
+       programStats.depth = programStats.nodes = programStats.time = 
+       programStats.score = programStats.got_only_move = 0;
+       sprintf(programStats.movelist, "%s (xbook)", bookHit);
+
+       strcpy(bookMove, "move ");
+       strcat(bookMove, bookHit);
+       HandleMachineMove(bookMove, &first);
+    }
 }\r
 \r
 \r