Describe divide-by-60 option of TC dialog in texi file
[xboard.git] / winboard / jaws.c
index d3856ae..aa843ad 100644 (file)
@@ -1,11 +1,12 @@
 /*\r
  * JAWS.c -- Code for Windows front end to XBoard to use it with JAWS\r
- * $Id: winboard.c,v 2.3 2003/11/25 05:25:20 mann Exp $\r
  *\r
  * Copyright 1991 by Digital Equipment Corporation, Maynard,\r
- * Massachusetts.  Enhancements Copyright\r
- * 1992-2001,2002,2003,2004,2005,2006,2007,2008,2009 Free Software\r
- * Foundation, Inc.\r
+ * Massachusetts.\r
+ *\r
+ * Enhancements Copyright 1992-2001, 2002, 2003, 2004, 2005, 2006,\r
+ * 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016 Free\r
+ * Software Foundation, Inc.\r
  *\r
  * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,\r
  * which was written and is copyrighted by Wayne Christopher.\r
 // BOARD_LEFT as 0, BOARD_RGHT and BOARD_HEIGHT as 8, and set holdingssizes to 0.\r
 // You will need to build with jaws.rc in stead of winboard.rc.\r
 \r
-// from common.h, but 'extern' added to it, so the actual declaraton can remain in backend.c\r
-\r
-extern long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement;\r
+// from resource.h\r
+\r
+#define IDM_PossibleAttackMove          1800\r
+#define IDM_PossibleAttacked            1801\r
+#define IDM_SayMachineMove              1802\r
+#define IDM_ReadRow                     1803\r
+#define IDM_ReadColumn                  1804\r
+#define IDM_SayCurrentPos               1805\r
+#define IDM_SayAllBoard                 1806\r
+#define IDM_SayUpperDiagnols            1807\r
+#define IDM_SayLowerDiagnols            1808\r
+#define IDM_SayClockTime                1810\r
+#define IDM_SayWhosTurn                 1811\r
+#define IDM_SayKnightMoves              1812\r
+#define ID_SHITTY_HI                    1813\r
+#define IDM_SayWhitePieces              1816\r
+#define IDM_SayBlackPieces              1817\r
 \r
-#if 0\r
-// from moves.h, but no longer needed, as the new routines are all moved to winboard.c\r
 \r
-extern char* PieceToName P((ChessSquare p, int i));\r
-extern char* SquareToChar P((int Xpos)); \r
-extern char* SquareToNum P((int Ypos));\r
-extern int CoordToNum P((char c));\r
+// from common.h, but 'extern' added to it, so the actual declaraton can remain in backend.c\r
 \r
-#endif\r
+extern long whiteTimeRemaining, blackTimeRemaining, timeControl, timeIncrement;\r
 \r
 // from moves.c, added WinBoard_F piece types and ranks / files\r
 \r
@@ -83,7 +93,7 @@ char *squareToNum[] = {"naught", "1", "2", "3", "4", "5", "6", "7", "8", "9" };
 char *ordinals[] = {"zeroth", "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "nineth"};\r
 \r
 char *pieceToName[] = {\r
-               "White Pawn", "White Knight", "White Bishop", "White Rook", "White Queen", \r
+               "White Pawn", "White Knight", "White Bishop", "White Rook", "White Queen",\r
                "White Guard", "White Elephant", "White Arch Bishop", "White Chancellor",\r
                "White General", "White Man", "White Cannon", "White Night Rider",\r
                "White Crowned Bishop", "White Crowned Rook", "White Grass Hopper", "White Veteran",\r
@@ -98,6 +108,22 @@ char *pieceToName[] = {
                "Empty"\r
        };\r
 \r
+char *pieceTypeName[] = {\r
+               "Pawn", "Knight", "Bishop", "Rook", "Queen",\r
+               "Guard", "Elephant", "Arch Bishop", "Chancellor",\r
+               "General", "Man", "Cannon", "Night Rider",\r
+               "Crowned Bishop", "Crowned Rook", "Grass Hopper", "Veteran",\r
+               "Falcon", "Amazon", "Snake", "Unicorn",\r
+               "King",\r
+               "Pawn", "Knight", "Bishop", "Rook", "Queen",\r
+               "Guard", "Elephant", "Arch Bishop", "Chancellor",\r
+               "General", "Man", "Cannon", "Night Rider",\r
+               "Crowned Bishop", "Crowned Rook", "Grass Hopper", "Veteran",\r
+               "Falcon", "Amazon", "Snake", "Unicorn",\r
+               "King",\r
+               "Empty"\r
+       };\r
+\r
 int CoordToNum(c)\r
                char c;\r
 {\r
@@ -111,7 +137,7 @@ char* PieceToName(p, i)
        int i;\r
 {\r
        if(i) return pieceToName[(int) p];\r
-               return pieceToName[(int) p]+6;\r
+               return pieceTypeName[(int) p];\r
 }\r
 \r
 char* SquareToChar(x)\r
@@ -128,9 +154,8 @@ char* SquareToNum(y)
 \r
 \r
 // from winboard.c: all new routines\r
-\r
-#include "jfwapi.h"\r
-#include "jaws.h"\r
+#define JFWAPI __declspec(dllimport)\r
+JFWAPI BOOL WINAPI JFWSayString (LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);\r
 \r
 typedef JFWAPI BOOL (WINAPI *PSAYSTRING)(LPCTSTR lpszStrinToSpeak, BOOL bInterrupt);\r
 \r
@@ -138,15 +163,20 @@ PSAYSTRING RealSayString;
 \r
 VOID SayString(char *mess, BOOL flag)\r
 { // for debug file\r
-       char buf[MSG_SIZ], *p;\r
+       static char buf[8000], *p;\r
+        int l = strlen(buf);\r
        if(appData.debugMode) fprintf(debugFP, "SAY '%s'\n", mess);\r
-       strcpy(buf, mess);\r
+        if(l) buf[l++] = ' '; // separate by space from previous\r
+       safeStrCpy(buf+l, _(mess), 8000-1-l); // buffer\r
+        if(!flag) return; // wait for flush\r
        if(p = StrCaseStr(buf, "Xboard adjudication:")) {\r
                int i;\r
                for(i=19; i>1; i--) p[i] = p[i-1];\r
                p[1] = ' ';\r
        }\r
-       RealSayString(buf, flag);\r
+       RealSayString(buf, !strcmp(mess, " ")); // kludge to indicate flushing of interruptable speach\r
+       if(appData.debugMode) fprintf(debugFP, "SPEAK '%s'\n", buf);\r
+       buf[0] = NULLCHAR;\r
 }\r
 \r
 //static int fromX = 0, fromY = 0;\r
@@ -154,13 +184,77 @@ static int oldFromX, oldFromY;
 static int timeflag;\r
 static int suppressClocks = 0;\r
 static int suppressOneKey = 0;\r
+static HANDLE hAccelJAWS;\r
+\r
+typedef struct { char *name; int code; } MenuItemDesc;\r
+\r
+MenuItemDesc menuItemJAWS[] = {\r
+{"Say Clock &Time\tAlt+T",      IDM_SayClockTime },\r
+{"-", 0 },\r
+{"Say Last &Move\tAlt+M",       IDM_SayMachineMove },\r
+{"Say W&ho's Turn\tAlt+X",      IDM_SayWhosTurn },\r
+{"-", 0 },\r
+{"Say Complete &Position\tAlt+P",IDM_SayAllBoard },\r
+{"Say &White Pieces\tAlt+W",    IDM_SayWhitePieces },\r
+{"Say &Black Pieces\tAlt+B",    IDM_SayBlackPieces },\r
+{"Say Board &Rank\tAlt+R",      IDM_ReadRow },\r
+{"Say Board &File\tAlt+F",      IDM_ReadColumn },\r
+{"-", 0 },\r
+{"Say &Upper Diagonals\tAlt+U",  IDM_SayUpperDiagnols },\r
+{"Say &Lower Diagonals\tAlt+L",  IDM_SayLowerDiagnols },\r
+{"Say K&night Moves\tAlt+N",    IDM_SayKnightMoves },\r
+{"Say Current &Square\tAlt+S",  IDM_SayCurrentPos },\r
+{"Say &Attacks\tAlt+A",         IDM_PossibleAttackMove },\r
+{"Say Attacke&d\tAlt+D",        IDM_PossibleAttacked },\r
+{NULL, 0}\r
+};\r
+\r
+ACCEL acceleratorsJAWS[] = {\r
+{FVIRTKEY|FALT, 'T', IDM_SayClockTime },\r
+{FVIRTKEY|FALT, 'M', IDM_SayMachineMove },\r
+{FVIRTKEY|FALT, 'X', IDM_SayWhosTurn },\r
+{FVIRTKEY|FALT, 'P', IDM_SayAllBoard },\r
+{FVIRTKEY|FALT, 'W', IDM_SayWhitePieces },\r
+{FVIRTKEY|FALT, 'B', IDM_SayBlackPieces },\r
+{FVIRTKEY|FALT, 'R', IDM_ReadRow },\r
+{FVIRTKEY|FALT, 'F', IDM_ReadColumn },\r
+{FVIRTKEY|FALT, 'U', IDM_SayUpperDiagnols },\r
+{FVIRTKEY|FALT, 'L', IDM_SayLowerDiagnols },\r
+{FVIRTKEY|FALT, 'N', IDM_SayKnightMoves },\r
+{FVIRTKEY|FALT, 'S', IDM_SayCurrentPos },\r
+{FVIRTKEY|FALT, 'A', IDM_PossibleAttackMove },\r
+{FVIRTKEY|FALT, 'D', IDM_PossibleAttacked }\r
+};\r
+\r
+void\r
+AdaptMenu()\r
+{\r
+       HMENU menuMain, menuJAWS;\r
+       MENUBARINFO helpMenuInfo;\r
+       int i;\r
+\r
+       helpMenuInfo.cbSize = sizeof(helpMenuInfo);\r
+       menuMain = GetMenu(hwndMain);\r
+       menuJAWS = CreatePopupMenu();\r
+\r
+       for(i=0; menuItemJAWS[i].name; i++) {\r
+           if(menuItemJAWS[i].name[0] == '-')\r
+                AppendMenu(menuJAWS, MF_SEPARATOR, (UINT_PTR) 0, NULL);\r
+           else AppendMenu(menuJAWS, MF_ENABLED|MF_STRING,\r
+                       (UINT_PTR) menuItemJAWS[i].code, (LPCTSTR) _(menuItemJAWS[i].name));\r
+       }\r
+       InsertMenu(menuMain, 7, MF_BYPOSITION|MF_POPUP|MF_ENABLED|MF_STRING,\r
+               (UINT_PTR) menuJAWS, "&JAWS");\r
+       oldMenuItemState[8] = oldMenuItemState[7];\r
+       DrawMenuBar(hwndMain);\r
+}\r
 \r
 BOOL\r
 InitJAWS()\r
 {      // to be called at beginning of WinMain, after InitApplication and InitInstance\r
        HINSTANCE hApi = LoadLibrary("jfwapi32.dll");\r
        if(!hApi) {\r
-               DisplayInformation("Missing jfwapi32.dll");        \r
+               DisplayInformation("Missing jfwapi32.dll");\r
                return (FALSE);\r
        }\r
 \r
@@ -171,20 +265,17 @@ InitJAWS()
        }\r
 \r
        {\r
-               // [HGM] kludge to reduce need for modification of winboard.c: mak tinyLayout menu identical\r
+               // [HGM] kludge to reduce need for modification of winboard.c: make tinyLayout menu identical\r
                // to standard layout, so that code for switching between them does not have to be deleted\r
-               HMENU hmenu = GetMenu(hwndMain);\r
                int i;\r
 \r
-               menuBarText[0][5] = "&JAWS";\r
-               for(i=0; i<7; i++) menuBarText[1][i] = menuBarText[0][i];\r
-               for (i=0; menuBarText[tinyLayout][i]; i++) {\r
-                       ModifyMenu(hmenu, i, MF_STRING|MF_BYPOSITION|MF_POPUP, \r
-                                       (UINT)GetSubMenu(hmenu, i), menuBarText[tinyLayout][i]);\r
-               }\r
-               DrawMenuBar(hwndMain);\r
+               AdaptMenu();\r
+               menuBarText[0][8] = menuBarText[0][7]; menuBarText[0][7] = "&JAWS";\r
+               for(i=0; i<9; i++) menuBarText[2][i] = menuBarText[1][i] = menuBarText[0][i];\r
        }\r
 \r
+       hAccelJAWS = CreateAcceleratorTable(acceleratorsJAWS, 14);\r
+\r
        /* initialize cursor position */\r
        fromX = fromY = 0;\r
        SetHighlights(fromX, fromY, -1, -1);\r
@@ -195,73 +286,85 @@ InitJAWS()
        return TRUE;\r
 }\r
 \r
+int beeps[] = { 1, 0, 0, 0, 0 };\r
+int beepCodes[] = { 0, MB_OK, MB_ICONERROR, MB_ICONQUESTION, MB_ICONEXCLAMATION, MB_ICONASTERISK };\r
+static int dropX = -1, dropY = -1;\r
+\r
 VOID\r
 KeyboardEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
 {\r
        ChessSquare currentPiece;\r
        char *piece, *xchar, *ynum ;\r
-       int n;\r
+       int n, beepType = 1; // empty beep\r
 \r
+       if(fromX == -1 || fromY == -1) { // if we just dropped piece, stay at that square\r
+               fromX = dropX; fromY = dropY;\r
+               dropX = dropY = -1; // but only once\r
+        }\r
        if(fromX == -1 || fromY == -1) {\r
                fromX = BOARD_LEFT; fromY = 0;\r
         }\r
        switch(wParam) {\r
        case VK_LEFT:\r
                if(fromX == BOARD_RGHT+1) fromX -= 2; else\r
-               if(fromX == BOARD_LEFT) { if(fromY >= BOARD_HEIGHT - gameInfo.holdingsSize) fromX -= 2; } else\r
-               if(fromX > BOARD_LEFT) fromX--;\r
+               if(fromX == BOARD_LEFT) { if(fromY >= BOARD_HEIGHT - gameInfo.holdingsSize) fromX -= 2; else beepType = 0; } else\r
+               if(fromX > BOARD_LEFT) fromX--; else beepType = 0; // off-board beep\r
                break;\r
        case VK_RIGHT:\r
                if(fromX == BOARD_LEFT-2) fromX += 2; else\r
-               if(fromX == BOARD_RGHT-1) { if(fromY < gameInfo.holdingsSize) fromX += 2; } else\r
-               if(fromX < BOARD_RGHT-1) fromX++;\r
+               if(fromX == BOARD_RGHT-1) { if(fromY < gameInfo.holdingsSize) fromX += 2; else beepType = 0; } else\r
+               if(fromX < BOARD_RGHT-1) fromX++; else beepType = 0;\r
                break;\r
        case VK_UP:\r
-               if(fromX == BOARD_RGHT+1) { if(fromY < gameInfo.holdingsSize - 1) fromY++; } else\r
-               if(fromY < BOARD_HEIGHT-1) fromY++;\r
+               if(fromX == BOARD_RGHT+1) { if(fromY < gameInfo.holdingsSize - 1) fromY++; else beepType = 0; } else\r
+               if(fromY < BOARD_HEIGHT-1) fromY++; else beepType = 0;\r
                break;\r
        case VK_DOWN:\r
-               if(fromX == BOARD_LEFT-2) { if(fromY > BOARD_HEIGHT - gameInfo.holdingsSize) fromY--; } else\r
-               if(fromY > 0) fromY--;\r
+               if(fromX == BOARD_LEFT-2) { if(fromY > BOARD_HEIGHT - gameInfo.holdingsSize) fromY--; else beepType = 0; } else\r
+               if(fromY > 0) fromY--; else beepType = 0;\r
                break;\r
        }\r
        SetHighlights(fromX, fromY, -1, -1);\r
        DrawPosition(FALSE, NULL);\r
        currentPiece = boards[currentMove][fromY][fromX];\r
        piece = PieceToName(currentPiece,1);\r
-       if(currentPiece != EmptySquare) MessageBeep(currentPiece < (int)BlackPawn ? MB_OK : MB_ICONEXCLAMATION);\r
+       if(beepType == 1 && currentPiece != EmptySquare) beepType = currentPiece < (int) BlackPawn ? 2 : 3; // white or black beep\r
+       if(beeps[beepType] == beeps[1] && (fromX == BOARD_RGHT+1 || fromX == BOARD_LEFT-2)) beepType = 4; // holdings beep\r
+       beepType = beeps[beepType]%6;\r
+       if(beepType) MessageBeep(beepCodes[beepType]);\r
        if(fromX == BOARD_LEFT - 2) {\r
                SayString("black holdings", FALSE);\r
                if(currentPiece != EmptySquare) {\r
                        char buf[MSG_SIZ];\r
                        n = boards[currentMove][fromY][1];\r
-                       sprintf(buf, "%d %s%s", n, piece+6, n == 1 ? "" : "s");\r
-                       SayString(buf, TRUE);\r
+                       snprintf(buf, MSG_SIZ, "%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");\r
+                       SayString(buf, FALSE);\r
                }\r
+               SayString(" ", TRUE);\r
        } else\r
        if(fromX == BOARD_RGHT + 1) {\r
                SayString("white holdings", FALSE);\r
                if(currentPiece != EmptySquare) {\r
                        char buf[MSG_SIZ];\r
                        n = boards[currentMove][fromY][BOARD_WIDTH-2];\r
-                       sprintf(buf, "%d %s%s", n, piece+6, n == 1 ? "" : "s");\r
-                       SayString(buf, TRUE);\r
+                       snprintf(buf, MSG_SIZ,"%d %s%s", n, PieceToName(currentPiece,0), n == 1 ? "" : "s");\r
+                       SayString(buf, FALSE);\r
                }\r
+               SayString(" ", TRUE);\r
        } else\r
        if(fromX >= BOARD_LEFT && fromX < BOARD_RGHT) {\r
                char buf[MSG_SIZ];\r
                xchar = SquareToChar(fromX);\r
                ynum = SquareToNum(fromY);\r
                if(currentPiece != EmptySquare) {\r
-//                     SayString(piece[0] == 'W' ? "white" : "black", TRUE);\r
-                       sprintf(buf, "%s %s %s", piece, xchar, ynum);\r
-               } else sprintf(buf, "%s %s", xchar, ynum);\r
-               SayString(buf, TRUE);\r
+                 snprintf(buf, MSG_SIZ, "%s %s %s", xchar, ynum, piece);\r
+               } else snprintf(buf, MSG_SIZ, "%s %s", xchar, ynum);\r
+               SayString(buf, FALSE);\r
+               SayString(" ", TRUE);\r
        }\r
        return;\r
 }\r
 \r
-extern char castlingRights[MAX_MOVES][BOARD_SIZE];\r
 int PosFlags(int nr);\r
 \r
 typedef struct {\r
@@ -319,7 +422,7 @@ PossibleAttackMove()
 \r
 //if(appData.debugMode) fprintf(debugFP, "PossibleAttackMove %d %d %d %d\n", fromX, fromY, oldFromX, oldFromY);\r
        if(fromY < 0 || fromY >= BOARD_HEIGHT) return;\r
-       if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }\r
+       if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",TRUE); return; }\r
 \r
        piece = boards[currentMove][fromY][fromX];\r
        if(piece == EmptySquare) { // if square is empty, try to substitute selected piece\r
@@ -330,7 +433,7 @@ PossibleAttackMove()
                SayString("Your", FALSE);\r
                SayString(PieceToName(piece, 0), FALSE);\r
                SayString("would have", FALSE);\r
-           } else { SayString("You must select a piece first", FALSE); return; }\r
+           } else { SayString("You must select a piece first", TRUE); return; }\r
        }\r
 \r
        victim = boards[currentMove][fromY][fromX];\r
@@ -340,9 +443,9 @@ PossibleAttackMove()
        swapColor = piece <  (int)BlackPawn && !WhiteOnMove(currentMove) ||\r
                    piece >= (int)BlackPawn &&  WhiteOnMove(currentMove);\r
        cl.count = 0; cl.rf = fromY; cl.ff = fromX; cl.rt = cl.ft = -1;\r
-       GenLegal(boards[currentMove], PosFlags(currentMove + swapColor), EP_NONE, \r
-                                               castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);\r
+       GenLegal(boards[currentMove], PosFlags(currentMove + swapColor), ReadCallback, (VOIDSTAR) &cl);\r
        if(cl.count == 0) SayString("None", FALSE);\r
+       SayString("", TRUE); // flush\r
        boards[currentMove][fromY][fromX] = victim; // repair\r
 \r
        if( removedSelectedPiece ) boards[currentMove][oldFromY][oldFromX] = piece;\r
@@ -356,7 +459,7 @@ PossibleAttacked()
        ChessSquare piece = EmptySquare, victim;\r
 \r
        if(fromY < 0 || fromY >= BOARD_HEIGHT) return;\r
-       if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",FALSE); return; }\r
+       if(fromX < BOARD_LEFT || fromX >= BOARD_RGHT) { SayString("holdings",TRUE); return; }\r
 \r
        if(oldFromX >= 0 && oldFromY >= 0) { // if piece is selected, remove it\r
                piece = boards[currentMove][oldFromY][oldFromX];\r
@@ -368,17 +471,16 @@ PossibleAttacked()
        victim = boards[currentMove][fromY][fromX]; // put dummy piece on target square, to activate Pawn captures\r
        boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? WhiteQueen : BlackQueen;\r
        cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;\r
-       GenLegal(boards[currentMove], PosFlags(currentMove+1), EP_NONE, \r
-                                               castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);\r
+       GenLegal(boards[currentMove], PosFlags(currentMove+1), ReadCallback, (VOIDSTAR) &cl);\r
        if(cl.count == 0) SayString("None", FALSE);\r
 \r
        SayString("You are defended by", FALSE);\r
 \r
        boards[currentMove][fromY][fromX] = WhiteOnMove(currentMove) ? BlackQueen : WhiteQueen;\r
        cl.count = 0; cl.rt = fromY; cl.ft = fromX; cl.rf = cl.ff = -1;\r
-       GenLegal(boards[currentMove], PosFlags(currentMove), EP_NONE, \r
-                                               castlingRights[currentMove], ReadCallback, (VOIDSTAR) &cl);\r
+       GenLegal(boards[currentMove], PosFlags(currentMove), ReadCallback, (VOIDSTAR) &cl);\r
        if(cl.count == 0) SayString("None", FALSE);\r
+       SayString("", TRUE); // flush\r
        boards[currentMove][fromY][fromX] = victim; // put back original occupant\r
 \r
        if(oldFromX >= 0 && oldFromY >= 0) { // put back possibl selected piece\r
@@ -389,15 +491,15 @@ PossibleAttacked()
 VOID\r
 ReadRow()\r
 {\r
-       ChessSquare currentpiece; \r
+       ChessSquare currentpiece;\r
        char *piece, *xchar, *ynum ;\r
        int xPos, count=0;\r
        ynum = SquareToNum(fromY);\r
-       \r
+\r
        if(fromY < 0) return;\r
 \r
        for (xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {\r
-               currentpiece = boards[currentMove][fromY][xPos];        \r
+               currentpiece = boards[currentMove][fromY][xPos];\r
                if(currentpiece != EmptySquare) {\r
                        piece = PieceToName(currentpiece,1);\r
                        xchar = SquareToChar(xPos);\r
@@ -412,20 +514,21 @@ ReadRow()
                SayString(ynum, FALSE);\r
                SayString("empty", FALSE);\r
        }\r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
 ReadColumn()\r
 {\r
-       ChessSquare currentpiece; \r
+       ChessSquare currentpiece;\r
        char *piece, *xchar, *ynum ;\r
        int yPos, count=0;\r
        xchar = SquareToChar(fromX);\r
-       \r
+\r
        if(fromX < 0) return;\r
 \r
        for (yPos=0; yPos<BOARD_HEIGHT; yPos++) {\r
-               currentpiece = boards[currentMove][yPos][fromX];        \r
+               currentpiece = boards[currentMove][yPos][fromX];\r
                if(currentpiece != EmptySquare) {\r
                        piece = PieceToName(currentpiece,1);\r
                        ynum = SquareToNum(yPos);\r
@@ -439,15 +542,16 @@ ReadColumn()
                SayString(xchar, FALSE);\r
                SayString("file empty", FALSE);\r
        }\r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
 SayUpperDiagnols()\r
 {\r
-       ChessSquare currentpiece; \r
+       ChessSquare currentpiece;\r
        char *piece, *xchar, *ynum ;\r
        int yPos, xPos;\r
-       \r
+\r
        if(fromX < 0 || fromY < 0) return;\r
 \r
        if(fromX < BOARD_RGHT-1 && fromY < BOARD_HEIGHT-1) {\r
@@ -455,7 +559,7 @@ SayUpperDiagnols()
                yPos = fromY+1;\r
                xPos = fromX+1;\r
                while(yPos<BOARD_HEIGHT && xPos<BOARD_RGHT) {\r
-                       currentpiece = boards[currentMove][yPos][xPos]; \r
+                       currentpiece = boards[currentMove][yPos][xPos];\r
                        piece = PieceToName(currentpiece,1);\r
                        xchar = SquareToChar(xPos);\r
                        ynum = SquareToNum(yPos);\r
@@ -473,7 +577,7 @@ SayUpperDiagnols()
                yPos = fromY+1;\r
                xPos = fromX-1;\r
                while(yPos<BOARD_HEIGHT && xPos>=BOARD_LEFT) {\r
-                       currentpiece = boards[currentMove][yPos][xPos]; \r
+                       currentpiece = boards[currentMove][yPos][xPos];\r
                        piece = PieceToName(currentpiece,1);\r
                        xchar = SquareToChar(xPos);\r
                        ynum = SquareToNum(yPos);\r
@@ -485,15 +589,16 @@ SayUpperDiagnols()
                }\r
        }\r
        else SayString("There is no squares to your upper left", FALSE);\r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
 SayLowerDiagnols()\r
 {\r
-       ChessSquare currentpiece; \r
+       ChessSquare currentpiece;\r
        char *piece, *xchar, *ynum ;\r
        int yPos, xPos;\r
-       \r
+\r
        if(fromX < 0 || fromY < 0) return;\r
 \r
        if(fromX < BOARD_RGHT-1 && fromY > 0) {\r
@@ -501,7 +606,7 @@ SayLowerDiagnols()
                yPos = fromY-1;\r
                xPos = fromX+1;\r
                while(yPos>=0 && xPos<BOARD_RGHT) {\r
-                       currentpiece = boards[currentMove][yPos][xPos]; \r
+                       currentpiece = boards[currentMove][yPos][xPos];\r
                        piece = PieceToName(currentpiece,1);\r
                        xchar = SquareToChar(xPos);\r
                        ynum = SquareToNum(yPos);\r
@@ -519,7 +624,7 @@ SayLowerDiagnols()
                yPos = fromY-1;\r
                xPos = fromX-1;\r
                while(yPos>=0 && xPos>=BOARD_LEFT) {\r
-                       currentpiece = boards[currentMove][yPos][xPos]; \r
+                       currentpiece = boards[currentMove][yPos][xPos];\r
                        piece = PieceToName(currentpiece,1);\r
                        xchar = SquareToChar(xPos);\r
                        ynum = SquareToNum(yPos);\r
@@ -531,16 +636,17 @@ SayLowerDiagnols()
                }\r
        }\r
        else SayString("There is no squares to your lower left", FALSE);\r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
 SayKnightMoves()\r
 {\r
-       ChessSquare currentpiece, oldpiece; \r
+       ChessSquare currentpiece, oldpiece;\r
        char *piece, *xchar, *ynum ;\r
 \r
        oldpiece = boards[currentMove][fromY][fromX];\r
-       if(oldpiece == WhiteKnight || oldpiece == BlackKnight) \r
+       if(oldpiece == WhiteKnight || oldpiece == BlackKnight)\r
                SayString("The possible squares a Knight could move to are", FALSE);\r
        else\r
                SayString("The squares a Knight could possibly attack from are", FALSE);\r
@@ -574,7 +680,7 @@ SayKnightMoves()
                        SayString(piece, FALSE);\r
                }\r
        }\r
-       \r
+\r
        if (fromY+1 < BOARD_HEIGHT && fromX+2 < BOARD_RGHT) {\r
                currentpiece = boards[currentMove][fromY+1][fromX+2];\r
                if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))\r
@@ -589,7 +695,7 @@ SayKnightMoves()
                        SayString(piece, FALSE);\r
                }\r
        }\r
-       \r
+\r
        if (fromY-1 >= 0 && fromX+2 < BOARD_RGHT) {\r
                currentpiece = boards[currentMove][fromY-1][fromX+2];\r
                if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))\r
@@ -604,7 +710,7 @@ SayKnightMoves()
                        SayString(piece, FALSE);\r
                }\r
        }\r
-       \r
+\r
        if (fromY-2 >= 0 && fromX+1 < BOARD_RGHT) {\r
                currentpiece = boards[currentMove][fromY-2][fromX+1];\r
                if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))\r
@@ -619,7 +725,7 @@ SayKnightMoves()
                        SayString(piece, FALSE);\r
                }\r
        }\r
-       \r
+\r
        if (fromY-2 >= 0 && fromX-1 >= BOARD_LEFT) {\r
                currentpiece = boards[currentMove][fromY-2][fromX-1];\r
                if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))\r
@@ -634,7 +740,7 @@ SayKnightMoves()
                        SayString(piece, FALSE);\r
                }\r
        }\r
-       \r
+\r
        if (fromY-1 >= 0 && fromX-2 >= BOARD_LEFT) {\r
                currentpiece = boards[currentMove][fromY-1][fromX-2];\r
                if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))\r
@@ -649,7 +755,7 @@ SayKnightMoves()
                        SayString(piece, FALSE);\r
                }\r
        }\r
-       \r
+\r
        if (fromY+1 < BOARD_HEIGHT && fromX-2 >= BOARD_LEFT) {\r
                currentpiece = boards[currentMove][fromY+1][fromX-2];\r
                if(((oldpiece == WhiteKnight) && (currentpiece > WhiteKing))\r
@@ -664,12 +770,13 @@ SayKnightMoves()
                        SayString(piece, FALSE);\r
                }\r
        }\r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
 SayPieces(ChessSquare p)\r
 {\r
-       ChessSquare currentpiece;  \r
+       ChessSquare currentpiece;\r
        char *piece, *xchar, *ynum ;\r
        int yPos, xPos, count = 0;\r
        char buf[50];\r
@@ -677,13 +784,13 @@ SayPieces(ChessSquare p)
        if(p == WhitePlay)   SayString("White pieces", FALSE); else\r
        if(p == BlackPlay)   SayString("Black pieces", FALSE); else\r
        if(p == EmptySquare) SayString("Pieces", FALSE); else {\r
-               sprintf(buf, "%ss", PieceToName(p,1));\r
+         snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%ss", PieceToName(p,1));\r
                SayString(buf, FALSE);\r
        }\r
        SayString("are located", FALSE);\r
        for(yPos=0; yPos<BOARD_HEIGHT; yPos++) {\r
                for(xPos=BOARD_LEFT; xPos<BOARD_RGHT; xPos++) {\r
-                       currentpiece = boards[currentMove][yPos][xPos]; \r
+                       currentpiece = boards[currentMove][yPos][xPos];\r
                        if(p == BlackPlay && currentpiece >= BlackPawn && currentpiece <= BlackKing ||\r
                           p == WhitePlay && currentpiece >= WhitePawn && currentpiece <= WhiteKing   )\r
                                piece = PieceToName(currentpiece,0);\r
@@ -692,7 +799,7 @@ SayPieces(ChessSquare p)
                        else if(p == currentpiece)\r
                                piece = NULL;\r
                        else continue;\r
-                               \r
+\r
                                if(count == 0) SayString("at", FALSE);\r
                                xchar = SquareToChar(xPos);\r
                                ynum = SquareToNum(yPos);\r
@@ -703,6 +810,7 @@ SayPieces(ChessSquare p)
                }\r
        }\r
        if(count == 0) SayString("nowhere", FALSE);\r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
@@ -712,7 +820,7 @@ SayCurrentPos()
        char *piece, *xchar, *ynum ;\r
        if(fromX <  BOARD_LEFT) { SayString("You strayed into the white holdings", FALSE); return; }\r
        if(fromX >= BOARD_RGHT) { SayString("You strayed into the black holdings", FALSE); return; }\r
-       currentpiece = boards[currentMove][fromY][fromX];       \r
+       currentpiece = boards[currentMove][fromY][fromX];\r
        piece = PieceToName(currentpiece,1);\r
        ynum = SquareToNum(fromY);\r
        xchar = SquareToChar(fromX);\r
@@ -720,13 +828,13 @@ SayCurrentPos()
        SayString(xchar, FALSE);\r
        SayString(ynum, FALSE);\r
        SayString(piece, FALSE);\r
-       if((fromX-BOARD_LEFT) ^ fromY)\r
-               SayString("on a dark square",FALSE);\r
-       else \r
+       if(((fromX-BOARD_LEFT) ^ fromY)&1)\r
                SayString("on a light square",FALSE);\r
+       else\r
+               SayString("on a dark square",FALSE);\r
 \r
        PossibleAttacked();\r
-       return;\r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
@@ -734,29 +842,33 @@ SayAllBoard()
 {\r
        int Xpos, Ypos;\r
        ChessSquare currentpiece;\r
-       char *piece, *xchar, *ynum ;\r
-       \r
+       char *piece, *ynum ;\r
+\r
        if(gameInfo.holdingsWidth) {\r
                int first = 0;\r
                for(Ypos=0; Ypos<gameInfo.holdingsSize; Ypos++) {\r
                        int n = boards[currentMove][Ypos][BOARD_WIDTH-2];\r
-                       if(n) {  char buf[MSG_SIZ];\r
-                               if(!first++) SayString("white holds", FALSE);\r
-                               currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];        \r
-                               piece = PieceToName(currentpiece,0);\r
-                               sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );\r
-                               SayString(buf, FALSE);\r
+                       if(n) {\r
+                         char buf[MSG_SIZ];\r
+                         if(!first++)\r
+                           SayString("white holds", FALSE);\r
+                         currentpiece = boards[currentMove][Ypos][BOARD_WIDTH-1];\r
+                         piece = PieceToName(currentpiece,0);\r
+                         snprintf(buf, MSG_SIZ,"%d %s%s", n, piece, (n==1 ? "" : "s") );\r
+                         SayString(buf, FALSE);\r
                        }\r
                }\r
                first = 0;\r
                for(Ypos=BOARD_HEIGHT-1; Ypos>=BOARD_HEIGHT - gameInfo.holdingsSize; Ypos--) {\r
                        int n = boards[currentMove][Ypos][1];\r
-                       if(n) {  char buf[MSG_SIZ];\r
-                               if(!first++) SayString("black holds", FALSE);\r
-                               currentpiece = boards[currentMove][Ypos][0];    \r
-                               piece = PieceToName(currentpiece,0);\r
-                               sprintf(buf, "%d %s%s", n, piece, (n==1 ? "" : "s") );\r
-                               SayString(buf, FALSE);\r
+                       if(n) {\r
+                         char buf[MSG_SIZ];\r
+                         if(!first++)\r
+                           SayString("black holds", FALSE);\r
+                         currentpiece = boards[currentMove][Ypos][0];\r
+                         piece = PieceToName(currentpiece,0);\r
+                         snprintf(buf, MSG_SIZ, "%d %s%s", n, piece, (n==1 ? "" : "s") );\r
+                         SayString(buf, FALSE);\r
                        }\r
                }\r
        }\r
@@ -766,16 +878,17 @@ SayAllBoard()
                SayString(ynum, FALSE);\r
                SayString("rank", FALSE);\r
                for(Xpos=BOARD_LEFT; Xpos<BOARD_RGHT; Xpos++) {\r
-                       currentpiece = boards[currentMove][Ypos][Xpos]; \r
+                       currentpiece = boards[currentMove][Ypos][Xpos];\r
                        if(currentpiece != EmptySquare) {\r
-                               int count = 0, oldX = Xpos;\r
+                               int count = 0;\r
                                char buf[50];\r
                                piece = PieceToName(currentpiece,1);\r
                                while(Xpos < BOARD_RGHT && boards[currentMove][Ypos][Xpos] == currentpiece)\r
                                        Xpos++, count++;\r
-                               if(count > 1) { \r
-                                       sprintf(buf, "%d %ss", count, piece);\r
-                               } else  sprintf(buf, "%s", piece);\r
+                               if(count > 1)\r
+                                 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%d %ss", count, piece);\r
+                               else\r
+                                 snprintf(buf, sizeof(buf)/sizeof(buf[0]), "%s", piece);\r
                                Xpos--;\r
                                SayString(buf, FALSE);\r
                        } else {\r
@@ -785,9 +898,9 @@ SayAllBoard()
                                if(Xpos == BOARD_RGHT && oldX == BOARD_LEFT)\r
                                        SayString("all", FALSE);\r
                                else{\r
-                                   if(count > 1) { \r
+                                   if(count > 1) {\r
                                        char buf[10];\r
-                                       sprintf(buf, "%d", count);\r
+                                       snprintf(buf, sizeof(buf)/sizeof(buf[0]),"%d", count);\r
                                        SayString(buf, FALSE);\r
                                    }\r
                                    Xpos--;\r
@@ -796,34 +909,36 @@ SayAllBoard()
                        }\r
                }\r
        }\r
-       \r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
 SayWhosTurn()\r
 {\r
-       if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingBlack) {\r
+       if(gameMode == MachinePlaysBlack || gameMode == IcsPlayingWhite) {\r
                if(WhiteOnMove(currentMove))\r
                        SayString("It is your turn", FALSE);\r
                else    SayString("It is your opponents turn", FALSE);\r
-       } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingWhite) {\r
+       } else if(gameMode == MachinePlaysWhite || gameMode == IcsPlayingBlack) {\r
                if(WhiteOnMove(currentMove))\r
                        SayString("It is your opponents turn", FALSE);\r
                else    SayString("It is your turn", FALSE);\r
        } else {\r
-               if(WhiteOnMove(currentMove)) \r
+               if(WhiteOnMove(currentMove))\r
                        SayString("White is on move here", FALSE);\r
                else    SayString("Black is on move here", FALSE);\r
        }\r
+       SayString("", TRUE); // flush\r
 }\r
-       \r
+\r
+extern char *commentList[];\r
 \r
 VOID\r
 SayMachineMove(int evenIfDuplicate)\r
 {\r
        int len, xPos, yPos, moveNr, secondSpace = 0, castle = 0, n;\r
        ChessSquare currentpiece;\r
-       char *piece, *xchar, *ynum, *p;\r
+       char *piece, *xchar, *ynum, *p, checkMark = 0;\r
        char c, buf[MSG_SIZ], comment[MSG_SIZ];\r
        static char disambiguation[2];\r
        static int previousMove = 0;\r
@@ -854,15 +969,15 @@ SayMachineMove(int evenIfDuplicate)
                                    c = 'W'; break;\r
                                  case IcsPlayingBlack:\r
                                  case MachinePlaysBlack:\r
-                                   c = 'B'; \r
+                                   c = 'B';\r
                                  default:\r
                                    break;\r
                                }\r
                            }\r
-                           if(c != lastMover) return; // line is thinking output of future move, ignore.\r
+                           if(c != lastMover && !evenIfDuplicate) return; // line is thinking output of future move, ignore.\r
                            if(2*moveNr - (dotCount < 2) == previousMove)\r
                                return; // do not repeat same move; likely ponder output\r
-                           sprintf(buf, "score %s %d at %d ply", \r
+                           snprintf(buf, MSG_SIZ, "score %s %d at %d ply",\r
                                        score > 0 ? "plus" : score < 0 ? "minus" : "",\r
                                        (int) (fabs(score)*100+0.5),\r
                                        depth );\r
@@ -879,6 +994,7 @@ SayMachineMove(int evenIfDuplicate)
                if(secondSpace) len = secondSpace; // position behind move\r
                if(messageText[len-1] == '+' || messageText[len-1] == '#') {  /* you are in checkmate */\r
                        len--; // strip off check or mate indicator\r
+                     checkMark = messageText[len]; // make sure still seen after we stip off promo piece\r
                }\r
                if(messageText[len-2] == '=') {  /* promotion */\r
                        len-=2; // strip off promotion piece\r
@@ -887,16 +1003,16 @@ SayMachineMove(int evenIfDuplicate)
 \r
                n = 2*moveNr - (dotCount < 2);\r
 \r
-               if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) { \r
+               if(previousMove != 2*moveNr + (dotCount > 1) || evenIfDuplicate) {\r
                    char number[20];\r
                    previousMove = 2*moveNr + (dotCount > 1); // remember move nr of move last spoken\r
-                   sprintf(number, "%d", moveNr);\r
+                   snprintf(number, sizeof(number)/sizeof(number[0]),"%d", moveNr);\r
 \r
                    yPos = CoordToNum(messageText[len-1]);  /* turn char coords to ints */\r
                    xPos = CoordToNum(messageText[len-2]);\r
                    if(xPos < 0 || xPos > 11) return; // prevent crashes if no coord string available to speak\r
                    if(yPos < 0 || yPos > 9)  return;\r
-                   currentpiece = boards[n][yPos][xPos];       \r
+                   currentpiece = boards[n][yPos][xPos];\r
                    piece = PieceToName(currentpiece,0);\r
                    ynum = SquareToNum(yPos);\r
                    xchar = SquareToChar(xPos);\r
@@ -935,11 +1051,11 @@ SayMachineMove(int evenIfDuplicate)
                                        SayString(piece, FALSE);\r
                                } else SayString("Capturing onn passann",FALSE);\r
                        }\r
-                       if(messageText[len] == '+') SayString("check", FALSE); else\r
-                       if(messageText[len] == '#') {\r
+                   }\r
+                   if(checkMark == '+') SayString("check", FALSE); else\r
+                   if(checkMark == '#') {\r
                                SayString("finishing off", FALSE);\r
                                SayString(WhiteOnMove(n) ? "White" : "Black", FALSE);\r
-                       }\r
                    }\r
                }\r
 \r
@@ -950,8 +1066,8 @@ SayMachineMove(int evenIfDuplicate)
                if(StrStr(messageText, " 1/2-1/2")) p = "game ends in a draw";\r
                if(comment[0]) {\r
                    if(p) {\r
-                       if(!StrCaseStr(comment, "draw") && \r
-                          !StrCaseStr(comment, "white") && \r
+                       if(!StrCaseStr(comment, "draw") &&\r
+                          !StrCaseStr(comment, "white") &&\r
                           !StrCaseStr(comment, "black") ) {\r
                                SayString(p, FALSE);\r
                                SayString("due to", FALSE);\r
@@ -960,12 +1076,15 @@ SayMachineMove(int evenIfDuplicate)
                    SayString(comment, FALSE); // alphabetic comment (usually game end)\r
                } else if(p) SayString(p, FALSE);\r
 \r
+               if(commentDialog && commentList[currentMove]) SetFocus(commentDialog);\r
+\r
            } else {\r
                /* starts not with digit */\r
                if(StrCaseStr(messageText, "illegal")) PlayIcsUnfinishedSound();\r
                SayString(messageText, FALSE);\r
            }\r
 \r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
@@ -978,16 +1097,17 @@ SayClockTime()
        suppressClocks = 1; // if user is using alt+T command, no reason to display them\r
        if(abs(lastWhiteTime - whiteTimeRemaining) < 1000 && abs(lastBlackTime - blackTimeRemaining) < 1000)\r
                suppressClocks = 0; // back on after two requests in rapid succession\r
-       sprintf(buf1, "%s", TimeString(whiteTimeRemaining));\r
+       snprintf(buf1, sizeof(buf1)/sizeof(buf1[0]),"%s", TimeString(whiteTimeRemaining));\r
        str1 = buf1;\r
-       SayString("White's remaining time is", FALSE);\r
+       SayString("White clock", FALSE);\r
        SayString(str1, FALSE);\r
-       sprintf(buf2, "%s", TimeString(blackTimeRemaining));\r
+       snprintf(buf2, sizeof(buf2)/sizeof(buf2[0]), "%s", TimeString(blackTimeRemaining));\r
        str2 = buf2;\r
-       SayString("Black's remaining time is", FALSE);\r
+       SayString("Black clock", FALSE);\r
        SayString(str2, FALSE);\r
        lastWhiteTime = whiteTimeRemaining;\r
        lastBlackTime = blackTimeRemaining;\r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 VOID\r
@@ -997,6 +1117,7 @@ Toggle(Boolean *b, char *mess)
        SayString(mess, FALSE);\r
        SayString("is now", FALSE);\r
        SayString(*b ? "on" : "off", FALSE);\r
+       SayString("", TRUE); // flush\r
 }\r
 \r
 /* handles keyboard moves in a click-click fashion */\r
@@ -1005,7 +1126,7 @@ KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
 {\r
        ChessSquare currentpiece;\r
        char *piece;\r
-       \r
+\r
        static BOOLEAN sameAgain = FALSE;\r
        switch (message) {\r
        case WM_KEYDOWN:\r
@@ -1016,11 +1137,11 @@ KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                        break;\r
                }\r
                else if(oldFromX != -1) {\r
-                       \r
+\r
                        ChessSquare pdown, pup;\r
       pdown = boards[currentMove][oldFromY][oldFromX];\r
       pup = boards[currentMove][fromY][fromX];\r
-               \r
+\r
                if (gameMode == EditPosition ||\r
                        !((WhitePawn <= pdown && pdown <= WhiteKing &&\r
                                 WhitePawn <= pup && pup <= WhiteKing) ||\r
@@ -1028,8 +1149,9 @@ KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                                 BlackPawn <= pup && pup <= BlackKing))) {\r
                        /* EditPosition, empty square, or different color piece;\r
                        click-click move is possible */\r
-               \r
-                       if (IsPromotion(oldFromX, oldFromY, fromX, fromY)) {\r
+                       char promoChoice = NULLCHAR;\r
+\r
+                       if (HasPromotionChoice(oldFromX, oldFromY, fromX, fromY, &promoChoice)) {\r
                                if (appData.alwaysPromoteToQueen) {\r
                                        UserMoveEvent(oldFromX, oldFromY, fromX, fromY, 'q');\r
                                }\r
@@ -1037,24 +1159,24 @@ KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
                                        toX = fromX; toY = fromY; fromX = oldFromX; fromY = oldFromY;\r
                                        PromotionPopup(hwnd);\r
                                        fromX = toX; fromY = toY;\r
-                               }       \r
+                               }\r
                        }\r
                        else {\r
-                               UserMoveEvent(oldFromX, oldFromY, fromX, fromY, NULLCHAR);\r
+                               UserMoveEvent(oldFromX, oldFromY, fromX, fromY, promoChoice);\r
                        }\r
                oldFromX = oldFromY = -1;\r
                break;\r
                }\r
-               \r
+\r
                }\r
                /* First downclick, or restart on a square with same color piece */\r
                if (OKToStartUserMove(fromX, fromY)) {\r
                oldFromX = fromX;\r
                oldFromY = fromY;\r
-               currentpiece = boards[currentMove][fromY][fromX];       \r
+               currentpiece = boards[currentMove][fromY][fromX];\r
                piece = PieceToName(currentpiece,1);\r
                SayString(piece, FALSE);\r
-               SayString("selected", FALSE);\r
+               SayString("selected", TRUE);\r
                }\r
                else {\r
                oldFromX = oldFromY = -1;\r
@@ -1067,10 +1189,10 @@ KeyboardMove(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
       if (sameAgain) {\r
        /* Clicked same square twice: abort click-click move */\r
                        oldFromX = oldFromY = -1;\r
-                       currentpiece = boards[currentMove][fromY][fromX];       \r
+                       currentpiece = boards[currentMove][fromY][fromX];\r
                        piece = PieceToName(currentpiece,0);\r
                        SayString(piece, FALSE);\r
-                       SayString("unselected", FALSE);\r
+                       SayString("unselected", TRUE);\r
                        }\r
                }\r
        }\r
@@ -1087,12 +1209,12 @@ NiceTime(int x)
        return (x%3000 == 0);\r
 }\r
 \r
-#if 0\r
-           if(isalpha((char)wParam)) {\r
-               /* capitals of any ind are intercepted and distinguished by left and right shift */\r
-               int mine = GetKeyState(VK_RSHIFT) < 0;\r
-               if(mine || GetKeyState(VK_LSHIFT) < 0) {\r
-#endif\r
+#define JAWS_ARGS \\r
+  { "beepOffBoard", ArgInt, (LPVOID) beeps, TRUE, (ArgIniType) 1 },\\r
+  { "beepEmpty", ArgInt, (LPVOID) (beeps+1), TRUE, (ArgIniType) 0 },\\r
+  { "beepWhite", ArgInt, (LPVOID) (beeps+2), TRUE, (ArgIniType) 0 },\\r
+  { "beepBlack", ArgInt, (LPVOID) (beeps+3), TRUE, (ArgIniType) 0 },\\r
+  { "beepHoldings", ArgInt, (LPVOID) (beeps+4), TRUE, (ArgIniType) 0 },\\r
 \r
 #define JAWS_ALT_INTERCEPT \\r
            if(suppressOneKey) {\\r
@@ -1102,6 +1224,7 @@ NiceTime(int x)
            if ((char)wParam == 022 && gameMode == EditPosition) { /* <Ctl R>. Pop up piece menu */\\r
                POINT pt; int x, y;\\r
                SquareToPos(fromY, fromX, &x, &y);\\r
+               dropX = fromX; dropY = fromY;\\r
                pt.x = x; pt.y = y;\\r
                if(gameInfo.variant != VariantShogi)\\r
                    MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\\r
@@ -1114,13 +1237,12 @@ NiceTime(int x)
     case '\020': /* ctrl P */\\r
       { char buf[MSG_SIZ];\\r
        if(GetWindowText(hwnd, buf, MSG_SIZ-1))\\r
-               SayString(buf, FALSE);\\r
+               SayString(buf, TRUE);\\r
       }\\r
       return 0;\\r
 \r
-#define JAWS_KB_NAVIGATION \\r
+#define JAWS_KBDOWN_NAVIGATION \\r
 \\r
-       case WM_KEYDOWN:\\r
 \\r
                if(GetKeyState(VK_MENU) < 0 && GetKeyState(VK_CONTROL) < 0) {\\r
                    /* Control + Alt + letter used for speaking piece positions */\\r
@@ -1153,17 +1275,17 @@ NiceTime(int x)
                        KeyboardEvent(hwnd, message, wParam, lParam);\\r
                        break;\\r
                case VK_SPACE:\\r
+                        shiftKey = GetKeyState(VK_SHIFT) < 0;\\r
                        KeyboardMove(hwnd, message, wParam, lParam);\\r
                        break;\\r
                }\\r
-               break;\\r
-       case WM_KEYUP:\\r
+\r
+#define JAWS_KBUP_NAVIGATION \\r
                switch (wParam) {\\r
                case VK_SPACE:\\r
                        KeyboardMove(hwnd, message, wParam, lParam);\\r
                        break;\\r
                }\\r
-               break;\\r
 \r
 #define JAWS_MENU_ITEMS \\r
                case IDM_PossibleAttackMove:  /*What can I possible attack from here */\\r
@@ -1258,23 +1380,21 @@ NiceTime(int x)
 \\r
 \r
 \r
+#define JAWS_ACCEL \\r
+       !(!frozen && TranslateAccelerator(hwndMain, hAccelJAWS, &msg)) &&\r
+\r
 #define JAWS_INIT if (!InitJAWS()) return (FALSE);\r
 \r
 #define JAWS_DELETE(X)\r
 \r
 #define JAWS_SILENCE if(suppressClocks) return;\r
 \r
-#define SAY(S) SayString((S), FALSE)\r
+#define JAWS_COPYRIGHT \\r
+       SetDlgItemText(hDlg, OPT_MESS, "Auditory/Keyboard Enhancements  By:  Ed Rodriguez (sort of)");\r
+\r
+#define SAY(S) SayString((S), TRUE)\r
 \r
 #define SAYMACHINEMOVE() SayMachineMove(0)\r
 \r
 // After inclusion of this file somewhere early in winboard.c, the remaining part of the patch\r
 // is scattered over winboard.c for actually calling the routines.\r
-//\r
-// * move fromX, fromY declaration to front, before incusion of this file. (Can be permanent change in winboard.c.)\r
-// * call InitJAWS(), after calling InitIntance(). (Using JAWS_INIT macro)\r
-// * add keyboard cases in main switch of WndProc, though JAWS_KB_NAVIGATION above, e.g. before WM_CHAR case.\r
-// * change the WM_CHAR case of same switch from "if(appData.icsActive)" to "if(appData.icsActive JAWS_IF_TAB)"\r
-// * add new menu cases in WM_COMMAND case of WndProc, e.g. before IDM_Forward. (throug macro defined above)\r
-// * add SAYMACHINEMOVE(); at the end of DisplayMessage();\r
-// * add SAY("board"); in WM_CHAR case of ConsoleTextSubclass, just before "SetFocus(buttondesc..."\r