#include "wsockerr.h"\r
#include "defaults.h"\r
\r
+#include "wsnap.h"
+
int myrandom(void);
void mysrandom(unsigned int seed);
char *firstChessProgramNames;\r
char *secondChessProgramNames;\r
\r
-#define ARG_MAX 64*1024 /* [AS] For Roger Brown's very long list! */
+#define ARG_MAX 128*1024 /* [AS] For Roger Brown's very long list! */
\r
#define PALETTESIZE 256\r
\r
void ParseIcsTextMenu(char *icsTextMenuString);\r
VOID PopUpMoveDialog(char firstchar);\r
VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);\r
+
+/* [AS] */
+int NewGameFRC();
+int GameListOptions();
+
+HWND moveHistoryDialog = NULL;
+BOOLEAN moveHistoryDialogUp = FALSE;
+
+WindowPlacement wpMoveHistory;
+
+HWND evalGraphDialog = NULL;
+BOOLEAN evalGraphDialogUp = FALSE;
+
+WindowPlacement wpEvalGraph;
+
+HWND engineOutputDialog = NULL;
+BOOLEAN engineOutputDialogUp = FALSE;
+
+WindowPlacement wpEngineOutput;
+
+VOID MoveHistoryPopUp();
+VOID MoveHistoryPopDown();
+VOID MoveHistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current, ChessProgramStats_Move * pvInfo );
+BOOL MoveHistoryIsUp();
+
+VOID EvalGraphSet( int first, int last, int current, ChessProgramStats_Move * pvInfo );
+VOID EvalGraphPopUp();
+VOID EvalGraphPopDown();
+BOOL EvalGraphIsUp();
+
+VOID EngineOutputPopUp();
+VOID EngineOutputPopDown();
+BOOL EngineOutputIsUp();
+VOID EngineOutputUpdate( int which, int depth, unsigned long nodes, int score, int time, char * pv );
\r
/*\r
* Setting "frozen" should disable all user input other than deleting\r
LPSTR lpCmdLine, int nCmdShow)\r
{\r
MSG msg;\r
- HANDLE hAccelMain, hAccelNoAlt;\r
+ HANDLE hAccelMain, hAccelNoAlt, hAccelNoICS;
\r
debugFP = stderr;\r
\r
\r
hAccelMain = LoadAccelerators (hInstance, szAppName);\r
hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");\r
+ hAccelNoICS = LoadAccelerators( hInstance, "NO_ICS"); /* [AS] No Ctrl-V on ICS!!! */
\r
/* Acquire and dispatch messages until a WM_QUIT message is received. */\r
\r
0)) /* highest message to examine */\r
{\r
if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&\r
+ !(moveHistoryDialog && IsDialogMessage(moveHistoryDialog, &msg)) &&
+ !(evalGraphDialog && IsDialogMessage(evalGraphDialog, &msg)) &&
+ !(engineOutputDialog && IsDialogMessage(engineOutputDialog, &msg)) &&
!(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&\r
!(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&\r
!(errorDialog && IsDialogMessage(errorDialog, &msg)) &&\r
!(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&\r
+ !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoICS, &msg)) &&
!(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {\r
TranslateMessage(&msg); /* Translates virtual key codes */\r
DispatchMessage(&msg); /* Dispatches message to window */\r
ConsoleCreate();\r
}\r
\r
+ /* [AS] Restore layout */
+ if( wpMoveHistory.visible ) {
+ MoveHistoryPopUp();
+ }
+
+ if( wpEvalGraph.visible ) {
+ EvalGraphPopUp();
+ }
+
+ if( wpEngineOutput.visible ) {
+ EngineOutputPopUp();
+ }
+
InitBackEnd2();\r
\r
/* Make the window visible; update its client area; and return "success" */\r
\r
SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
+
+ /* [AS] Disable the FRC stuff if not playing the proper variant */
+ if( gameInfo.variant != VariantFischeRandom ) {
+ EnableMenuItem( GetMenu(hwndMain), IDM_NewGameFRC, MF_GRAYED );
+ }
+
if (hwndConsole) {\r
#if AOT_CONSOLE\r
SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
{ "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },\r
{ "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },\r
/* [AS] New features */
- { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, TRUE },
- { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, TRUE },
+ { "firstScoreAbs", ArgBoolean, (LPVOID) &appData.firstScoreIsAbsolute, FALSE },
+ { "secondScoreAbs", ArgBoolean, (LPVOID) &appData.secondScoreIsAbsolute, FALSE },
{ "pgnExtendedInfo", ArgBoolean, (LPVOID) &appData.saveExtendedInfoInPGN, TRUE },
{ "hideThinkingFromHuman", ArgBoolean, (LPVOID) &appData.hideThinkingFromHuman, TRUE },
{ "liteBackTextureFile", ArgString, (LPVOID) &appData.liteBackTextureFile, TRUE },
{ "delayBeforeQuit", ArgInt, (LPVOID) &appData.delayBeforeQuit, TRUE },
{ "delayAfterQuit", ArgInt, (LPVOID) &appData.delayAfterQuit, TRUE },
{ "nameOfDebugFile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
- { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
{ "debugfile", ArgFilename, (LPVOID) &appData.nameOfDebugFile, FALSE },
+ { "pgnEventHeader", ArgString, (LPVOID) &appData.pgnEventHeader, TRUE },
+ { "defaultFrcPosition", ArgInt, (LPVOID) &appData.defaultFrcPosition, TRUE },
+ { "gameListTags", ArgString, (LPVOID) &appData.gameListTags, TRUE },
+ { "saveOutOfBookInfo", ArgBoolean, (LPVOID) &appData.saveOutOfBookInfo, TRUE },
+ { "showEvalInMoveHistory", ArgBoolean, (LPVOID) &appData.showEvalInMoveHistory, TRUE },
+ { "evalHistColorWhite", ArgColor, (LPVOID) &appData.evalHistColorWhite, TRUE },
+ { "evalHistColorBlack", ArgColor, (LPVOID) &appData.evalHistColorBlack, TRUE },
+ { "highlightMoveWithArrow", ArgBoolean, (LPVOID) &appData.highlightMoveWithArrow, TRUE },
+ { "highlightArrowColor", ArgColor, (LPVOID) &appData.highlightArrowColor, TRUE },
+ { "stickyWindows", ArgBoolean, (LPVOID) &appData.useStickyWindows, TRUE },
+ { "adjudicateDrawMoves", ArgInt, (LPVOID) &appData.adjudicateDrawMoves, TRUE },
+ { "autoDisplayComment", ArgBoolean, (LPVOID) &appData.autoDisplayComment, TRUE },
+ { "autoDisplayTags", ArgBoolean, (LPVOID) &appData.autoDisplayTags, TRUE },
+
+ /* [AS] Layout stuff */
+ { "moveHistoryUp", ArgBoolean, (LPVOID) &wpMoveHistory.visible, TRUE },
+ { "moveHistoryX", ArgInt, (LPVOID) &wpMoveHistory.x, TRUE },
+ { "moveHistoryY", ArgInt, (LPVOID) &wpMoveHistory.y, TRUE },
+ { "moveHistoryW", ArgInt, (LPVOID) &wpMoveHistory.width, TRUE },
+ { "moveHistoryH", ArgInt, (LPVOID) &wpMoveHistory.height, TRUE },
+
+ { "evalGraphUp", ArgBoolean, (LPVOID) &wpEvalGraph.visible, TRUE },
+ { "evalGraphX", ArgInt, (LPVOID) &wpEvalGraph.x, TRUE },
+ { "evalGraphY", ArgInt, (LPVOID) &wpEvalGraph.y, TRUE },
+ { "evalGraphW", ArgInt, (LPVOID) &wpEvalGraph.width, TRUE },
+ { "evalGraphH", ArgInt, (LPVOID) &wpEvalGraph.height, TRUE },
+
+ { "engineOutputUp", ArgBoolean, (LPVOID) &wpEngineOutput.visible, TRUE },
+ { "engineOutputX", ArgInt, (LPVOID) &wpEngineOutput.x, TRUE },
+ { "engineOutputY", ArgInt, (LPVOID) &wpEngineOutput.y, TRUE },
+ { "engineOutputW", ArgInt, (LPVOID) &wpEngineOutput.width, TRUE },
+ { "engineOutputH", ArgInt, (LPVOID) &wpEngineOutput.height, TRUE },
+
#ifdef ZIPPY\r
{ "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },\r
{ "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },\r
appData.delayAfterQuit = 0;
appData.nameOfDebugFile = "winboard.debug";
appData.pgnEventHeader = "Computer Chess Game";
+ appData.defaultFrcPosition = -1;
+ appData.gameListTags = GLT_DEFAULT_TAGS;
+ appData.saveOutOfBookInfo = TRUE;
+ appData.showEvalInMoveHistory = TRUE;
+ appData.evalHistColorWhite = ParseColorName( "#FFFFB0" );
+ appData.evalHistColorBlack = ParseColorName( "#AD5D3D" );
+ appData.highlightMoveWithArrow = FALSE;
+ appData.highlightArrowColor = ParseColorName( "#FFFF80" );
+ appData.useStickyWindows = TRUE;
+ appData.adjudicateDrawMoves = 0;
+ appData.autoDisplayComment = TRUE;
+ appData.autoDisplayTags = TRUE;
+
+ InitWindowPlacement( &wpMoveHistory );
+ InitWindowPlacement( &wpEvalGraph );
+ InitWindowPlacement( &wpEngineOutput );
#ifdef ZIPPY\r
appData.zippyTalk = ZIPPY_TALK;\r
gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
}\r
\r
+ /* [AS] Move history */
+ wpMoveHistory.visible = MoveHistoryIsUp();
+
+ if( moveHistoryDialog ) {
+ GetWindowPlacement(moveHistoryDialog, &wp);
+ wpMoveHistory.x = wp.rcNormalPosition.left;
+ wpMoveHistory.y = wp.rcNormalPosition.top;
+ wpMoveHistory.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
+ wpMoveHistory.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
+ }
+
+ /* [AS] Eval graph */
+ wpEvalGraph.visible = EvalGraphIsUp();
+
+ if( evalGraphDialog ) {
+ GetWindowPlacement(evalGraphDialog, &wp);
+ wpEvalGraph.x = wp.rcNormalPosition.left;
+ wpEvalGraph.y = wp.rcNormalPosition.top;
+ wpEvalGraph.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
+ wpEvalGraph.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
+ }
+
+ /* [AS] Engine output */
+ wpEngineOutput.visible = EngineOutputIsUp();
+
+ if( engineOutputDialog ) {
+ GetWindowPlacement(engineOutputDialog, &wp);
+ wpEngineOutput.x = wp.rcNormalPosition.left;
+ wpEngineOutput.y = wp.rcNormalPosition.top;
+ wpEngineOutput.width = wp.rcNormalPosition.right - wp.rcNormalPosition.left;
+ wpEngineOutput.height = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;
+ }
+
for (ad = argDescriptors; ad->argName != NULL; ad++) {\r
if (!ad->save) continue;\r
switch (ad->argType) {\r
SelectObject( hdc, hbm_old );
+ if( hPieceFace[index] != NULL ) {
+ DeleteObject( hPieceFace[index] );
+ }
+
hPieceFace[index] = hbm;
}
else {
for( i=0; i<12; i++ ) {
hPieceMask[i] = NULL;
+ hPieceFace[i] = NULL;
}
}
\r
/* [AS] Use font-based pieces if needed */
if( fontBitmapSquareSize >= 0 && squareSize > 32 ) {
- /* Create piece bitmaps, or do nothing if piece set is up to data */
+ /* Create piece bitmaps, or do nothing if piece set is up to date */
CreatePiecesFromFont();
if( fontBitmapSquareSize == squareSize ) {
}
}
+/* [AS] Arrow highlighting support */
+
+static int A_WIDTH = 5; /* Width of arrow body */
+
+#define A_HEIGHT_FACTOR 6 /* Length of arrow "point", relative to body width */
+#define A_WIDTH_FACTOR 3 /* Width of arrow "point", relative to body width */
+
+static double Sqr( double x )
+{
+ return x*x;
+}
+
+static int Round( double x )
+{
+ return (int) (x + 0.5);
+}
+
+/* Draw an arrow between two points using current settings */
+VOID DrawArrowBetweenPoints( HDC hdc, int s_x, int s_y, int d_x, int d_y )
+{
+ POINT arrow[7];
+ double dx, dy, j, k, x, y;
+
+ if( d_x == s_x ) {
+ int h = (d_y > s_y) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;
+
+ arrow[0].x = s_x + A_WIDTH;
+ arrow[0].y = s_y;
+
+ arrow[1].x = s_x + A_WIDTH;
+ arrow[1].y = d_y - h;
+
+ arrow[2].x = s_x + A_WIDTH*A_WIDTH_FACTOR;
+ arrow[2].y = d_y - h;
+
+ arrow[3].x = d_x;
+ arrow[3].y = d_y;
+
+ arrow[4].x = s_x - A_WIDTH*A_WIDTH_FACTOR;
+ arrow[4].y = d_y - h;
+
+ arrow[5].x = s_x - A_WIDTH;
+ arrow[5].y = d_y - h;
+
+ arrow[6].x = s_x - A_WIDTH;
+ arrow[6].y = s_y;
+ }
+ else if( d_y == s_y ) {
+ int w = (d_x > s_x) ? +A_WIDTH*A_HEIGHT_FACTOR : -A_WIDTH*A_HEIGHT_FACTOR;
+
+ arrow[0].x = s_x;
+ arrow[0].y = s_y + A_WIDTH;
+
+ arrow[1].x = d_x - w;
+ arrow[1].y = s_y + A_WIDTH;
+
+ arrow[2].x = d_x - w;
+ arrow[2].y = s_y + A_WIDTH*A_WIDTH_FACTOR;
+
+ arrow[3].x = d_x;
+ arrow[3].y = d_y;
+
+ arrow[4].x = d_x - w;
+ arrow[4].y = s_y - A_WIDTH*A_WIDTH_FACTOR;
+
+ arrow[5].x = d_x - w;
+ arrow[5].y = s_y - A_WIDTH;
+
+ arrow[6].x = s_x;
+ arrow[6].y = s_y - A_WIDTH;
+ }
+ else {
+ /* [AS] Needed a lot of paper for this! :-) */
+ dy = (double) (d_y - s_y) / (double) (d_x - s_x);
+ dx = (double) (s_x - d_x) / (double) (s_y - d_y);
+
+ j = sqrt( Sqr(A_WIDTH) / (1.0 + Sqr(dx)) );
+
+ k = sqrt( Sqr(A_WIDTH*A_HEIGHT_FACTOR) / (1.0 + Sqr(dy)) );
+
+ x = s_x;
+ y = s_y;
+
+ arrow[0].x = Round(x - j);
+ arrow[0].y = Round(y + j*dx);
+
+ arrow[1].x = Round(x + j);
+ arrow[1].y = Round(y - j*dx);
+
+ if( d_x > s_x ) {
+ x = (double) d_x - k;
+ y = (double) d_y - k*dy;
+ }
+ else {
+ x = (double) d_x + k;
+ y = (double) d_y + k*dy;
+ }
+
+ arrow[2].x = Round(x + j);
+ arrow[2].y = Round(y - j*dx);
+
+ arrow[3].x = Round(x + j*A_WIDTH_FACTOR);
+ arrow[3].y = Round(y - j*A_WIDTH_FACTOR*dx);
+
+ arrow[4].x = d_x;
+ arrow[4].y = d_y;
+
+ arrow[5].x = Round(x - j*A_WIDTH_FACTOR);
+ arrow[5].y = Round(y + j*A_WIDTH_FACTOR*dx);
+
+ arrow[6].x = Round(x - j);
+ arrow[6].y = Round(y + j*dx);
+ }
+
+ Polygon( hdc, arrow, 7 );
+}
+
+/* [AS] Draw an arrow between two squares */
+VOID DrawArrowBetweenSquares( HDC hdc, int s_col, int s_row, int d_col, int d_row )
+{
+ int s_x, s_y, d_x, d_y;
+ HPEN hpen;
+ HPEN holdpen;
+ HBRUSH hbrush;
+ HBRUSH holdbrush;
+ LOGBRUSH stLB;
+
+ if( s_col == d_col && s_row == d_row ) {
+ return;
+ }
+
+ /* Get source and destination points */
+ SquareToPos( s_row, s_col, &s_x, &s_y);
+ SquareToPos( d_row, d_col, &d_x, &d_y);
+
+ if( d_y > s_y ) {
+ d_y += squareSize / 4;
+ }
+ else if( d_y < s_y ) {
+ d_y += 3 * squareSize / 4;
+ }
+ else {
+ d_y += squareSize / 2;
+ }
+
+ if( d_x > s_x ) {
+ d_x += squareSize / 4;
+ }
+ else if( d_x < s_x ) {
+ d_x += 3 * squareSize / 4;
+ }
+ else {
+ d_x += squareSize / 2;
+ }
+
+ s_x += squareSize / 2;
+ s_y += squareSize / 2;
+
+ /* Adjust width */
+ A_WIDTH = squareSize / 14;
+
+ /* Draw */
+ stLB.lbStyle = BS_SOLID;
+ stLB.lbColor = appData.highlightArrowColor;
+ stLB.lbHatch = 0;
+
+ hpen = CreatePen( PS_SOLID, 2, RGB(0x00,0x00,0x00) );
+ holdpen = SelectObject( hdc, hpen );
+ hbrush = CreateBrushIndirect( &stLB );
+ holdbrush = SelectObject( hdc, hbrush );
+
+ DrawArrowBetweenPoints( hdc, s_x, s_y, d_x, d_y );
+
+ SelectObject( hdc, holdpen );
+ SelectObject( hdc, holdbrush );
+ DeleteObject( hpen );
+ DeleteObject( hbrush );
+}
+
+BOOL HasHighlightInfo()
+{
+ BOOL result = FALSE;
+
+ if( highlightInfo.sq[0].x >= 0 && highlightInfo.sq[0].y >= 0 &&
+ highlightInfo.sq[1].x >= 0 && highlightInfo.sq[1].y >= 0 )
+ {
+ result = TRUE;
+ }
+
+ return result;
+}
+
+BOOL IsDrawArrowEnabled()
+{
+ BOOL result = FALSE;
+
+ if( appData.highlightMoveWithArrow && squareSize >= 32 ) {
+ result = TRUE;
+ }
+
+ return result;
+}
+
+VOID DrawArrowHighlight( HDC hdc )
+{
+ if( IsDrawArrowEnabled() && HasHighlightInfo() ) {
+ DrawArrowBetweenSquares( hdc,
+ highlightInfo.sq[0].x, highlightInfo.sq[0].y,
+ highlightInfo.sq[1].x, highlightInfo.sq[1].y );
+ }
+}
+
+HRGN GetArrowHighlightClipRegion( HDC hdc )
+{
+ HRGN result = NULL;
+
+ if( HasHighlightInfo() ) {
+ int x1, y1, x2, y2;
+ int sx, sy, dx, dy;
+
+ SquareToPos(highlightInfo.sq[0].y, highlightInfo.sq[0].x, &x1, &y1 );
+ SquareToPos(highlightInfo.sq[1].y, highlightInfo.sq[1].x, &x2, &y2 );
+
+ sx = MIN( x1, x2 );
+ sy = MIN( y1, y2 );
+ dx = MAX( x1, x2 ) + squareSize;
+ dy = MAX( y1, y2 ) + squareSize;
+
+ result = CreateRectRgn( sx, sy, dx, dy );
+ }
+
+ return result;
+}
+
+/*
+ Warning: this function modifies the behavior of several other functions.
+
+ Basically, Winboard is optimized to avoid drawing the whole board if not strictly
+ needed. Unfortunately, the decision whether or not to perform a full or partial
+ repaint is scattered all over the place, which is not good for features such as
+ "arrow highlighting" that require a full repaint of the board.
+
+ So, I've tried to patch the code where I thought it made sense (e.g. after or during
+ user interaction, when speed is not so important) but especially to avoid errors
+ in the displayed graphics.
+
+ In such patched places, I always try refer to this function so there is a single
+ place to maintain knowledge.
+
+ To restore the original behavior, just return FALSE unconditionally.
+*/
+BOOL IsFullRepaintPreferrable()
+{
+ BOOL result = FALSE;
+
+ if( (appData.highlightLastMove || appData.highlightDragging) && IsDrawArrowEnabled() ) {
+ /* Arrow may appear on the board */
+ result = TRUE;
+ }
+
+ return result;
+}
+
+/*
+ This function is called by DrawPosition to know whether a full repaint must
+ be forced or not.
+
+ Only DrawPosition may directly call this function, which makes use of
+ some state information. Other function should call DrawPosition specifying
+ the repaint flag, and can use IsFullRepaintPreferrable if needed.
+*/
+BOOL DrawPositionNeedsFullRepaint()
+{
+ BOOL result = FALSE;
+
+ /*
+ Probably a slightly better policy would be to trigger a full repaint
+ when animInfo.piece changes state (i.e. empty -> non-empty and viceversa),
+ but animation is fast enough that it's difficult to notice.
+ */
+ if( animInfo.piece == EmptySquare ) {
+ if( (appData.highlightLastMove || appData.highlightDragging) && IsDrawArrowEnabled() && HasHighlightInfo() ) {
+ result = TRUE;
+ }
+ }
+
+ return result;
+}
+
VOID\r
DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)\r
{\r
*/\r
Boolean fullrepaint = repaint;\r
\r
+ if( DrawPositionNeedsFullRepaint() ) {
+ fullrepaint = TRUE;
+ }
+
+#if 0
+ if( fullrepaint ) {
+ static int repaint_count = 0;
+ char buf[128];
+
+ repaint_count++;
+ sprintf( buf, "FULL repaint: %d\n", repaint_count );
+ OutputDebugString( buf );
+ }
+#endif
+
if (board == NULL) {\r
if (!lastReqValid) {\r
return;\r
DrawGridOnDC(hdcmem);\r
DrawHighlightsOnDC(hdcmem);\r
DrawBoardOnDC(hdcmem, board, tmphdc);\r
+
+ if( appData.highlightMoveWithArrow ) {
+ DrawArrowHighlight(hdcmem);
+ }
+
DrawCoordsOnDC(hdcmem);\r
\r
/* Put the dragged piece back into place and draw it */\r
POINT pt;\r
static int recursive = 0;\r
HMENU hmenu;\r
+ BOOLEAN needsRedraw = FALSE;
BOOLEAN saveAnimate;\r
+ BOOLEAN forceFullRepaint = IsFullRepaintPreferrable(); /* [AS] */
static BOOLEAN sameAgain = FALSE;\r
\r
if (recursive) {\r
}\r
if (!appData.highlightLastMove) {\r
ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
+ DrawPosition(forceFullRepaint || FALSE, NULL);
}\r
fromX = fromY = -1;\r
dragInfo.start.x = dragInfo.start.y = -1;\r
} else if (fromX == x && fromY == y) {\r
/* Downclick on same square again */\r
ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
+ DrawPosition(forceFullRepaint || FALSE, NULL);
sameAgain = TRUE; \r
} else if (fromX != -1) {\r
/* Downclick on different square */\r
UserMoveEvent(fromX, fromY, toX, toY, 'q');\r
if (!appData.highlightLastMove) {\r
ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
+ DrawPosition(forceFullRepaint || FALSE, NULL);
}\r
} else {\r
SetHighlights(fromX, fromY, toX, toY);\r
- DrawPosition(FALSE, NULL);\r
+ DrawPosition(forceFullRepaint || FALSE, NULL);
PromotionPopup(hwnd);\r
}\r
} else { /* not a promotion */\r
UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);\r
if (appData.animate && !appData.highlightLastMove) {\r
ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
+ DrawPosition(forceFullRepaint || FALSE, NULL);
}\r
}\r
if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
break;\r
}\r
ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
+ DrawPosition(forceFullRepaint || FALSE, NULL);
}\r
/* First downclick, or restart on a square with same color piece */\r
if (!frozen && OKToStartUserMove(x, y)) {\r
fromX = fromY = -1;\r
dragInfo.start.x = dragInfo.start.y = -1;\r
dragInfo.from = dragInfo.start;\r
+ DrawPosition(forceFullRepaint || FALSE, NULL); /* [AS] */
}\r
break;\r
\r
/* First square clicked: start click-click move */\r
SetHighlights(fromX, fromY, -1, -1);\r
}\r
- DrawPosition(FALSE, NULL);\r
+ DrawPosition(forceFullRepaint || FALSE, NULL);
} else if (dragInfo.from.x < 0 || dragInfo.from.y < 0) {\r
/* Errant click; ignore */\r
break;\r
if (appData.alwaysPromoteToQueen) {\r
UserMoveEvent(fromX, fromY, toX, toY, 'q');\r
} else {\r
- DrawPosition(FALSE, NULL);\r
+ DrawPosition(forceFullRepaint || FALSE, NULL);
PromotionPopup(hwnd);\r
}\r
} else {\r
}\r
if (appData.animate || appData.animateDragging ||\r
appData.highlightDragging || gotPremove) {\r
- DrawPosition(FALSE, NULL);\r
+ DrawPosition(forceFullRepaint || FALSE, NULL);
}\r
}\r
dragInfo.start.x = dragInfo.start.y = -1; \r
case WM_MOUSEMOVE:\r
if ((appData.animateDragging || appData.highlightDragging)\r
&& (wParam & MK_LBUTTON)\r
- && dragInfo.from.x >= 0) {\r
+ && dragInfo.from.x >= 0)
+ {
+ BOOL full_repaint = FALSE;
+
if (appData.animateDragging) {\r
dragInfo.pos = pt;\r
}\r
if (appData.highlightDragging) {\r
SetHighlights(fromX, fromY, x, y);\r
+ if( IsDrawArrowEnabled() && (x < 0 || x > 7 || y < 0 || y > y) ) {
+ full_repaint = TRUE;
}\r
- DrawPosition(FALSE, NULL);\r
+ }
+
+ DrawPosition( full_repaint, NULL);
+
dragInfo.lastpos = dragInfo.pos;\r
}\r
break;\r
FILE *f;\r
UINT number;\r
char fileTitle[MSG_SIZ];\r
+ static SnapData sd;
\r
switch (message) {\r
\r
AnalysisPopDown();\r
break;\r
\r
+ case IDM_NewGameFRC:
+ if( NewGameFRC() == 0 ) {
+ ResetGameEvent();
+ AnalysisPopDown();
+ }
+ break;
+
case IDM_LoadGame:\r
LoadGameDialog(hwnd, "Load Game from File");\r
break;\r
PasteGameFromClipboard();\r
break;\r
\r
+ case IDM_CopyGameListToClipboard:
+ CopyGameListToClipboard();
+ break;
+
/* [AS] Autodetect FEN or PGN data */
- case IDM_Paste:
+ case IDM_PasteAny:
PasteGameOrFENFromClipboard();
break;
+ /* [AS] Move history */
+ case IDM_ShowMoveHistory:
+ if( MoveHistoryIsUp() ) {
+ MoveHistoryPopDown();
+ }
+ else {
+ MoveHistoryPopUp();
+ }
+ break;
+
+ /* [AS] Eval graph */
+ case IDM_ShowEvalGraph:
+ if( EvalGraphIsUp() ) {
+ EvalGraphPopDown();
+ }
+ else {
+ EvalGraphPopUp();
+ }
+ break;
+
+ /* [AS] Engine output */
+ case IDM_ShowEngineOutput:
+ if( EngineOutputIsUp() ) {
+ EngineOutputPopDown();
+ }
+ else {
+ EngineOutputPopUp();
+ }
+ break;
+
/* [AS] User adjudication */
case IDM_UserAdjudication_White:
UserAdjudicationEvent( +1 );
UserAdjudicationEvent( 0 );
break;
+ /* [AS] Game list options dialog */
+ case IDM_GameListOptions:
+ GameListOptions();
+ break;
+
case IDM_CopyPosition:\r
CopyFENToClipboard();\r
break;\r
\r
case IDM_GeneralOptions:\r
GeneralOptionsPopup(hwnd);\r
+ DrawPosition(TRUE, NULL);
break;\r
\r
case IDM_BoardOptions:\r
BoardOptionsPopup(hwnd);\r
break;\r
\r
+ case IDM_EnginePlayOptions:
+ EnginePlayOptionsPopup(hwnd);
+ break;
+
case IDM_IcsOptions:\r
IcsOptionsPopup(hwnd);\r
break;\r
InputEvent(hwnd, message, wParam, lParam);\r
break;\r
\r
+ /* [AS] Also move "attached" child windows */
+ case WM_WINDOWPOSCHANGING:
+ if( hwnd == hwndMain && appData.useStickyWindows ) {
+ LPWINDOWPOS lpwp = (LPWINDOWPOS) lParam;
+
+ if( ((lpwp->flags & SWP_NOMOVE) == 0) && ((lpwp->flags & SWP_NOSIZE) != 0) ) {
+ /* Window is moving */
+ RECT rcMain;
+
+ GetWindowRect( hwnd, &rcMain );
+
+ ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, moveHistoryDialog, &wpMoveHistory );
+ ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, evalGraphDialog, &wpEvalGraph );
+ ReattachAfterMove( &rcMain, lpwp->x, lpwp->y, engineOutputDialog, &wpEngineOutput );
+ }
+ }
+ break;
+
+ /* [AS] Snapping */
case WM_ENTERSIZEMOVE:\r
if (hwnd == hwndMain) {\r
doingSizing = TRUE;\r
lastSizing = 0;\r
}\r
+ return OnEnterSizeMove( &sd, hwnd, wParam, lParam );
break;\r
\r
case WM_SIZING:\r
}\r
break;\r
\r
+ case WM_MOVING:
+ return OnMoving( &sd, hwnd, wParam, lParam );
+
case WM_EXITSIZEMOVE:\r
if (hwnd == hwndMain) {\r
RECT client;\r
ResizeBoard(client.right, client.bottom, lastSizing);\r
lastSizing = 0;\r
}\r
+ return OnExitSizeMove( &sd, hwnd, wParam, lParam );
break;\r
\r
case WM_DESTROY: /* message: window being destroyed */\r
EndDeferWindowPos(cl.hdwp);\r
}\r
\r
-/* Center one window over another */\r
-BOOL CenterWindow (HWND hwndChild, HWND hwndParent)\r
+BOOL CenterWindowEx(HWND hwndChild, HWND hwndParent, int mode)
{\r
RECT rChild, rParent;\r
int wChild, hChild, wParent, hParent;\r
}\r
\r
/* Calculate new Y position, then adjust for screen */\r
+ if( mode == 0 ) {
yNew = rParent.top + ((hParent - hChild) /2);\r
+ }
+ else {
+ yNew = rParent.top + GetSystemMetrics( SM_CYCAPTION ) * 2 / 3;
+ }
+
if (yNew < 0) {\r
yNew = 0;\r
} else if ((yNew+hChild) > hScreen) {\r
xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\r
}\r
\r
+/* Center one window over another */
+BOOL CenterWindow (HWND hwndChild, HWND hwndParent)
+{
+ return CenterWindowEx( hwndChild, hwndParent, 0 );
+}
+
/*---------------------------------------------------------------------------*\\r
*\r
* Startup Dialog functions\r
case WM_INITDIALOG:\r
move[0] = (char) lParam;\r
move[1] = NULLCHAR;\r
- CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
+ CenterWindowEx(hDlg, GetWindow(hDlg, GW_OWNER), 1 );
hInput = GetDlgItem(hDlg, OPT_Move);\r
SetWindowText(hInput, move);\r
SetFocus(hInput);\r
LRESULT CALLBACK\r
ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
{\r
+ static SnapData sd;
static HWND hText, hInput, hFocus;\r
InputSource *is = consoleInputSource;\r
RECT rect;\r
mmi->ptMinTrackSize.x = 100;\r
mmi->ptMinTrackSize.y = 100;\r
break;\r
+
+ /* [AS] Snapping */
+ 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 );
}\r
+
return DefWindowProc(hDlg, message, wParam, lParam);\r
}\r
\r
{\r
int ok, err;\r
\r
+ /* [AS] */
+ if( count <= 0 ) {
+ if (appData.debugMode) {
+ fprintf( debugFP, "DoReadFile: trying to read past end of buffer, overflow = %d\n", count );
+ }
+
+ return ERROR_INVALID_USER_BUFFER;
+ }
+
ResetEvent(ovl->hEvent);\r
ovl->Offset = ovl->OffsetHigh = 0;\r
ok = ReadFile(hFile, buf, count, outCount, ovl);\r
fprintf( debugFP, "Input line exceeded buffer size (source id=%u)\n", is->id );
}
- is->error = ERROR_BROKEN_PIPE; /* [AS] Just a non-successful code! */
- is->count = (DWORD) -2;
+ is->error = ERROR_BROKEN_PIPE; /* [AS] Just any non-successful code! */
+ is->count = (DWORD) -1;
is->next = is->buf;
}
}
is->count = 0;\r
} else {\r
is->count = (DWORD) -1;\r
+ /* [AS] The (is->count <= 0) check below is not useful for unsigned values! */
+ break;
}\r
}\r
CheckForInputBufferFull( is );
SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
+
+ if( is->count == ((DWORD) -1) ) break; /* [AS] */
+
if (is->count <= 0) break; /* Quit on EOF or error */\r
}\r
+
CloseHandle(ovl.hEvent);\r
CloseHandle(is->hFile);\r
+
+ if (appData.debugMode) {
+ fprintf( debugFP, "Input thread terminated (id=%u, error=%d, count=%d)\n", is->id, is->error, is->count );
+ }
+
return 0;\r
}\r
\r
CheckForInputBufferFull( is );
SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
+
+ if( is->count == ((DWORD) -1) ) break; /* [AS] */
+
if (is->count < 0) break; /* Quit on error */\r
}\r
CloseHandle(is->hFile);\r
}\r
}\r
SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
+
+ if( is->count == ((DWORD) -1) ) break; /* [AS] */
+
if (is->count <= 0) break; /* Quit on EOF or error */\r
}\r
return 0;\r
FreeProcInstance(lpProc);\r
}\r
\r
+/* [AS] Pick FRC position */
+LRESULT CALLBACK NewGameFRC_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static int * lpIndexFRC;
+ BOOL index_is_ok;
+ char buf[16];
+
+ switch( message )
+ {
+ case WM_INITDIALOG:
+ lpIndexFRC = (int *) lParam;
+
+ CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));
+
+ SendDlgItemMessage( hDlg, IDC_NFG_Edit, EM_SETLIMITTEXT, sizeof(buf)-1, 0 );
+ SetDlgItemInt( hDlg, IDC_NFG_Edit, *lpIndexFRC, TRUE );
+ SendDlgItemMessage( hDlg, IDC_NFG_Edit, EM_SETSEL, 0, -1 );
+ SetFocus(GetDlgItem(hDlg, IDC_NFG_Edit));
+
+ break;
+
+ case WM_COMMAND:
+ switch( LOWORD(wParam) ) {
+ case IDOK:
+ *lpIndexFRC = GetDlgItemInt(hDlg, IDC_NFG_Edit, &index_is_ok, TRUE );
+ EndDialog( hDlg, 0 );
+ return TRUE;
+ case IDCANCEL:
+ EndDialog( hDlg, 1 );
+ return TRUE;
+ case IDC_NFG_Edit:
+ if( HIWORD(wParam) == EN_CHANGE ) {
+ GetDlgItemInt(hDlg, IDC_NFG_Edit, &index_is_ok, TRUE );
+
+ EnableWindow( GetDlgItem(hDlg, IDOK), index_is_ok );
+ }
+ return TRUE;
+ case IDC_NFG_Random:
+ sprintf( buf, "%d", myrandom() % 960 );
+ SetDlgItemText(hDlg, IDC_NFG_Edit, buf );
+ return TRUE;
+ }
+
+ break;
+ }
+
+ return FALSE;
+}
+
+int NewGameFRC()
+{
+ int result;
+ int index = appData.defaultFrcPosition;
+ FARPROC lpProc = MakeProcInstance( (FARPROC) NewGameFRC_Proc, hInst );
+
+ result = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_NewGameFRC), hwndMain, (DLGPROC)lpProc, (LPARAM)&index );
+
+ if( result == 0 ) {
+ appData.defaultFrcPosition = index;
+ }
+
+ return result;
+}
+
+/* [AS] Game list options */
+typedef struct {
+ char id;
+ char * name;
+} GLT_Item;
+
+static GLT_Item GLT_ItemInfo[] = {
+ { GLT_EVENT, "Event" },
+ { GLT_SITE, "Site" },
+ { GLT_DATE, "Date" },
+ { GLT_ROUND, "Round" },
+ { GLT_PLAYERS, "Players" },
+ { GLT_RESULT, "Result" },
+ { GLT_WHITE_ELO, "White Rating" },
+ { GLT_BLACK_ELO, "Black Rating" },
+ { GLT_TIME_CONTROL,"Time Control" },
+ { GLT_VARIANT, "Variant" },
+ { GLT_OUT_OF_BOOK,PGN_OUT_OF_BOOK },
+ { 0, 0 }
+};
+
+const char * GLT_FindItem( char id )
+{
+ const char * result = 0;
+
+ GLT_Item * list = GLT_ItemInfo;
+
+ while( list->id != 0 ) {
+ if( list->id == id ) {
+ result = list->name;
+ break;
+ }
+
+ list++;
+ }
+
+ return result;
+}
+
+void GLT_AddToList( HWND hDlg, int iDlgItem, char id, int index )
+{
+ const char * name = GLT_FindItem( id );
+
+ if( name != 0 ) {
+ if( index >= 0 ) {
+ SendDlgItemMessage( hDlg, iDlgItem, LB_INSERTSTRING, index, (LPARAM) name );
+ }
+ else {
+ SendDlgItemMessage( hDlg, iDlgItem, LB_ADDSTRING, 0, (LPARAM) name );
+ }
+ }
+}
+
+void GLT_TagsToList( HWND hDlg, char * tags )
+{
+ char * pc = tags;
+
+ SendDlgItemMessage( hDlg, IDC_GameListTags, LB_RESETCONTENT, 0, 0 );
+
+ while( *pc ) {
+ GLT_AddToList( hDlg, IDC_GameListTags, *pc, -1 );
+ pc++;
+ }
+
+ SendDlgItemMessage( hDlg, IDC_GameListTags, LB_ADDSTRING, 0, (LPARAM) "\t --- Hidden tags ---" );
+
+ pc = GLT_ALL_TAGS;
+
+ while( *pc ) {
+ if( strchr( tags, *pc ) == 0 ) {
+ GLT_AddToList( hDlg, IDC_GameListTags, *pc, -1 );
+ }
+ pc++;
+ }
+
+ SendDlgItemMessage( hDlg, IDC_GameListTags, LB_SETCURSEL, 0, 0 );
+}
+
+char GLT_ListItemToTag( HWND hDlg, int index )
+{
+ char result = '\0';
+ char name[128];
+
+ GLT_Item * list = GLT_ItemInfo;
+
+ if( SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETTEXT, index, (LPARAM) name ) != LB_ERR ) {
+ while( list->id != 0 ) {
+ if( strcmp( list->name, name ) == 0 ) {
+ result = list->id;
+ break;
+ }
+
+ list++;
+ }
+ }
+
+ return result;
+}
+
+void GLT_MoveSelection( HWND hDlg, int delta )
+{
+ int idx1 = (int) SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETCURSEL, 0, 0 );
+ int idx2 = idx1 + delta;
+ int count = (int) SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETCOUNT, 0, 0 );
+
+ if( idx1 >=0 && idx1 < count && idx2 >= 0 && idx2 < count ) {
+ char buf[128];
+
+ SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETTEXT, idx1, (LPARAM) buf );
+ SendDlgItemMessage( hDlg, IDC_GameListTags, LB_DELETESTRING, idx1, 0 );
+ SendDlgItemMessage( hDlg, IDC_GameListTags, LB_INSERTSTRING, idx2, (LPARAM) buf );
+ SendDlgItemMessage( hDlg, IDC_GameListTags, LB_SETCURSEL, idx2, 0 );
+ }
+}
+
+LRESULT CALLBACK GameListOptions_Proc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
+{
+ static char glt[64];
+ static char * lpUserGLT;
+
+ switch( message )
+ {
+ case WM_INITDIALOG:
+ lpUserGLT = (char *) lParam;
+
+ strcpy( glt, lpUserGLT );
+
+ CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));
+
+ /* Initialize list */
+ GLT_TagsToList( hDlg, glt );
+
+ SetFocus( GetDlgItem(hDlg, IDC_GameListTags) );
+
+ break;
+
+ case WM_COMMAND:
+ switch( LOWORD(wParam) ) {
+ case IDOK:
+ {
+ char * pc = lpUserGLT;
+ int idx = 0;
+ int cnt = (int) SendDlgItemMessage( hDlg, IDC_GameListTags, LB_GETCOUNT, 0, 0 );
+ char id;
+
+ do {
+ id = GLT_ListItemToTag( hDlg, idx );
+
+ *pc++ = id;
+ idx++;
+ } while( id != '\0' );
+ }
+ EndDialog( hDlg, 0 );
+ return TRUE;
+ case IDCANCEL:
+ EndDialog( hDlg, 1 );
+ return TRUE;
+
+ case IDC_GLT_Default:
+ strcpy( glt, GLT_DEFAULT_TAGS );
+ GLT_TagsToList( hDlg, glt );
+ return TRUE;
+
+ case IDC_GLT_Restore:
+ strcpy( glt, lpUserGLT );
+ GLT_TagsToList( hDlg, glt );
+ return TRUE;
+
+ case IDC_GLT_Up:
+ GLT_MoveSelection( hDlg, -1 );
+ return TRUE;
+
+ case IDC_GLT_Down:
+ GLT_MoveSelection( hDlg, +1 );
+ return TRUE;
+ }
+
+ break;
+ }
+
+ return FALSE;
+}
+
+int GameListOptions()
+{
+ char glt[64];
+ int result;
+ FARPROC lpProc = MakeProcInstance( (FARPROC) GameListOptions_Proc, hInst );
+
+ strcpy( glt, appData.gameListTags );
+
+ result = DialogBoxParam( hInst, MAKEINTRESOURCE(DLG_GameListOptions), hwndMain, (DLGPROC)lpProc, (LPARAM)glt );
+
+ if( result == 0 ) {
+ /* [AS] Memory leak here! */
+ appData.gameListTags = strdup( glt );
+ }
+
+ return result;
+}
+
\r
VOID\r
DisplayIcsInteractionTitle(char *str)\r
is->kind = cp->kind;\r
/*
[AS] Try to avoid a race condition if the thread is given control too early:
- we create all threads suspended to that the is->hThread variable can be
+ we create all threads suspended so that the is->hThread variable can be
safely assigned, then let the threads start with ResumeThread.
*/
switch (cp->kind) {\r
FARPROC lpProc;\r
char *p, *q;\r
\r
+ /* [AS] */
+ EngineOutputPopUp();
+ return;
+
if (str == NULL) str = "";\r
p = (char *) malloc(2 * strlen(str) + 2);\r
q = p;\r
}\r
\r
void\r
-HistorySet(char movelist[][2*MOVE_LEN], int first, int last, int current)\r
+HistorySet( char movelist[][2*MOVE_LEN], int first, int last, int current )
{\r
- /* Currently not implemented in WinBoard */\r
-}\r
+#if 0
+ char buf[256];
\r
+ sprintf( buf, "HistorySet: first=%d, last=%d, current=%d (%s)\n",
+ first, last, current, current >= 0 ? movelist[current] : "n/a" );
\r
+ OutputDebugString( buf );
+#endif
+
+ MoveHistorySet( movelist, first, last, current, pvInfoList );
+
+ EvalGraphSet( first, last, current, pvInfoList );
+}
+
+void SetProgramStats( int which, int depth, unsigned long nodes, int score, int time, char * pv )
+{
+#if 0
+ char buf[1024];
+
+ sprintf( buf, "SetStats for %d: depth=%d, nodes=%lu, score=%5.2f, time=%5.2f, pv=%s\n",
+ which, depth, nodes, score / 100.0, time / 100.0, pv == 0 ? "n/a" : pv );
+
+ OutputDebugString( buf );
+#endif
+
+ EngineOutputUpdate( which, depth, nodes, score, time, pv );
+}