-/* \r
- * WinBoard.c -- Windows NT front end to XBoard\r
- * $Id$\r
- *\r
- * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.\r
- * Enhancements Copyright 1992-2001 Free 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
- *\r
- * The following terms apply to Digital Equipment Corporation's copyright\r
- * interest in XBoard:\r
- * ------------------------------------------------------------------------\r
- * All Rights Reserved\r
- *\r
- * Permission to use, copy, modify, and distribute this software and its\r
- * documentation for any purpose and without fee is hereby granted,\r
- * provided that the above copyright notice appear in all copies and that\r
- * both that copyright notice and this permission notice appear in\r
- * supporting documentation, and that the name of Digital not be\r
- * used in advertising or publicity pertaining to distribution of the\r
- * software without specific, written prior permission.\r
- *\r
- * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING\r
- * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL\r
- * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR\r
- * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\r
- * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\r
- * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS\r
- * SOFTWARE.\r
- * ------------------------------------------------------------------------\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., 675 Mass Ave, Cambridge, MA 02139, USA.\r
- * ------------------------------------------------------------------------\r
- */\r
-\r
-#include "config.h"\r
-\r
-#include <windows.h>\r
-#include <winuser.h>\r
-#include <winsock.h>\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <malloc.h>\r
-#include <sys/stat.h>\r
-#include <fcntl.h>\r
-#include <math.h>\r
-#include <commdlg.h>\r
-#include <dlgs.h>\r
-#include <richedit.h>\r
-#include <mmsystem.h>\r
-\r
-#if __GNUC__\r
-#include <errno.h>\r
-#include <string.h>\r
-#endif\r
-\r
-#include "common.h"\r
-#include "winboard.h"\r
-#include "frontend.h"\r
-#include "backend.h"\r
-#include "moves.h"\r
-#include "wclipbrd.h"\r
-#include "wgamelist.h"\r
-#include "wedittags.h"\r
-#include "woptions.h"\r
-#include "wsockerr.h"\r
-#include "defaults.h"\r
-\r
-typedef struct {\r
- ChessSquare piece; \r
- POINT pos; /* window coordinates of current pos */\r
- POINT lastpos; /* window coordinates of last pos - used for clipping */\r
- POINT from; /* board coordinates of the piece's orig pos */\r
- POINT to; /* board coordinates of the piece's new pos */\r
-} AnimInfo;\r
-\r
-static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };\r
-\r
-typedef struct {\r
- POINT start; /* window coordinates of start pos */\r
- POINT pos; /* window coordinates of current pos */\r
- POINT lastpos; /* window coordinates of last pos - used for clipping */\r
- POINT from; /* board coordinates of the piece's orig pos */\r
-} DragInfo;\r
-\r
-static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };\r
-\r
-typedef struct {\r
- POINT sq[2]; /* board coordinates of from, to squares */\r
-} HighlightInfo;\r
-\r
-static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };\r
-static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };\r
-\r
-/* Window class names */\r
-char szAppName[] = "WinBoard";\r
-char szConsoleName[] = "WBConsole";\r
-\r
-/* Title bar text */\r
-char szTitle[] = "WinBoard";\r
-char szConsoleTitle[] = "ICS Interaction";\r
-\r
-char *programName;\r
-char *settingsFileName;\r
-BOOLEAN saveSettingsOnExit;\r
-char installDir[MSG_SIZ];\r
-\r
-BoardSize boardSize;\r
-BOOLEAN chessProgram;\r
-static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;\r
-static int squareSize, lineGap;\r
-static int winWidth, winHeight;\r
-static RECT messageRect, whiteRect, blackRect;\r
-static char messageText[MESSAGE_TEXT_MAX];\r
-static int clockTimerEvent = 0;\r
-static int loadGameTimerEvent = 0;\r
-static int analysisTimerEvent = 0;\r
-static DelayedEventCallback delayedTimerCallback;\r
-static int delayedTimerEvent = 0;\r
-static int buttonCount = 2;\r
-char *icsTextMenuString;\r
-char *icsNames;\r
-char *firstChessProgramNames;\r
-char *secondChessProgramNames;\r
-\r
-#define ARG_MAX 20000\r
-\r
-#define PALETTESIZE 256\r
-\r
-HINSTANCE hInst; /* current instance */\r
-HWND hwndMain = NULL; /* root window*/\r
-HWND hwndConsole = NULL;\r
-BOOLEAN alwaysOnTop = FALSE;\r
-RECT boardRect;\r
-COLORREF lightSquareColor, darkSquareColor, whitePieceColor, \r
- blackPieceColor, highlightSquareColor, premoveHighlightColor;\r
-HPALETTE hPal;\r
-ColorClass currentColorClass;\r
-\r
-HWND hCommPort = NULL; /* currently open comm port */\r
-static HWND hwndPause; /* pause button */\r
-static HBITMAP pieceBitmap[3][(int) WhiteKing + 1];\r
-static HBRUSH lightSquareBrush, darkSquareBrush,\r
- whitePieceBrush, blackPieceBrush, iconBkgndBrush, outlineBrush;\r
-static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];\r
-static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];\r
-static HPEN gridPen = NULL;\r
-static HPEN highlightPen = NULL;\r
-static HPEN premovePen = NULL;\r
-static NPLOGPALETTE pLogPal;\r
-static BOOL paletteChanged = FALSE;\r
-static HICON iconWhite, iconBlack, iconCurrent;\r
-static int doingSizing = FALSE;\r
-static int lastSizing = 0;\r
-static int prevStderrPort;\r
-\r
-#if __GNUC__ && !defined(_winmajor)\r
-#define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */\r
-#else\r
-#define oldDialog (_winmajor < 4)\r
-#endif\r
-\r
-char *defaultTextAttribs[] = \r
-{\r
- COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,\r
- COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,\r
- COLOR_NONE\r
-};\r
-\r
-typedef struct {\r
- char *name;\r
- int squareSize;\r
- int lineGap;\r
- int smallLayout;\r
- int tinyLayout;\r
- int cliWidth, cliHeight;\r
-} SizeInfo;\r
-\r
-SizeInfo sizeInfo[] = \r
-{\r
- { "tiny", 21, 0, 1, 1, 0, 0 },\r
- { "teeny", 25, 1, 1, 1, 0, 0 },\r
- { "dinky", 29, 1, 1, 1, 0, 0 },\r
- { "petite", 33, 1, 1, 1, 0, 0 },\r
- { "slim", 37, 2, 1, 0, 0, 0 },\r
- { "small", 40, 2, 1, 0, 0, 0 },\r
- { "mediocre", 45, 2, 1, 0, 0, 0 },\r
- { "middling", 49, 2, 0, 0, 0, 0 },\r
- { "average", 54, 2, 0, 0, 0, 0 },\r
- { "moderate", 58, 3, 0, 0, 0, 0 },\r
- { "medium", 64, 3, 0, 0, 0, 0 },\r
- { "bulky", 72, 3, 0, 0, 0, 0 },\r
- { "large", 80, 3, 0, 0, 0, 0 },\r
- { "big", 87, 3, 0, 0, 0, 0 },\r
- { "huge", 95, 3, 0, 0, 0, 0 },\r
- { "giant", 108, 3, 0, 0, 0, 0 },\r
- { "colossal", 116, 4, 0, 0, 0, 0 },\r
- { "titanic", 129, 4, 0, 0, 0, 0 },\r
- { NULL, 0, 0, 0, 0, 0, 0 }\r
-};\r
-\r
-#define MF(x) {x, {0, }, {0, }, 0}\r
-MyFont fontRec[NUM_SIZES][NUM_FONTS] =\r
-{\r
- { MF(CLOCK_FONT_TINY), MF(MESSAGE_FONT_TINY), \r
- MF(COORD_FONT_TINY), MF(CONSOLE_FONT_TINY),\r
- MF(COMMENT_FONT_TINY), MF(EDITTAGS_FONT_TINY) },\r
- { MF(CLOCK_FONT_TEENY), MF(MESSAGE_FONT_TEENY), \r
- MF(COORD_FONT_TEENY), MF(CONSOLE_FONT_TEENY),\r
- MF(COMMENT_FONT_TEENY), MF(EDITTAGS_FONT_TEENY) },\r
- { MF(CLOCK_FONT_DINKY), MF(MESSAGE_FONT_DINKY),\r
- MF(COORD_FONT_DINKY), MF(CONSOLE_FONT_DINKY),\r
- MF(COMMENT_FONT_DINKY), MF(EDITTAGS_FONT_DINKY) },\r
- { MF(CLOCK_FONT_PETITE), MF(MESSAGE_FONT_PETITE),\r
- MF(COORD_FONT_PETITE), MF(CONSOLE_FONT_PETITE),\r
- MF(COMMENT_FONT_PETITE), MF(EDITTAGS_FONT_PETITE) },\r
- { MF(CLOCK_FONT_SLIM), MF(MESSAGE_FONT_SLIM),\r
- MF(COORD_FONT_SLIM), MF(CONSOLE_FONT_SLIM),\r
- MF(COMMENT_FONT_SLIM), MF(EDITTAGS_FONT_SLIM) },\r
- { MF(CLOCK_FONT_SMALL), MF(MESSAGE_FONT_SMALL),\r
- MF(COORD_FONT_SMALL), MF(CONSOLE_FONT_SMALL),\r
- MF(COMMENT_FONT_SMALL), MF(EDITTAGS_FONT_SMALL) },\r
- { MF(CLOCK_FONT_MEDIOCRE), MF(MESSAGE_FONT_MEDIOCRE),\r
- MF(COORD_FONT_MEDIOCRE), MF(CONSOLE_FONT_MEDIOCRE),\r
- MF(COMMENT_FONT_MEDIOCRE), MF(EDITTAGS_FONT_MEDIOCRE) },\r
- { MF(CLOCK_FONT_MIDDLING), MF(MESSAGE_FONT_MIDDLING),\r
- MF(COORD_FONT_MIDDLING), MF(CONSOLE_FONT_MIDDLING),\r
- MF(COMMENT_FONT_MIDDLING), MF(EDITTAGS_FONT_MIDDLING) },\r
- { MF(CLOCK_FONT_AVERAGE), MF(MESSAGE_FONT_AVERAGE),\r
- MF(COORD_FONT_AVERAGE), MF(CONSOLE_FONT_AVERAGE),\r
- MF(COMMENT_FONT_AVERAGE), MF(EDITTAGS_FONT_AVERAGE) },\r
- { MF(CLOCK_FONT_MODERATE), MF(MESSAGE_FONT_MODERATE),\r
- MF(COORD_FONT_MODERATE), MF(CONSOLE_FONT_MODERATE),\r
- MF(COMMENT_FONT_MODERATE), MF(EDITTAGS_FONT_MODERATE) },\r
- { MF(CLOCK_FONT_MEDIUM), MF(MESSAGE_FONT_MEDIUM),\r
- MF(COORD_FONT_MEDIUM), MF(CONSOLE_FONT_MEDIUM),\r
- MF(COMMENT_FONT_MEDIUM), MF(EDITTAGS_FONT_MEDIUM) },\r
- { MF(CLOCK_FONT_BULKY), MF(MESSAGE_FONT_BULKY),\r
- MF(COORD_FONT_BULKY), MF(CONSOLE_FONT_BULKY),\r
- MF(COMMENT_FONT_BULKY), MF(EDITTAGS_FONT_BULKY) },\r
- { MF(CLOCK_FONT_LARGE), MF(MESSAGE_FONT_LARGE),\r
- MF(COORD_FONT_LARGE), MF(CONSOLE_FONT_LARGE),\r
- MF(COMMENT_FONT_LARGE), MF(EDITTAGS_FONT_LARGE) },\r
- { MF(CLOCK_FONT_BIG), MF(MESSAGE_FONT_BIG),\r
- MF(COORD_FONT_BIG), MF(CONSOLE_FONT_BIG),\r
- MF(COMMENT_FONT_BIG), MF(EDITTAGS_FONT_BIG) },\r
- { MF(CLOCK_FONT_HUGE), MF(MESSAGE_FONT_HUGE),\r
- MF(COORD_FONT_HUGE), MF(CONSOLE_FONT_HUGE),\r
- MF(COMMENT_FONT_HUGE), MF(EDITTAGS_FONT_HUGE) },\r
- { MF(CLOCK_FONT_GIANT), MF(MESSAGE_FONT_GIANT),\r
- MF(COORD_FONT_GIANT), MF(CONSOLE_FONT_GIANT),\r
- MF(COMMENT_FONT_GIANT), MF(EDITTAGS_FONT_GIANT) },\r
- { MF(CLOCK_FONT_COLOSSAL), MF(MESSAGE_FONT_COLOSSAL),\r
- MF(COORD_FONT_COLOSSAL), MF(CONSOLE_FONT_COLOSSAL),\r
- MF(COMMENT_FONT_COLOSSAL), MF(EDITTAGS_FONT_COLOSSAL) },\r
- { MF(CLOCK_FONT_TITANIC), MF(MESSAGE_FONT_TITANIC),\r
- MF(COORD_FONT_TITANIC), MF(CONSOLE_FONT_TITANIC),\r
- MF(COMMENT_FONT_TITANIC), MF(EDITTAGS_FONT_TITANIC) },\r
-};\r
-\r
-MyFont *font[NUM_SIZES][NUM_FONTS];\r
-\r
-typedef struct {\r
- char *label;\r
- int id;\r
- HWND hwnd;\r
- WNDPROC wndproc;\r
-} MyButtonDesc;\r
-\r
-#define BUTTON_WIDTH (tinyLayout ? 16 : 32)\r
-#define N_BUTTONS 5\r
-\r
-MyButtonDesc buttonDesc[N_BUTTONS] =\r
-{\r
- {"<<", IDM_ToStart, NULL, NULL},\r
- {"<", IDM_Backward, NULL, NULL},\r
- {"P", IDM_Pause, NULL, NULL},\r
- {">", IDM_Forward, NULL, NULL},\r
- {">>", IDM_ToEnd, NULL, NULL},\r
-};\r
-\r
-int tinyLayout = 0, smallLayout = 0;\r
-#define MENU_BAR_ITEMS 6\r
-char *menuBarText[2][MENU_BAR_ITEMS+1] = {\r
- { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },\r
- { "&F", "&M", "&A", "&S", "&O", "&H", NULL },\r
-};\r
-\r
-\r
-MySound sounds[(int)NSoundClasses];\r
-MyTextAttribs textAttribs[(int)NColorClasses];\r
-\r
-MyColorizeAttribs colorizeAttribs[] = {\r
- { (COLORREF)0, 0, "Shout Text" },\r
- { (COLORREF)0, 0, "SShout/CShout" },\r
- { (COLORREF)0, 0, "Channel 1 Text" },\r
- { (COLORREF)0, 0, "Channel Text" },\r
- { (COLORREF)0, 0, "Kibitz Text" },\r
- { (COLORREF)0, 0, "Tell Text" },\r
- { (COLORREF)0, 0, "Challenge Text" },\r
- { (COLORREF)0, 0, "Request Text" },\r
- { (COLORREF)0, 0, "Seek Text" },\r
- { (COLORREF)0, 0, "Normal Text" },\r
- { (COLORREF)0, 0, "None" }\r
-};\r
-\r
-\r
-\r
-static char *commentTitle;\r
-static char *commentText;\r
-static int commentIndex;\r
-static Boolean editComment = FALSE;\r
-HWND commentDialog = NULL;\r
-BOOLEAN commentDialogUp = FALSE;\r
-static int commentX, commentY, commentH, commentW;\r
-\r
-static char *analysisTitle;\r
-static char *analysisText;\r
-HWND analysisDialog = NULL;\r
-BOOLEAN analysisDialogUp = FALSE;\r
-static int analysisX, analysisY, analysisH, analysisW;\r
-\r
-char errorTitle[MSG_SIZ];\r
-char errorMessage[2*MSG_SIZ];\r
-HWND errorDialog = NULL;\r
-BOOLEAN moveErrorMessageUp = FALSE;\r
-BOOLEAN consoleEcho = TRUE;\r
-CHARFORMAT consoleCF;\r
-COLORREF consoleBackgroundColor;\r
-\r
-char *programVersion;\r
-\r
-#define CPReal 1\r
-#define CPComm 2\r
-#define CPSock 3\r
-#define CPRcmd 4\r
-typedef int CPKind;\r
-\r
-typedef struct {\r
- CPKind kind;\r
- HANDLE hProcess;\r
- DWORD pid;\r
- HANDLE hTo;\r
- HANDLE hFrom;\r
- SOCKET sock;\r
- SOCKET sock2; /* stderr socket for OpenRcmd */\r
-} ChildProc;\r
-\r
-#define INPUT_SOURCE_BUF_SIZE 4096\r
-\r
-typedef struct _InputSource {\r
- CPKind kind;\r
- HANDLE hFile;\r
- SOCKET sock;\r
- int lineByLine;\r
- HANDLE hThread;\r
- DWORD id;\r
- char buf[INPUT_SOURCE_BUF_SIZE];\r
- char *next;\r
- DWORD count;\r
- int error;\r
- InputCallback func;\r
- struct _InputSource *second; /* for stderr thread on CPRcmd */\r
- VOIDSTAR closure;\r
-} InputSource;\r
-\r
-InputSource *consoleInputSource;\r
-\r
-DCB dcb;\r
-\r
-/* forward */\r
-VOID ConsoleOutput(char* data, int length, int forceVisible);\r
-VOID ConsoleCreate();\r
-LRESULT CALLBACK\r
- ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
-VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);\r
-VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);\r
-VOID ParseCommSettings(char *arg, DCB *dcb);\r
-LRESULT CALLBACK\r
- StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);\r
-VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);\r
-void ParseIcsTextMenu(char *icsTextMenuString);\r
-VOID PopUpMoveDialog(char firstchar);\r
-VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);\r
-\r
-/*\r
- * Setting "frozen" should disable all user input other than deleting\r
- * the window. We do this while engines are initializing themselves.\r
- */\r
-static int frozen = 0;\r
-static int oldMenuItemState[MENU_BAR_ITEMS];\r
-void FreezeUI()\r
-{\r
- HMENU hmenu;\r
- int i;\r
-\r
- if (frozen) return;\r
- frozen = 1;\r
- hmenu = GetMenu(hwndMain);\r
- for (i=0; i<MENU_BAR_ITEMS; i++) {\r
- oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);\r
- }\r
- DrawMenuBar(hwndMain);\r
-}\r
-\r
-/* Undo a FreezeUI */\r
-void ThawUI()\r
-{\r
- HMENU hmenu;\r
- int i;\r
-\r
- if (!frozen) return;\r
- frozen = 0;\r
- hmenu = GetMenu(hwndMain);\r
- for (i=0; i<MENU_BAR_ITEMS; i++) {\r
- EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);\r
- }\r
- DrawMenuBar(hwndMain);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * WinMain\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-int APIENTRY\r
-WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,\r
- LPSTR lpCmdLine, int nCmdShow)\r
-{\r
- MSG msg;\r
- HANDLE hAccelMain, hAccelNoAlt;\r
-\r
- debugFP = stderr;\r
-\r
- LoadLibrary("RICHED32.DLL");\r
- consoleCF.cbSize = sizeof(CHARFORMAT);\r
-\r
- if (!InitApplication(hInstance)) {\r
- return (FALSE);\r
- }\r
- if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {\r
- return (FALSE);\r
- }\r
-\r
- hAccelMain = LoadAccelerators (hInstance, szAppName);\r
- hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");\r
-\r
- /* Acquire and dispatch messages until a WM_QUIT message is received. */\r
-\r
- while (GetMessage(&msg, /* message structure */\r
- NULL, /* handle of window receiving the message */\r
- 0, /* lowest message to examine */\r
- 0)) /* highest message to examine */\r
- {\r
- if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&\r
- !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&\r
- !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&\r
- !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&\r
- !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&\r
- !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {\r
- TranslateMessage(&msg); /* Translates virtual key codes */\r
- DispatchMessage(&msg); /* Dispatches message to window */\r
- }\r
- }\r
-\r
-\r
- return (msg.wParam); /* Returns the value from PostQuitMessage */\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Initialization functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-BOOL\r
-InitApplication(HINSTANCE hInstance)\r
-{\r
- WNDCLASS wc;\r
-\r
- /* Fill in window class structure with parameters that describe the */\r
- /* main window. */\r
-\r
- wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */\r
- wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */\r
- wc.cbClsExtra = 0; /* No per-class extra data. */\r
- wc.cbWndExtra = 0; /* No per-window extra data. */\r
- wc.hInstance = hInstance; /* Owner of this class */\r
- wc.hIcon = LoadIcon(hInstance, "icon_white");\r
- wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */\r
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */\r
- wc.lpszMenuName = szAppName; /* Menu name from .RC */\r
- wc.lpszClassName = szAppName; /* Name to register as */\r
-\r
- /* Register the window class and return success/failure code. */\r
- if (!RegisterClass(&wc)) return FALSE;\r
-\r
- wc.style = CS_HREDRAW | CS_VREDRAW;\r
- wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;\r
- wc.cbClsExtra = 0;\r
- wc.cbWndExtra = DLGWINDOWEXTRA;\r
- wc.hInstance = hInstance;\r
- wc.hIcon = LoadIcon(hInstance, "icon_white");\r
- wc.hCursor = LoadCursor(NULL, IDC_ARROW);\r
- wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);\r
- wc.lpszMenuName = NULL;\r
- wc.lpszClassName = szConsoleName;\r
-\r
- if (!RegisterClass(&wc)) return FALSE;\r
- return TRUE;\r
-}\r
-\r
-\r
-/* Set by InitInstance, used by EnsureOnScreen */\r
-int screenHeight, screenWidth;\r
-\r
-void\r
-EnsureOnScreen(int *x, int *y)\r
-{\r
- /* Be sure window at (x,y) is not off screen (or even mostly off screen) */\r
- if (*x > screenWidth - 32) *x = 0;\r
- if (*y > screenHeight - 32) *y = 0;\r
-}\r
-\r
-BOOL\r
-InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)\r
-{\r
- HWND hwnd; /* Main window handle. */\r
- int ibs;\r
- WINDOWPLACEMENT wp;\r
- char *filepart;\r
-\r
- hInst = hInstance; /* Store instance handle in our global variable */\r
-\r
- if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {\r
- *filepart = NULLCHAR;\r
- } else {\r
- GetCurrentDirectory(MSG_SIZ, installDir);\r
- }\r
- InitAppData(lpCmdLine); /* Get run-time parameters */\r
- if (appData.debugMode) {\r
- debugFP = fopen("winboard.debug", "w");\r
- setbuf(debugFP, NULL);\r
- }\r
-\r
- InitBackEnd1();\r
-\r
- /* Create a main window for this application instance. */\r
- hwnd = CreateWindow(szAppName, szTitle,\r
- (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),\r
- CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,\r
- NULL, NULL, hInstance, NULL);\r
- hwndMain = hwnd;\r
-\r
- /* If window could not be created, return "failure" */\r
- if (!hwnd) {\r
- return (FALSE);\r
- }\r
-\r
- iconWhite = LoadIcon(hInstance, "icon_white");\r
- iconBlack = LoadIcon(hInstance, "icon_black");\r
- iconCurrent = iconWhite;\r
- InitDrawingColors();\r
- screenHeight = GetSystemMetrics(SM_CYSCREEN);\r
- screenWidth = GetSystemMetrics(SM_CXSCREEN);\r
- for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {\r
- /* Compute window size for each board size, and use the largest\r
- size that fits on this screen as the default. */\r
- InitDrawingSizes((BoardSize)ibs, 0);\r
- if (boardSize == (BoardSize)-1 &&\r
- winHeight <= screenHeight && winWidth <= screenWidth) {\r
- boardSize = (BoardSize)ibs;\r
- }\r
- }\r
- InitDrawingSizes(boardSize, 0);\r
- InitMenuChecks();\r
- buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);\r
-\r
- InitBackEnd2();\r
-\r
- /* Make the window visible; update its client area; and return "success" */\r
- EnsureOnScreen(&boardX, &boardY);\r
- wp.length = sizeof(WINDOWPLACEMENT);\r
- wp.flags = 0;\r
- wp.showCmd = nCmdShow;\r
- wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
- wp.rcNormalPosition.left = boardX;\r
- wp.rcNormalPosition.right = boardX + winWidth;\r
- wp.rcNormalPosition.top = boardY;\r
- wp.rcNormalPosition.bottom = boardY + winHeight;\r
- SetWindowPlacement(hwndMain, &wp);\r
-\r
- SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
- 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
- if (hwndConsole) {\r
-#if AOT_CONSOLE\r
- SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,\r
- 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);\r
-#endif\r
- ShowWindow(hwndConsole, nCmdShow);\r
- }\r
- UpdateWindow(hwnd);\r
-\r
- return TRUE;\r
-\r
-}\r
-\r
-\r
-typedef enum {\r
- ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone, \r
- ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,\r
- ArgSettingsFilename\r
-} ArgType;\r
-\r
-typedef struct {\r
- char *argName;\r
- ArgType argType;\r
- /***\r
- union {\r
- String *pString; // ArgString\r
- int *pInt; // ArgInt\r
- float *pFloat; // ArgFloat\r
- Boolean *pBoolean; // ArgBoolean\r
- COLORREF *pColor; // ArgColor\r
- ColorClass cc; // ArgAttribs\r
- String *pFilename; // ArgFilename\r
- BoardSize *pBoardSize; // ArgBoardSize\r
- int whichFont; // ArgFont\r
- DCB *pDCB; // ArgCommSettings\r
- String *pFilename; // ArgSettingsFilename\r
- } argLoc;\r
- ***/\r
- LPVOID argLoc;\r
- BOOL save;\r
-} ArgDescriptor;\r
-\r
-int junk;\r
-ArgDescriptor argDescriptors[] = {\r
- /* positional arguments */\r
- { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
- { "", ArgNone, NULL },\r
- /* keyword arguments */\r
- { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },\r
- { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },\r
- { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },\r
- { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },\r
- { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },\r
- { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },\r
- { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },\r
- { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },\r
- { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },\r
- { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },\r
- { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },\r
- { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },\r
- { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },\r
- { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },\r
- { "initString", ArgString, (LPVOID) &appData.initString, FALSE },\r
- { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },\r
- { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },\r
- { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,\r
- FALSE },\r
- { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,\r
- FALSE },\r
- { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,\r
- FALSE },\r
- { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },\r
- { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,\r
- FALSE },\r
- { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },\r
- { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
- { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
- { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
- { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },\r
- { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },\r
- { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },\r
- { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },\r
- { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },\r
- { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },\r
- { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },\r
- { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },\r
- { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },\r
- { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },\r
- { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },\r
- { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },\r
- { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },\r
- /*!!bitmapDirectory?*/\r
- { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },\r
- { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },\r
- { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },\r
- { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },\r
- { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },\r
- { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },\r
- { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },\r
- { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },\r
- { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },\r
- { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },\r
- { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },\r
- { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },\r
- { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },\r
- { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },\r
- { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },\r
- { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },\r
- { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },\r
- { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },\r
- { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
- { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
- { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
- { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },\r
- { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },\r
- { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },\r
- { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },\r
- { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },\r
- { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },\r
- { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },\r
- { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },\r
- { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },\r
- { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },\r
- { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
- { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },\r
- { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },\r
- { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },\r
- { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },\r
- { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },\r
- { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },\r
- { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },\r
- { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },\r
- { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },\r
- { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },\r
- { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },\r
- { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },\r
- { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },\r
- { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },\r
- { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },\r
- { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },\r
- { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },\r
- { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },\r
- { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },\r
- { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },\r
- { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },\r
- { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },\r
- { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },\r
- { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },\r
- { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },\r
- { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },\r
- { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },\r
- { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },\r
- { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },\r
- { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },\r
- { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },\r
- { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },\r
- { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },\r
- { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },\r
- { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },\r
- { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },\r
- { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },\r
- { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },\r
- { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },\r
- { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },\r
- { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },\r
- { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },\r
- { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },\r
- { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },\r
- { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },\r
- { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },\r
- { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },\r
- { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },\r
- { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },\r
- { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },\r
- { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },\r
- { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },\r
- { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },\r
- { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },\r
- { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },\r
- { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },\r
- { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },\r
- { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },\r
- { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },\r
- { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },\r
- { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },\r
- { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, \r
- FALSE }, /* only so that old WinBoard.ini files from betas can be read */\r
- { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },\r
- { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },\r
- { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },\r
- { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },\r
- { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },\r
- { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },\r
- { "boardSize", ArgBoardSize, (LPVOID) &boardSize,\r
- TRUE }, /* must come after all fonts */\r
- { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },\r
- { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,\r
- FALSE }, /* historical; kept only so old winboard.ini files will parse */\r
- { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },\r
- { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },\r
- { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },\r
- { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },\r
- { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },\r
- { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },\r
- { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },\r
- { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },\r
- { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },\r
- { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },\r
- { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },\r
- { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },\r
- { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },\r
- { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },\r
- { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },\r
- { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },\r
- { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },\r
- { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },\r
- { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },\r
- { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },\r
- { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },\r
- { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },\r
- { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },\r
- { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },\r
- { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },\r
- { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },\r
- { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },\r
- { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },\r
-#if 0\r
- { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },\r
- { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },\r
-#endif\r
- { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },\r
- { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },\r
- { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },\r
- { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },\r
- { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },\r
- { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },\r
- { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },\r
- { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },\r
- { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },\r
- { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },\r
- { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },\r
- { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },\r
- { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },\r
- { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },\r
- { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },\r
- { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },\r
- { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },\r
- { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },\r
- { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },\r
- { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },\r
- { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },\r
- { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },\r
- { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },\r
- { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },\r
- { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },\r
- { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },\r
- { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },\r
- { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },\r
- { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },\r
- { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },\r
- { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },\r
- { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },\r
- { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },\r
- { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },\r
- { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},\r
- { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},\r
- { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},\r
- { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},\r
- { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},\r
- { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},\r
- { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},\r
- { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },\r
- { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },\r
- { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },\r
- { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },\r
- { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },\r
- { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },\r
- { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },\r
- { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },\r
- { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },\r
- { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },\r
- { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },\r
- { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },\r
- { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },\r
- { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },\r
- { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },\r
- { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },\r
- { "highlightLastMove", ArgBoolean,\r
- (LPVOID) &appData.highlightLastMove, TRUE },\r
- { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },\r
- { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },\r
- { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },\r
- { "highlightDragging", ArgBoolean,\r
- (LPVOID) &appData.highlightDragging, TRUE },\r
- { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },\r
- { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },\r
- { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },\r
- { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },\r
- { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },\r
- { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },\r
- { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },\r
- { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },\r
- { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },\r
- { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },\r
- { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },\r
- { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },\r
- { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },\r
- { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },\r
- { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },\r
- { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },\r
- { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },\r
- { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },\r
- { "soundShout", ArgFilename,\r
- (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },\r
- { "soundSShout", ArgFilename,\r
- (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },\r
- { "soundChannel1", ArgFilename,\r
- (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },\r
- { "soundChannel", ArgFilename,\r
- (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },\r
- { "soundKibitz", ArgFilename,\r
- (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },\r
- { "soundTell", ArgFilename,\r
- (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },\r
- { "soundChallenge", ArgFilename,\r
- (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },\r
- { "soundRequest", ArgFilename,\r
- (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },\r
- { "soundSeek", ArgFilename,\r
- (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },\r
- { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },\r
- { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },\r
- { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },\r
- { "soundIcsLoss", ArgFilename, \r
- (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },\r
- { "soundIcsDraw", ArgFilename, \r
- (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },\r
- { "soundIcsUnfinished", ArgFilename, \r
- (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},\r
- { "soundIcsAlarm", ArgFilename, \r
- (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },\r
- { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },\r
- { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },\r
- { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },\r
- { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },\r
- { "reuseChessPrograms", ArgBoolean,\r
- (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */\r
- { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },\r
- { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },\r
- { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },\r
- { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },\r
- { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },\r
- { "x", ArgInt, (LPVOID) &boardX, TRUE },\r
- { "y", ArgInt, (LPVOID) &boardY, TRUE },\r
- { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },\r
- { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },\r
- { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },\r
- { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },\r
- { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },\r
- { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },\r
- { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },\r
- { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },\r
- { "commentX", ArgInt, (LPVOID) &commentX, TRUE },\r
- { "commentY", ArgInt, (LPVOID) &commentY, TRUE },\r
- { "commentW", ArgInt, (LPVOID) &commentW, TRUE },\r
- { "commentH", ArgInt, (LPVOID) &commentH, TRUE },\r
- { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },\r
- { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },\r
- { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },\r
- { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },\r
- { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },\r
- { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },\r
- { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },\r
- { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },\r
- { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },\r
- { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },\r
- { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },\r
- { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },\r
- { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },\r
- { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },\r
- { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },\r
- { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },\r
- { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },\r
- { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,\r
- TRUE },\r
- { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,\r
- TRUE },\r
- { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },\r
- { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },\r
- { "variant", ArgString, (LPVOID) &appData.variant, FALSE },\r
- { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion,\r
- FALSE },\r
- { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,\r
- FALSE },\r
- { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },\r
- { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },\r
- { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },\r
- { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },\r
-#ifdef ZIPPY\r
- { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },\r
- { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },\r
- { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },\r
- { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },\r
- { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },\r
- { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },\r
- { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },\r
- { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },\r
- { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },\r
- { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },\r
- { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },\r
- { "zippyPassword2", ArgString, (LPVOID) &appData.zippyPassword2, FALSE },\r
- { "zippyWrongPassword", ArgString, (LPVOID) &appData.zippyWrongPassword,\r
- FALSE },\r
- { "zippyAcceptOnly", ArgString, (LPVOID) &appData.zippyAcceptOnly, FALSE },\r
- { "zippyUseI", ArgBoolean, (LPVOID) &appData.zippyUseI, FALSE },\r
- { "zui", ArgTrue, (LPVOID) &appData.zippyUseI, FALSE },\r
- { "xzui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },\r
- { "-zui", ArgFalse, (LPVOID) &appData.zippyUseI, FALSE },\r
- { "zippyBughouse", ArgInt, (LPVOID) &appData.zippyBughouse, FALSE },\r
- { "zippyNoplayCrafty", ArgBoolean, (LPVOID) &appData.zippyNoplayCrafty,\r
- FALSE },\r
- { "znc", ArgTrue, (LPVOID) &appData.zippyNoplayCrafty, FALSE },\r
- { "xznc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },\r
- { "-znc", ArgFalse, (LPVOID) &appData.zippyNoplayCrafty, FALSE },\r
- { "zippyGameEnd", ArgString, (LPVOID) &appData.zippyGameEnd, FALSE },\r
- { "zippyGameStart", ArgString, (LPVOID) &appData.zippyGameStart, FALSE },\r
- { "zippyAdjourn", ArgBoolean, (LPVOID) &appData.zippyAdjourn, FALSE },\r
- { "zadj", ArgTrue, (LPVOID) &appData.zippyAdjourn, FALSE },\r
- { "xzadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },\r
- { "-zadj", ArgFalse, (LPVOID) &appData.zippyAdjourn, FALSE },\r
- { "zippyAbort", ArgBoolean, (LPVOID) &appData.zippyAbort, FALSE },\r
- { "zab", ArgTrue, (LPVOID) &appData.zippyAbort, FALSE },\r
- { "xzab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },\r
- { "-zab", ArgFalse, (LPVOID) &appData.zippyAbort, FALSE },\r
- { "zippyVariants", ArgString, (LPVOID) &appData.zippyVariants, FALSE },\r
- { "zippyMaxGames", ArgInt, (LPVOID)&appData.zippyMaxGames, FALSE },\r
- { "zippyReplayTimeout", ArgInt, (LPVOID)&appData.zippyReplayTimeout, FALSE },\r
- /* Kludge to allow winboard.ini files from buggy 4.0.4 to be read: */\r
- { "zippyReplyTimeout", ArgInt, (LPVOID)&junk, FALSE },\r
-#endif\r
- { NULL, ArgNone, NULL, FALSE }\r
-};\r
-\r
-\r
-/* Kludge for indirection files on command line */\r
-char* lastIndirectionFilename;\r
-ArgDescriptor argDescriptorIndirection =\r
-{ "", ArgSettingsFilename, (LPVOID) NULL, FALSE };\r
-\r
-\r
-VOID\r
-ExitArgError(char *msg, char *badArg)\r
-{\r
- char buf[MSG_SIZ];\r
-\r
- sprintf(buf, "%s %s", msg, badArg);\r
- DisplayFatalError(buf, 0, 2);\r
- exit(2);\r
-}\r
-\r
-/* Command line font name parser. NULL name means do nothing.\r
- Syntax like "Courier New:10.0 bi" or "Arial:10" or "Arial:10b"\r
- For backward compatibility, syntax without the colon is also\r
- accepted, but font names with digits in them won't work in that case.\r
-*/\r
-VOID\r
-ParseFontName(char *name, MyFontParams *mfp)\r
-{\r
- char *p, *q;\r
- if (name == NULL) return;\r
- p = name;\r
- q = strchr(p, ':');\r
- if (q) {\r
- if (q - p >= sizeof(mfp->faceName))\r
- ExitArgError("Font name too long:", name);\r
- memcpy(mfp->faceName, p, q - p);\r
- mfp->faceName[q - p] = NULLCHAR;\r
- p = q + 1;\r
- } else {\r
- q = mfp->faceName;\r
- while (*p && !isdigit(*p)) {\r
- *q++ = *p++;\r
- if (q - mfp->faceName >= sizeof(mfp->faceName))\r
- ExitArgError("Font name too long:", name);\r
- }\r
- while (q > mfp->faceName && q[-1] == ' ') q--;\r
- *q = NULLCHAR;\r
- }\r
- if (!*p) ExitArgError("Font point size missing:", name);\r
- mfp->pointSize = (float) atof(p);\r
- mfp->bold = (strchr(p, 'b') != NULL);\r
- mfp->italic = (strchr(p, 'i') != NULL);\r
- mfp->underline = (strchr(p, 'u') != NULL);\r
- mfp->strikeout = (strchr(p, 's') != NULL);\r
-}\r
-\r
-/* Color name parser.\r
- X version accepts X color names, but this one\r
- handles only the #rrggbb form (hex) or rrr,ggg,bbb (decimal) */\r
-COLORREF\r
-ParseColorName(char *name)\r
-{\r
- int red, green, blue, count;\r
- char buf[MSG_SIZ];\r
-\r
- count = sscanf(name, "#%2x%2x%2x", &red, &green, &blue);\r
- if (count != 3) {\r
- count = sscanf(name, "%3d%*[^0-9]%3d%*[^0-9]%3d", \r
- &red, &green, &blue);\r
- }\r
- if (count != 3) {\r
- sprintf(buf, "Can't parse color name %s", name);\r
- DisplayError(buf, 0);\r
- return RGB(0, 0, 0);\r
- }\r
- return PALETTERGB(red, green, blue);\r
-}\r
-\r
-\r
-void ParseAttribs(COLORREF *color, int *effects, char* argValue)\r
-{\r
- char *e = argValue;\r
- int eff = 0;\r
-\r
- while (*e) {\r
- if (*e == 'b') eff |= CFE_BOLD;\r
- else if (*e == 'i') eff |= CFE_ITALIC;\r
- else if (*e == 'u') eff |= CFE_UNDERLINE;\r
- else if (*e == 's') eff |= CFE_STRIKEOUT;\r
- else if (*e == '#' || isdigit(*e)) break;\r
- e++;\r
- }\r
- *effects = eff;\r
- *color = ParseColorName(e);\r
-}\r
-\r
-\r
-BoardSize\r
-ParseBoardSize(char *name)\r
-{\r
- BoardSize bs = SizeTiny;\r
- while (sizeInfo[bs].name != NULL) {\r
- if (StrCaseCmp(name, sizeInfo[bs].name) == 0) return bs;\r
- bs++;\r
- }\r
- ExitArgError("Unrecognized board size value", name);\r
- return bs; /* not reached */\r
-}\r
-\r
-\r
-char\r
-StringGet(void *getClosure)\r
-{\r
- char **p = (char **) getClosure;\r
- return *((*p)++);\r
-}\r
-\r
-char\r
-FileGet(void *getClosure)\r
-{\r
- int c;\r
- FILE* f = (FILE*) getClosure;\r
-\r
- c = getc(f);\r
- if (c == EOF)\r
- return NULLCHAR;\r
- else\r
- return (char) c;\r
-}\r
-\r
-/* Parse settings file named "name". If file found, return the\r
- full name in fullname and return TRUE; else return FALSE */\r
-BOOLEAN\r
-ParseSettingsFile(char *name, char fullname[MSG_SIZ])\r
-{\r
- char *dummy;\r
- FILE *f;\r
-\r
- if (SearchPath(installDir, name, NULL, MSG_SIZ, fullname, &dummy)) {\r
- f = fopen(fullname, "r");\r
- if (f != NULL) {\r
- ParseArgs(FileGet, f);\r
- fclose(f);\r
- return TRUE;\r
- }\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-ParseArgs(GetFunc get, void *cl)\r
-{\r
- char argName[ARG_MAX];\r
- char argValue[ARG_MAX];\r
- ArgDescriptor *ad;\r
- char start;\r
- char *q;\r
- int i, octval;\r
- char ch;\r
- int posarg = 0;\r
-\r
- ch = get(cl);\r
- for (;;) {\r
- while (ch == ' ' || ch == '\n' || ch == '\t') ch = get(cl);\r
- if (ch == NULLCHAR) break;\r
- if (ch == ';') {\r
- /* Comment to end of line */\r
- ch = get(cl);\r
- while (ch != '\n' && ch != NULLCHAR) ch = get(cl);\r
- continue;\r
- } else if (ch == '/' || ch == '-') {\r
- /* Switch */\r
- q = argName;\r
- while (ch != ' ' && ch != '=' && ch != ':' && ch != NULLCHAR &&\r
- ch != '\n' && ch != '\t') {\r
- *q++ = ch;\r
- ch = get(cl);\r
- }\r
- *q = NULLCHAR;\r
-\r
- for (ad = argDescriptors; ad->argName != NULL; ad++)\r
- if (strcmp(ad->argName, argName + 1) == 0) break;\r
-\r
- if (ad->argName == NULL)\r
- ExitArgError("Unrecognized argument", argName);\r
-\r
- } else if (ch == '@') {\r
- /* Indirection file */\r
- ad = &argDescriptorIndirection;\r
- ch = get(cl);\r
- } else {\r
- /* Positional argument */\r
- ad = &argDescriptors[posarg++];\r
- strcpy(argName, ad->argName);\r
- }\r
-\r
- if (ad->argType == ArgTrue) {\r
- *(Boolean *) ad->argLoc = TRUE;\r
- continue;\r
- }\r
- if (ad->argType == ArgFalse) {\r
- *(Boolean *) ad->argLoc = FALSE;\r
- continue;\r
- }\r
-\r
- while (ch == ' ' || ch == '=' || ch == ':' || ch == '\t') ch = get(cl);\r
- if (ch == NULLCHAR || ch == '\n') {\r
- ExitArgError("No value provided for argument", argName);\r
- }\r
- q = argValue;\r
- if (ch == '{') {\r
- // Quoting with { }. No characters have to (or can) be escaped.\r
- // Thus the string cannot contain a '}' character.\r
- start = ch;\r
- ch = get(cl);\r
- while (start) {\r
- switch (ch) {\r
- case NULLCHAR:\r
- start = NULLCHAR;\r
- break;\r
- \r
- case '}':\r
- ch = get(cl);\r
- start = NULLCHAR;\r
- break;\r
-\r
- default:\r
- *q++ = ch;\r
- ch = get(cl);\r
- break;\r
- }\r
- } \r
- } else if (ch == '\'' || ch == '"') {\r
- // Quoting with ' ' or " ", with \ as escape character.\r
- // Inconvenient for long strings that may contain Windows filenames.\r
- start = ch;\r
- ch = get(cl);\r
- while (start) {\r
- switch (ch) {\r
- case NULLCHAR:\r
- start = NULLCHAR;\r
- break;\r
-\r
- default:\r
- not_special:\r
- *q++ = ch;\r
- ch = get(cl);\r
- break;\r
-\r
- case '\'':\r
- case '\"':\r
- if (ch == start) {\r
- ch = get(cl);\r
- start = NULLCHAR;\r
- break;\r
- } else {\r
- goto not_special;\r
- }\r
-\r
- case '\\':\r
- if (ad->argType == ArgFilename\r
- || ad->argType == ArgSettingsFilename) {\r
- goto not_special;\r
- }\r
- ch = get(cl);\r
- switch (ch) {\r
- case NULLCHAR:\r
- ExitArgError("Incomplete \\ escape in value for", argName);\r
- break;\r
- case 'n':\r
- *q++ = '\n';\r
- ch = get(cl);\r
- break;\r
- case 'r':\r
- *q++ = '\r';\r
- ch = get(cl);\r
- break;\r
- case 't':\r
- *q++ = '\t';\r
- ch = get(cl);\r
- break;\r
- case 'b':\r
- *q++ = '\b';\r
- ch = get(cl);\r
- break;\r
- case 'f':\r
- *q++ = '\f';\r
- ch = get(cl);\r
- break;\r
- default:\r
- octval = 0;\r
- for (i = 0; i < 3; i++) {\r
- if (ch >= '0' && ch <= '7') {\r
- octval = octval*8 + (ch - '0');\r
- ch = get(cl);\r
- } else {\r
- break;\r
- }\r
- }\r
- if (i > 0) {\r
- *q++ = (char) octval;\r
- } else {\r
- *q++ = ch;\r
- ch = get(cl);\r
- }\r
- break;\r
- }\r
- break;\r
- }\r
- }\r
- } else {\r
- while (ch != ' ' && ch != NULLCHAR && ch != '\t' && ch != '\n') {\r
- *q++ = ch;\r
- ch = get(cl);\r
- }\r
- }\r
- *q = NULLCHAR;\r
-\r
- switch (ad->argType) {\r
- case ArgInt:\r
- *(int *) ad->argLoc = atoi(argValue);\r
- break;\r
-\r
- case ArgFloat:\r
- *(float *) ad->argLoc = (float) atof(argValue);\r
- break;\r
-\r
- case ArgString:\r
- case ArgFilename:\r
- *(char **) ad->argLoc = strdup(argValue);\r
- break;\r
-\r
- case ArgSettingsFilename:\r
- {\r
- char fullname[MSG_SIZ];\r
- if (ParseSettingsFile(argValue, fullname)) {\r
- if (ad->argLoc != NULL) {\r
- *(char **) ad->argLoc = strdup(fullname);\r
- }\r
- } else {\r
- if (ad->argLoc != NULL) {\r
- } else {\r
- ExitArgError("Failed to open indirection file", argValue);\r
- }\r
- }\r
- }\r
- break;\r
-\r
- case ArgBoolean:\r
- switch (argValue[0]) {\r
- case 't':\r
- case 'T':\r
- *(Boolean *) ad->argLoc = TRUE;\r
- break;\r
- case 'f':\r
- case 'F':\r
- *(Boolean *) ad->argLoc = FALSE;\r
- break;\r
- default:\r
- ExitArgError("Unrecognized boolean argument value", argValue);\r
- break;\r
- }\r
- break;\r
-\r
- case ArgColor:\r
- *(COLORREF *)ad->argLoc = ParseColorName(argValue);\r
- break;\r
-\r
- case ArgAttribs: {\r
- ColorClass cc = (ColorClass)ad->argLoc;\r
- ParseAttribs(&textAttribs[cc].color, &textAttribs[cc].effects, argValue);\r
- }\r
- break;\r
- \r
- case ArgBoardSize:\r
- *(BoardSize *)ad->argLoc = ParseBoardSize(argValue);\r
- break;\r
-\r
- case ArgFont:\r
- ParseFontName(argValue, &font[boardSize][(int)ad->argLoc]->mfp);\r
- break;\r
-\r
- case ArgCommSettings:\r
- ParseCommSettings(argValue, &dcb);\r
- break;\r
-\r
- case ArgNone:\r
- ExitArgError("Unrecognized argument", argValue);\r
- break;\r
- }\r
- }\r
-}\r
-\r
-VOID\r
-LFfromMFP(LOGFONT* lf, MyFontParams *mfp)\r
-{\r
- HDC hdc = CreateDC("DISPLAY", NULL, NULL, NULL);\r
- lf->lfHeight = -(int)(mfp->pointSize * GetDeviceCaps(hdc, LOGPIXELSY) / 72.0 + 0.5);\r
- DeleteDC(hdc);\r
- lf->lfWidth = 0;\r
- lf->lfEscapement = 0;\r
- lf->lfOrientation = 0;\r
- lf->lfWeight = mfp->bold ? FW_BOLD : FW_NORMAL;\r
- lf->lfItalic = mfp->italic;\r
- lf->lfUnderline = mfp->underline;\r
- lf->lfStrikeOut = mfp->strikeout;\r
- lf->lfCharSet = DEFAULT_CHARSET;\r
- lf->lfOutPrecision = OUT_DEFAULT_PRECIS;\r
- lf->lfClipPrecision = CLIP_DEFAULT_PRECIS;\r
- lf->lfQuality = DEFAULT_QUALITY;\r
- lf->lfPitchAndFamily = DEFAULT_PITCH|FF_DONTCARE;\r
- strcpy(lf->lfFaceName, mfp->faceName);\r
-}\r
-\r
-VOID\r
-CreateFontInMF(MyFont *mf)\r
-{\r
- LFfromMFP(&mf->lf, &mf->mfp);\r
- if (mf->hf) DeleteObject(mf->hf);\r
- mf->hf = CreateFontIndirect(&mf->lf);\r
-}\r
-\r
-VOID\r
-SetDefaultTextAttribs()\r
-{\r
- ColorClass cc;\r
- for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
- ParseAttribs(&textAttribs[cc].color, \r
- &textAttribs[cc].effects, \r
- defaultTextAttribs[cc]);\r
- }\r
-}\r
-\r
-VOID\r
-SetDefaultSounds()\r
-{\r
- ColorClass cc;\r
- SoundClass sc;\r
- for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
- textAttribs[cc].sound.name = strdup("");\r
- textAttribs[cc].sound.data = NULL;\r
- }\r
- for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
- sounds[sc].name = strdup("");\r
- sounds[sc].data = NULL;\r
- }\r
- sounds[(int)SoundBell].name = strdup(SOUND_BELL);\r
-}\r
-\r
-VOID\r
-LoadAllSounds()\r
-{\r
- ColorClass cc;\r
- SoundClass sc;\r
- for (cc = (ColorClass)0; cc < NColorClasses; cc++) {\r
- MyLoadSound(&textAttribs[cc].sound);\r
- }\r
- for (sc = (SoundClass)0; sc < NSoundClasses; sc++) {\r
- MyLoadSound(&sounds[sc]);\r
- }\r
-}\r
-\r
-VOID\r
-InitAppData(LPSTR lpCmdLine)\r
-{\r
- int i, j;\r
- char buf[ARG_MAX], currDir[MSG_SIZ];\r
- char *dummy, *p;\r
-\r
- programName = szAppName;\r
-\r
- /* Initialize to defaults */\r
- lightSquareColor = ParseColorName(LIGHT_SQUARE_COLOR);\r
- darkSquareColor = ParseColorName(DARK_SQUARE_COLOR);\r
- whitePieceColor = ParseColorName(WHITE_PIECE_COLOR);\r
- blackPieceColor = ParseColorName(BLACK_PIECE_COLOR);\r
- highlightSquareColor = ParseColorName(HIGHLIGHT_SQUARE_COLOR);\r
- premoveHighlightColor = ParseColorName(PREMOVE_HIGHLIGHT_COLOR);\r
- consoleBackgroundColor = ParseColorName(COLOR_BKGD);\r
- SetDefaultTextAttribs();\r
- SetDefaultSounds();\r
- appData.movesPerSession = MOVES_PER_SESSION;\r
- appData.initString = INIT_STRING;\r
- appData.secondInitString = INIT_STRING;\r
- appData.firstComputerString = COMPUTER_STRING;\r
- appData.secondComputerString = COMPUTER_STRING;\r
- appData.firstChessProgram = FIRST_CHESS_PROGRAM;\r
- appData.secondChessProgram = SECOND_CHESS_PROGRAM;\r
- appData.firstPlaysBlack = FALSE;\r
- appData.noChessProgram = FALSE;\r
- chessProgram = FALSE;\r
- appData.firstHost = FIRST_HOST;\r
- appData.secondHost = SECOND_HOST;\r
- appData.firstDirectory = FIRST_DIRECTORY;\r
- appData.secondDirectory = SECOND_DIRECTORY;\r
- appData.bitmapDirectory = "";\r
- appData.remoteShell = REMOTE_SHELL;\r
- appData.remoteUser = "";\r
- appData.timeDelay = TIME_DELAY;\r
- appData.timeControl = TIME_CONTROL;\r
- appData.timeIncrement = TIME_INCREMENT;\r
- appData.icsActive = FALSE;\r
- appData.icsHost = "";\r
- appData.icsPort = ICS_PORT;\r
- appData.icsCommPort = ICS_COMM_PORT;\r
- appData.icsLogon = ICS_LOGON;\r
- appData.icsHelper = "";\r
- appData.useTelnet = FALSE;\r
- appData.telnetProgram = TELNET_PROGRAM;\r
- appData.gateway = "";\r
- appData.loadGameFile = "";\r
- appData.loadGameIndex = 0;\r
- appData.saveGameFile = "";\r
- appData.autoSaveGames = FALSE;\r
- appData.loadPositionFile = "";\r
- appData.loadPositionIndex = 1;\r
- appData.savePositionFile = "";\r
- appData.matchMode = FALSE;\r
- appData.matchGames = 0;\r
- appData.monoMode = FALSE;\r
- appData.debugMode = FALSE;\r
- appData.clockMode = TRUE;\r
- boardSize = (BoardSize) -1; /* determine by screen size */\r
- appData.Iconic = FALSE; /*unused*/\r
- appData.searchTime = "";\r
- appData.searchDepth = 0;\r
- appData.showCoords = FALSE;\r
- appData.ringBellAfterMoves = TRUE; /*obsolete in WinBoard*/\r
- appData.autoCallFlag = FALSE;\r
- appData.flipView = FALSE;\r
- appData.autoFlipView = TRUE;\r
- appData.cmailGameName = "";\r
- appData.alwaysPromoteToQueen = FALSE;\r
- appData.oldSaveStyle = FALSE;\r
- appData.quietPlay = FALSE;\r
- appData.showThinking = FALSE;\r
- appData.ponderNextMove = TRUE;\r
- appData.periodicUpdates = TRUE;\r
- appData.popupExitMessage = TRUE;\r
- appData.popupMoveErrors = FALSE;\r
- appData.autoObserve = FALSE;\r
- appData.autoComment = FALSE;\r
- appData.animate = TRUE;\r
- appData.animSpeed = 10;\r
- appData.animateDragging = TRUE;\r
- appData.highlightLastMove = TRUE;\r
- appData.getMoveList = TRUE;\r
- appData.testLegality = TRUE;\r
- appData.premove = TRUE;\r
- appData.premoveWhite = FALSE;\r
- appData.premoveWhiteText = "";\r
- appData.premoveBlack = FALSE;\r
- appData.premoveBlackText = "";\r
- appData.icsAlarm = TRUE;\r
- appData.icsAlarmTime = 5000;\r
- appData.autoRaiseBoard = TRUE;\r
- appData.localLineEditing = TRUE;\r
- appData.colorize = TRUE;\r
- appData.reuseFirst = TRUE;\r
- appData.reuseSecond = TRUE;\r
- appData.blindfold = FALSE;\r
- dcb.DCBlength = sizeof(DCB);\r
- dcb.BaudRate = 9600;\r
- dcb.fBinary = TRUE;\r
- dcb.fParity = FALSE;\r
- dcb.fOutxCtsFlow = FALSE;\r
- dcb.fOutxDsrFlow = FALSE;\r
- dcb.fDtrControl = DTR_CONTROL_ENABLE;\r
- dcb.fDsrSensitivity = FALSE;\r
- dcb.fTXContinueOnXoff = TRUE;\r
- dcb.fOutX = FALSE;\r
- dcb.fInX = FALSE;\r
- dcb.fNull = FALSE;\r
- dcb.fRtsControl = RTS_CONTROL_ENABLE;\r
- dcb.fAbortOnError = FALSE;\r
- dcb.wReserved = 0;\r
- dcb.ByteSize = 7;\r
- dcb.Parity = SPACEPARITY;\r
- dcb.StopBits = ONESTOPBIT;\r
- settingsFileName = SETTINGS_FILE;\r
- saveSettingsOnExit = TRUE;\r
- boardX = CW_USEDEFAULT;\r
- boardY = CW_USEDEFAULT;\r
- consoleX = CW_USEDEFAULT; \r
- consoleY = CW_USEDEFAULT; \r
- consoleW = CW_USEDEFAULT;\r
- consoleH = CW_USEDEFAULT;\r
- analysisX = CW_USEDEFAULT; \r
- analysisY = CW_USEDEFAULT; \r
- analysisW = CW_USEDEFAULT;\r
- analysisH = CW_USEDEFAULT;\r
- commentX = CW_USEDEFAULT; \r
- commentY = CW_USEDEFAULT; \r
- commentW = CW_USEDEFAULT;\r
- commentH = CW_USEDEFAULT;\r
- editTagsX = CW_USEDEFAULT; \r
- editTagsY = CW_USEDEFAULT; \r
- editTagsW = CW_USEDEFAULT;\r
- editTagsH = CW_USEDEFAULT;\r
- gameListX = CW_USEDEFAULT; \r
- gameListY = CW_USEDEFAULT; \r
- gameListW = CW_USEDEFAULT;\r
- gameListH = CW_USEDEFAULT;\r
- icsTextMenuString = ICS_TEXT_MENU_DEFAULT;\r
- icsNames = ICS_NAMES;\r
- firstChessProgramNames = FCP_NAMES;\r
- secondChessProgramNames = SCP_NAMES;\r
- appData.initialMode = "";\r
- appData.variant = "normal";\r
- appData.firstProtocolVersion = PROTOVER;\r
- appData.secondProtocolVersion = PROTOVER;\r
- appData.showButtonBar = TRUE;\r
-#ifdef ZIPPY\r
- appData.zippyTalk = ZIPPY_TALK;\r
- appData.zippyPlay = ZIPPY_PLAY;\r
- appData.zippyLines = ZIPPY_LINES;\r
- appData.zippyPinhead = ZIPPY_PINHEAD;\r
- appData.zippyPassword = ZIPPY_PASSWORD;\r
- appData.zippyPassword2 = ZIPPY_PASSWORD2;\r
- appData.zippyWrongPassword = ZIPPY_WRONG_PASSWORD;\r
- appData.zippyAcceptOnly = ZIPPY_ACCEPT_ONLY;\r
- appData.zippyUseI = ZIPPY_USE_I;\r
- appData.zippyBughouse = ZIPPY_BUGHOUSE;\r
- appData.zippyNoplayCrafty = ZIPPY_NOPLAY_CRAFTY;\r
- appData.zippyGameEnd = ZIPPY_GAME_END;\r
- appData.zippyGameStart = ZIPPY_GAME_START;\r
- appData.zippyAdjourn = ZIPPY_ADJOURN;\r
- appData.zippyAbort = ZIPPY_ABORT;\r
- appData.zippyVariants = ZIPPY_VARIANTS;\r
- appData.zippyMaxGames = ZIPPY_MAX_GAMES;\r
- appData.zippyReplayTimeout = ZIPPY_REPLAY_TIMEOUT;\r
-#endif\r
-\r
- /* Point font array elements to structures and\r
- parse default font names */\r
- for (i=0; i<NUM_FONTS; i++) {\r
- for (j=0; j<NUM_SIZES; j++) {\r
- font[j][i] = &fontRec[j][i];\r
- ParseFontName(font[j][i]->def, &font[j][i]->mfp);\r
- }\r
- }\r
- \r
- /* Parse default settings file if any */\r
- if (ParseSettingsFile(settingsFileName, buf)) {\r
- settingsFileName = strdup(buf);\r
- }\r
-\r
- /* Parse command line */\r
- ParseArgs(StringGet, &lpCmdLine);\r
-\r
- /* Propagate options that affect others */\r
- if (appData.matchMode || appData.matchGames) chessProgram = TRUE;\r
- if (appData.icsActive || appData.noChessProgram) {\r
- chessProgram = FALSE; /* not local chess program mode */\r
- }\r
-\r
- /* Open startup dialog if needed */\r
- if ((!appData.noChessProgram && !chessProgram && !appData.icsActive) ||\r
- (appData.icsActive && *appData.icsHost == NULLCHAR) ||\r
- (chessProgram && (*appData.firstChessProgram == NULLCHAR ||\r
- *appData.secondChessProgram == NULLCHAR))) {\r
- FARPROC lpProc;\r
- \r
- lpProc = MakeProcInstance((FARPROC)StartupDialog, hInst);\r
- DialogBox(hInst, MAKEINTRESOURCE(DLG_Startup), NULL, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
- }\r
-\r
- /* Make sure save files land in the right (?) directory */\r
- if (GetFullPathName(appData.saveGameFile, MSG_SIZ, buf, &dummy)) {\r
- appData.saveGameFile = strdup(buf);\r
- }\r
- if (GetFullPathName(appData.savePositionFile, MSG_SIZ, buf, &dummy)) {\r
- appData.savePositionFile = strdup(buf);\r
- }\r
-\r
- /* Finish initialization for fonts and sounds */\r
- for (i=0; i<NUM_FONTS; i++) {\r
- for (j=0; j<NUM_SIZES; j++) {\r
- CreateFontInMF(font[j][i]);\r
- }\r
- }\r
- /* xboard, and older WinBoards, controlled the move sound with the\r
- appData.ringBellAfterMoves option. In the current WinBoard, we\r
- always turn the option on (so that the backend will call us),\r
- then let the user turn the sound off by setting it to silence if\r
- desired. To accommodate old winboard.ini files saved by old\r
- versions of WinBoard, we also turn off the sound if the option\r
- was initially set to false. */\r
- if (!appData.ringBellAfterMoves) {\r
- sounds[(int)SoundMove].name = strdup("");\r
- appData.ringBellAfterMoves = TRUE;\r
- }\r
- GetCurrentDirectory(MSG_SIZ, currDir);\r
- SetCurrentDirectory(installDir);\r
- LoadAllSounds();\r
- SetCurrentDirectory(currDir);\r
-\r
- p = icsTextMenuString;\r
- if (p[0] == '@') {\r
- FILE* f = fopen(p + 1, "r");\r
- if (f == NULL) {\r
- DisplayFatalError(p + 1, errno, 2);\r
- return;\r
- }\r
- i = fread(buf, 1, sizeof(buf)-1, f);\r
- fclose(f);\r
- buf[i] = NULLCHAR;\r
- p = buf;\r
- }\r
- ParseIcsTextMenu(strdup(p));\r
-}\r
-\r
-\r
-VOID\r
-InitMenuChecks()\r
-{\r
- HMENU hmenu = GetMenu(hwndMain);\r
-\r
- (void) EnableMenuItem(hmenu, IDM_CommPort,\r
- MF_BYCOMMAND|((appData.icsActive &&\r
- *appData.icsCommPort != NULLCHAR) ?\r
- MF_ENABLED : MF_GRAYED));\r
- (void) CheckMenuItem(hmenu, IDM_SaveSettingsOnExit,\r
- MF_BYCOMMAND|(saveSettingsOnExit ?\r
- MF_CHECKED : MF_UNCHECKED));\r
-}\r
-\r
-\r
-VOID\r
-SaveSettings(char* name)\r
-{\r
- FILE *f;\r
- ArgDescriptor *ad;\r
- WINDOWPLACEMENT wp;\r
- char dir[MSG_SIZ];\r
-\r
- if (!hwndMain) return;\r
-\r
- GetCurrentDirectory(MSG_SIZ, dir);\r
- SetCurrentDirectory(installDir);\r
- f = fopen(name, "w");\r
- SetCurrentDirectory(dir);\r
- if (f == NULL) {\r
- DisplayError(name, errno);\r
- return;\r
- }\r
- fprintf(f, ";\n");\r
- fprintf(f, "; %s %s.%s Save Settings file\n", PRODUCT, VERSION, PATCHLEVEL);\r
- fprintf(f, ";\n");\r
- fprintf(f, "; You can edit the values of options that are already set in this file,\n");\r
- fprintf(f, "; but if you add other options, the next Save Settings will not save them.\n");\r
- fprintf(f, "; Use a shortcut, an @indirection file, or a .bat file instead.\n");\r
- fprintf(f, ";\n");\r
-\r
- wp.length = sizeof(WINDOWPLACEMENT);\r
- GetWindowPlacement(hwndMain, &wp);\r
- boardX = wp.rcNormalPosition.left;\r
- boardY = wp.rcNormalPosition.top;\r
-\r
- if (hwndConsole) {\r
- GetWindowPlacement(hwndConsole, &wp);\r
- consoleX = wp.rcNormalPosition.left;\r
- consoleY = wp.rcNormalPosition.top;\r
- consoleW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
- consoleH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
- }\r
-\r
- if (analysisDialog) {\r
- GetWindowPlacement(analysisDialog, &wp);\r
- analysisX = wp.rcNormalPosition.left;\r
- analysisY = wp.rcNormalPosition.top;\r
- analysisW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
- analysisH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
- }\r
-\r
- if (commentDialog) {\r
- GetWindowPlacement(commentDialog, &wp);\r
- commentX = wp.rcNormalPosition.left;\r
- commentY = wp.rcNormalPosition.top;\r
- commentW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
- commentH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
- }\r
-\r
- if (editTagsDialog) {\r
- GetWindowPlacement(editTagsDialog, &wp);\r
- editTagsX = wp.rcNormalPosition.left;\r
- editTagsY = wp.rcNormalPosition.top;\r
- editTagsW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
- editTagsH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
- }\r
-\r
- if (gameListDialog) {\r
- GetWindowPlacement(gameListDialog, &wp);\r
- gameListX = wp.rcNormalPosition.left;\r
- gameListY = wp.rcNormalPosition.top;\r
- gameListW = wp.rcNormalPosition.right - wp.rcNormalPosition.left;\r
- gameListH = wp.rcNormalPosition.bottom - wp.rcNormalPosition.top;\r
- }\r
-\r
- for (ad = argDescriptors; ad->argName != NULL; ad++) {\r
- if (!ad->save) continue;\r
- switch (ad->argType) {\r
- case ArgString:\r
- {\r
- char *p = *(char **)ad->argLoc;\r
- if ((strchr(p, '\\') || strchr(p, '\n')) && !strchr(p, '}')) {\r
- /* Quote multiline values or \-containing values\r
- with { } if possible */\r
- fprintf(f, "/%s={%s}\n", ad->argName, p);\r
- } else {\r
- /* Else quote with " " */\r
- fprintf(f, "/%s=\"", ad->argName);\r
- while (*p) {\r
- if (*p == '\n') fprintf(f, "\n");\r
- else if (*p == '\r') fprintf(f, "\\r");\r
- else if (*p == '\t') fprintf(f, "\\t");\r
- else if (*p == '\b') fprintf(f, "\\b");\r
- else if (*p == '\f') fprintf(f, "\\f");\r
- else if (*p < ' ') fprintf(f, "\\%03o", *p);\r
- else if (*p == '\"') fprintf(f, "\\\"");\r
- else if (*p == '\\') fprintf(f, "\\\\");\r
- else putc(*p, f);\r
- p++;\r
- }\r
- fprintf(f, "\"\n");\r
- }\r
- }\r
- break;\r
- case ArgInt:\r
- fprintf(f, "/%s=%d\n", ad->argName, *(int *)ad->argLoc);\r
- break;\r
- case ArgFloat:\r
- fprintf(f, "/%s=%g\n", ad->argName, *(float *)ad->argLoc);\r
- break;\r
- case ArgBoolean:\r
- fprintf(f, "/%s=%s\n", ad->argName, \r
- (*(Boolean *)ad->argLoc) ? "true" : "false");\r
- break;\r
- case ArgTrue:\r
- if (*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);\r
- break;\r
- case ArgFalse:\r
- if (!*(Boolean *)ad->argLoc) fprintf(f, "/%s\n", ad->argName);\r
- break;\r
- case ArgColor:\r
- {\r
- COLORREF color = *(COLORREF *)ad->argLoc;\r
- fprintf(f, "/%s=#%02x%02x%02x\n", ad->argName, \r
- color&0xff, (color>>8)&0xff, (color>>16)&0xff);\r
- }\r
- break;\r
- case ArgAttribs:\r
- {\r
- MyTextAttribs* ta = &textAttribs[(ColorClass)ad->argLoc];\r
- fprintf(f, "/%s=\"%s%s%s%s%s#%02x%02x%02x\"\n", ad->argName,\r
- (ta->effects & CFE_BOLD) ? "b" : "",\r
- (ta->effects & CFE_ITALIC) ? "i" : "",\r
- (ta->effects & CFE_UNDERLINE) ? "u" : "",\r
- (ta->effects & CFE_STRIKEOUT) ? "s" : "",\r
- (ta->effects) ? " " : "",\r
- ta->color&0xff, (ta->color >> 8)&0xff, (ta->color >> 16)&0xff);\r
- }\r
- break;\r
- case ArgFilename:\r
- if (strchr(*(char **)ad->argLoc, '\"')) {\r
- fprintf(f, "/%s='%s'\n", ad->argName, *(char **)ad->argLoc);\r
- } else {\r
- fprintf(f, "/%s=\"%s\"\n", ad->argName, *(char **)ad->argLoc);\r
- }\r
- break;\r
- case ArgBoardSize:\r
- fprintf(f, "/%s=%s\n", ad->argName,\r
- sizeInfo[*(BoardSize *)ad->argLoc].name);\r
- break;\r
- case ArgFont:\r
- {\r
- int bs;\r
- for (bs=0; bs<NUM_SIZES; bs++) {\r
- MyFontParams *mfp = &font[bs][(int) ad->argLoc]->mfp;\r
- fprintf(f, "/size=%s ", sizeInfo[bs].name);\r
- fprintf(f, "/%s=\"%s:%g%s%s%s%s%s\"\n",\r
- ad->argName, mfp->faceName, mfp->pointSize,\r
- mfp->bold || mfp->italic || mfp->underline || mfp->strikeout ? " " : "",\r
- mfp->bold ? "b" : "",\r
- mfp->italic ? "i" : "",\r
- mfp->underline ? "u" : "",\r
- mfp->strikeout ? "s" : "");\r
- }\r
- }\r
- break;\r
- case ArgCommSettings:\r
- PrintCommSettings(f, ad->argName, (DCB *)ad->argLoc);\r
- }\r
- }\r
- fclose(f);\r
-}\r
-\r
-\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * GDI board drawing routines\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-HBITMAP\r
-DoLoadBitmap(HINSTANCE hinst, char *piece, int squareSize, char *suffix)\r
-{\r
- char name[128];\r
-\r
- sprintf(name, "%s%d%s", piece, squareSize, suffix);\r
- if (gameInfo.event &&\r
- strcmp(gameInfo.event, "Easter Egg Hunt") == 0 &&\r
- strcmp(name, "k80s") == 0) {\r
- strcpy(name, "tim");\r
- }\r
- return LoadBitmap(hinst, name);\r
-}\r
-\r
-\r
-/* Insert a color into the program's logical palette\r
- structure. This code assumes the given color is\r
- the result of the RGB or PALETTERGB macro, and it\r
- knows how those macros work (which is documented).\r
-*/\r
-VOID\r
-InsertInPalette(COLORREF color)\r
-{\r
- LPPALETTEENTRY pe = &(pLogPal->palPalEntry[pLogPal->palNumEntries]);\r
-\r
- if (pLogPal->palNumEntries++ >= PALETTESIZE) {\r
- DisplayFatalError("Too many colors", 0, 1);\r
- pLogPal->palNumEntries--;\r
- return;\r
- }\r
-\r
- pe->peFlags = (char) 0;\r
- pe->peRed = (char) (0xFF & color);\r
- pe->peGreen = (char) (0xFF & (color >> 8));\r
- pe->peBlue = (char) (0xFF & (color >> 16));\r
- return;\r
-}\r
-\r
-\r
-VOID\r
-InitDrawingColors()\r
-{\r
- if (pLogPal == NULL) {\r
- /* Allocate enough memory for a logical palette with\r
- * PALETTESIZE entries and set the size and version fields\r
- * of the logical palette structure.\r
- */\r
- pLogPal = (NPLOGPALETTE)\r
- LocalAlloc(LMEM_FIXED, (sizeof(LOGPALETTE) +\r
- (sizeof(PALETTEENTRY) * (PALETTESIZE))));\r
- pLogPal->palVersion = 0x300;\r
- }\r
- pLogPal->palNumEntries = 0;\r
-\r
- InsertInPalette(lightSquareColor);\r
- InsertInPalette(darkSquareColor);\r
- InsertInPalette(whitePieceColor);\r
- InsertInPalette(blackPieceColor);\r
- InsertInPalette(highlightSquareColor);\r
- InsertInPalette(premoveHighlightColor);\r
-\r
- /* create a logical color palette according the information\r
- * in the LOGPALETTE structure.\r
- */\r
- hPal = CreatePalette((LPLOGPALETTE) pLogPal);\r
-\r
- lightSquareBrush = CreateSolidBrush(lightSquareColor);\r
- darkSquareBrush = CreateSolidBrush(darkSquareColor);\r
- whitePieceBrush = CreateSolidBrush(whitePieceColor);\r
- blackPieceBrush = CreateSolidBrush(blackPieceColor);\r
- iconBkgndBrush = CreateSolidBrush(GetSysColor(COLOR_BACKGROUND));\r
-}\r
-\r
-\r
-int\r
-BoardWidth(int boardSize)\r
-{\r
- return (BOARD_SIZE + 1) * sizeInfo[boardSize].lineGap +\r
- BOARD_SIZE * sizeInfo[boardSize].squareSize;\r
-}\r
-\r
-/* Respond to board resize by dragging edge */\r
-VOID\r
-ResizeBoard(int newSizeX, int newSizeY, int flags)\r
-{\r
- BoardSize newSize = NUM_SIZES - 1;\r
- static int recurse = 0;\r
- if (IsIconic(hwndMain)) return;\r
- if (recurse > 0) return;\r
- recurse++;\r
- while (newSize > 0 &&\r
- (newSizeX < sizeInfo[newSize].cliWidth ||\r
- newSizeY < sizeInfo[newSize].cliHeight)) {\r
- newSize--;\r
- } \r
- boardSize = newSize;\r
- InitDrawingSizes(boardSize, flags);\r
- recurse--;\r
-}\r
-\r
-\r
-\r
-VOID\r
-InitDrawingSizes(BoardSize boardSize, int flags)\r
-{\r
- int i, boardWidth;\r
- ChessSquare piece;\r
- static int oldBoardSize = -1, oldTinyLayout = 0;\r
- HDC hdc;\r
- SIZE clockSize, messageSize;\r
- HFONT oldFont;\r
- char buf[MSG_SIZ];\r
- char *str;\r
- HMENU hmenu = GetMenu(hwndMain);\r
- RECT crect, wrect;\r
- int offby;\r
- LOGBRUSH logbrush;\r
-\r
- tinyLayout = sizeInfo[boardSize].tinyLayout;\r
- smallLayout = sizeInfo[boardSize].smallLayout;\r
- squareSize = sizeInfo[boardSize].squareSize;\r
- lineGap = sizeInfo[boardSize].lineGap;\r
-\r
- if (tinyLayout != oldTinyLayout) {\r
- long style = GetWindowLong(hwndMain, GWL_STYLE);\r
- if (tinyLayout) {\r
- style &= ~WS_SYSMENU;\r
- InsertMenu(hmenu, IDM_Exit, MF_BYCOMMAND, IDM_Minimize,\r
- "&Minimize\tCtrl+F4");\r
- } else {\r
- style |= WS_SYSMENU;\r
- RemoveMenu(hmenu, IDM_Minimize, MF_BYCOMMAND);\r
- }\r
- SetWindowLong(hwndMain, GWL_STYLE, style);\r
-\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
- }\r
-\r
- boardWidth = BoardWidth(boardSize);\r
-\r
- /* Get text area sizes */\r
- hdc = GetDC(hwndMain);\r
- if (appData.clockMode) {\r
- sprintf(buf, "White: %s", TimeString(23*60*60*1000L));\r
- } else {\r
- sprintf(buf, "White");\r
- }\r
- oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);\r
- GetTextExtentPoint(hdc, buf, strlen(buf), &clockSize);\r
- SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);\r
- str = "We only care about the height here";\r
- GetTextExtentPoint(hdc, str, strlen(str), &messageSize);\r
- SelectObject(hdc, oldFont);\r
- 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
-\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
- messageRect.left = whiteRect.left + MESSAGE_LINE_LEFTMARGIN;\r
- if (appData.showButtonBar) {\r
- messageRect.right = blackRect.right\r
- - N_BUTTONS*BUTTON_WIDTH - MESSAGE_LINE_LEFTMARGIN;\r
- } else {\r
- messageRect.right = blackRect.right;\r
- }\r
- messageRect.top = whiteRect.bottom + INNER_MARGIN;\r
- messageRect.bottom = messageRect.top + messageSize.cy;\r
-\r
- boardRect.left = whiteRect.left;\r
- boardRect.right = boardRect.left + boardWidth;\r
- boardRect.top = messageRect.bottom + INNER_MARGIN;\r
- boardRect.bottom = boardRect.top + boardWidth;\r
-\r
- sizeInfo[boardSize].cliWidth = boardRect.right + OUTER_MARGIN;\r
- sizeInfo[boardSize].cliHeight = boardRect.bottom + OUTER_MARGIN;\r
- winWidth = 2 * GetSystemMetrics(SM_CXFRAME) + boardRect.right + OUTER_MARGIN;\r
- winHeight = 2 * GetSystemMetrics(SM_CYFRAME) + GetSystemMetrics(SM_CYMENU) +\r
- GetSystemMetrics(SM_CYCAPTION) + boardRect.bottom + OUTER_MARGIN;\r
- GetWindowRect(hwndMain, &wrect);\r
- SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,\r
- SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);\r
- /* compensate if menu bar wrapped */\r
- GetClientRect(hwndMain, &crect);\r
- offby = boardRect.bottom + OUTER_MARGIN - crect.bottom;\r
- winHeight += offby;\r
- switch (flags) {\r
- case WMSZ_TOPLEFT:\r
- SetWindowPos(hwndMain, NULL, \r
- wrect.right - winWidth, wrect.bottom - winHeight, \r
- winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);\r
- break;\r
-\r
- case WMSZ_TOPRIGHT:\r
- case WMSZ_TOP:\r
- SetWindowPos(hwndMain, NULL, \r
- wrect.left, wrect.bottom - winHeight, \r
- winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);\r
- break;\r
-\r
- case WMSZ_BOTTOMLEFT:\r
- case WMSZ_LEFT:\r
- SetWindowPos(hwndMain, NULL, \r
- wrect.right - winWidth, wrect.top, \r
- winWidth, winHeight, SWP_NOCOPYBITS|SWP_NOZORDER);\r
- break;\r
-\r
- case WMSZ_BOTTOMRIGHT:\r
- case WMSZ_BOTTOM:\r
- case WMSZ_RIGHT:\r
- default:\r
- SetWindowPos(hwndMain, NULL, 0, 0, winWidth, winHeight,\r
- SWP_NOCOPYBITS|SWP_NOZORDER|SWP_NOMOVE);\r
- break;\r
- }\r
-\r
- hwndPause = NULL;\r
- for (i = 0; i < N_BUTTONS; i++) {\r
- if (buttonDesc[i].hwnd != NULL) {\r
- DestroyWindow(buttonDesc[i].hwnd);\r
- buttonDesc[i].hwnd = NULL;\r
- }\r
- if (appData.showButtonBar) {\r
- buttonDesc[i].hwnd =\r
- CreateWindow("BUTTON", buttonDesc[i].label,\r
- WS_VISIBLE | WS_CHILD | BS_PUSHBUTTON,\r
- boardRect.right - BUTTON_WIDTH*(N_BUTTONS-i),\r
- messageRect.top, BUTTON_WIDTH, messageSize.cy, hwndMain,\r
- (HMENU) buttonDesc[i].id,\r
- (HINSTANCE) GetWindowLong(hwndMain, GWL_HINSTANCE), NULL);\r
- if (tinyLayout) {\r
- SendMessage(buttonDesc[i].hwnd, WM_SETFONT, \r
- (WPARAM)font[boardSize][MESSAGE_FONT]->hf,\r
- MAKELPARAM(FALSE, 0));\r
- }\r
- if (buttonDesc[i].id == IDM_Pause)\r
- hwndPause = buttonDesc[i].hwnd;\r
- buttonDesc[i].wndproc = (WNDPROC)\r
- SetWindowLong(buttonDesc[i].hwnd, GWL_WNDPROC, (LONG) ButtonProc);\r
- }\r
- }\r
- if (gridPen != NULL) DeleteObject(gridPen);\r
- if (highlightPen != NULL) DeleteObject(highlightPen);\r
- if (premovePen != NULL) DeleteObject(premovePen);\r
- if (lineGap != 0) {\r
- logbrush.lbStyle = BS_SOLID;\r
- logbrush.lbColor = RGB(0, 0, 0); /* grid pen color = black */\r
- gridPen =\r
- ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,\r
- lineGap, &logbrush, 0, NULL);\r
- logbrush.lbColor = highlightSquareColor;\r
- highlightPen =\r
- ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,\r
- lineGap, &logbrush, 0, NULL);\r
-\r
- logbrush.lbColor = premoveHighlightColor; \r
- premovePen =\r
- ExtCreatePen(PS_GEOMETRIC|PS_SOLID|PS_ENDCAP_FLAT|PS_JOIN_MITER,\r
- lineGap, &logbrush, 0, NULL);\r
-\r
- for (i = 0; i < BOARD_SIZE + 1; i++) {\r
- gridEndpoints[i*2].x = boardRect.left + lineGap / 2;\r
- gridEndpoints[i*2 + BOARD_SIZE*2 + 2].y = boardRect.top + lineGap / 2;\r
- gridEndpoints[i*2].y = gridEndpoints[i*2 + 1].y =\r
- boardRect.top + lineGap / 2 + (i * (squareSize + lineGap));\r
- gridEndpoints[i*2 + 1].x = boardRect.left + lineGap / 2 +\r
- BOARD_SIZE * (squareSize + lineGap);\r
- gridEndpoints[i*2 + BOARD_SIZE*2 + 2].x =\r
- gridEndpoints[i*2 + 1 + BOARD_SIZE*2 + 2].x = boardRect.left +\r
- lineGap / 2 + (i * (squareSize + lineGap));\r
- gridEndpoints[i*2 + 1 + BOARD_SIZE*2 + 2].y =\r
- boardRect.top + BOARD_SIZE * (squareSize + lineGap);\r
- gridVertexCounts[i*2] = gridVertexCounts[i*2 + 1] = 2;\r
- }\r
- }\r
-\r
- if (boardSize == oldBoardSize) return;\r
- oldBoardSize = boardSize;\r
- oldTinyLayout = tinyLayout;\r
-\r
- /* Load piece bitmaps for this board size */\r
- for (i=0; i<=2; i++) {\r
- for (piece = WhitePawn;\r
- (int) piece <= (int) WhiteKing;\r
- piece = (ChessSquare) ((int) piece + 1)) {\r
- if (pieceBitmap[i][piece] != NULL)\r
- DeleteObject(pieceBitmap[i][piece]);\r
- }\r
- }\r
-\r
- pieceBitmap[0][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "s");\r
- pieceBitmap[0][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "s");\r
- pieceBitmap[0][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "s");\r
- pieceBitmap[0][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "s");\r
- pieceBitmap[0][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "s");\r
- pieceBitmap[0][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "s");\r
- pieceBitmap[1][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "o");\r
- pieceBitmap[1][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "o");\r
- pieceBitmap[1][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "o");\r
- pieceBitmap[1][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "o");\r
- pieceBitmap[1][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "o");\r
- pieceBitmap[1][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "o");\r
- pieceBitmap[2][WhitePawn] = DoLoadBitmap(hInst, "p", squareSize, "w");\r
- pieceBitmap[2][WhiteKnight] = DoLoadBitmap(hInst, "n", squareSize, "w");\r
- pieceBitmap[2][WhiteBishop] = DoLoadBitmap(hInst, "b", squareSize, "w");\r
- pieceBitmap[2][WhiteRook] = DoLoadBitmap(hInst, "r", squareSize, "w");\r
- pieceBitmap[2][WhiteQueen] = DoLoadBitmap(hInst, "q", squareSize, "w");\r
- pieceBitmap[2][WhiteKing] = DoLoadBitmap(hInst, "k", squareSize, "w");\r
-\r
-}\r
-\r
-HBITMAP\r
-PieceBitmap(ChessSquare p, int kind)\r
-{\r
- if ((int) p >= (int) BlackPawn)\r
- p = (ChessSquare) ((int) p - (int) BlackPawn + (int) WhitePawn);\r
-\r
- return pieceBitmap[kind][(int) p];\r
-}\r
-\r
-/***************************************************************/\r
-\r
-#define MIN(a,b) (((a) < (b)) ? (a) : (b))\r
-#define MAX(a,b) (((a) > (b)) ? (a) : (b))\r
-/*\r
-#define MIN3(a,b,c) (((a) < (b) && (a) < (c)) ? (a) : (((b) < (a) && (b) < (c)) ? (b) : (c)))\r
-#define MAX3(a,b,c) (((a) > (b) && (a) > (c)) ? (a) : (((b) > (a) && (b) > (c)) ? (b) : (c)))\r
-*/\r
-\r
-VOID\r
-SquareToPos(int row, int column, int * x, int * y)\r
-{\r
- if (flipView) {\r
- *x = boardRect.left + lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);\r
- *y = boardRect.top + lineGap + row * (squareSize + lineGap);\r
- } else {\r
- *x = boardRect.left + lineGap + column * (squareSize + lineGap);\r
- *y = boardRect.top + lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);\r
- }\r
-}\r
-\r
-VOID\r
-DrawCoordsOnDC(HDC hdc)\r
-{\r
- static char files[16] = {'1','2','3','4','5','6','7','8','8','7','6','5','4','3','2','1'};\r
- static char ranks[16] = {'h','g','f','e','d','c','b','a','a','b','c','d','e','f','g','h'};\r
- char str[2] = { NULLCHAR, NULLCHAR };\r
- int oldMode, oldAlign, x, y, start, i;\r
- HFONT oldFont;\r
- HBRUSH oldBrush;\r
-\r
- if (!appData.showCoords)\r
- return;\r
-\r
- start = flipView ? 0 : 8;\r
-\r
- oldBrush = SelectObject(hdc, GetStockObject(BLACK_BRUSH));\r
- oldMode = SetBkMode(hdc, (appData.monoMode ? OPAQUE : TRANSPARENT));\r
- oldAlign = GetTextAlign(hdc);\r
- oldFont = SelectObject(hdc, font[boardSize][COORD_FONT]->hf);\r
-\r
- y = boardRect.top + lineGap;\r
- x = boardRect.left + lineGap;\r
-\r
- SetTextAlign(hdc, TA_LEFT|TA_TOP);\r
- for (i = 0; i < 8; i++) {\r
- str[0] = files[start + i];\r
- ExtTextOut(hdc, x + 2, y + 1, 0, NULL, str, 1, NULL);\r
- y += squareSize + lineGap;\r
- }\r
-\r
- SetTextAlign(hdc, TA_RIGHT|TA_BOTTOM);\r
- for (i = 0; i < 8; i++) {\r
- str[0] = ranks[start + i];\r
- ExtTextOut(hdc, x + squareSize - 2, y - 1, 0, NULL, str, 1, NULL);\r
- x += squareSize + lineGap;\r
- } \r
-\r
- SelectObject(hdc, oldBrush);\r
- SetBkMode(hdc, oldMode);\r
- SetTextAlign(hdc, oldAlign);\r
- SelectObject(hdc, oldFont);\r
-}\r
-\r
-VOID\r
-DrawGridOnDC(HDC hdc)\r
-{\r
- HPEN oldPen;\r
- \r
- if (lineGap != 0) {\r
- oldPen = SelectObject(hdc, gridPen);\r
- PolyPolyline(hdc, gridEndpoints, gridVertexCounts, BOARD_SIZE*2 + 2);\r
- SelectObject(hdc, oldPen);\r
- }\r
-}\r
-\r
-#define HIGHLIGHT_PEN 0\r
-#define PREMOVE_PEN 1\r
-\r
-VOID\r
-DrawHighlightOnDC(HDC hdc, BOOLEAN on, int x, int y, int pen)\r
-{\r
- int x1, y1;\r
- HPEN oldPen, hPen;\r
- if (lineGap == 0) return;\r
- if (flipView) {\r
- x1 = boardRect.left +\r
- lineGap/2 + ((BOARD_SIZE-1)-x) * (squareSize + lineGap);\r
- y1 = boardRect.top +\r
- lineGap/2 + y * (squareSize + lineGap);\r
- } else {\r
- x1 = boardRect.left +\r
- lineGap/2 + x * (squareSize + lineGap);\r
- y1 = boardRect.top +\r
- lineGap/2 + ((BOARD_SIZE-1)-y) * (squareSize + lineGap);\r
- }\r
- hPen = pen ? premovePen : highlightPen;\r
- oldPen = SelectObject(hdc, on ? hPen : gridPen);\r
- MoveToEx(hdc, x1, y1, NULL);\r
- LineTo(hdc, x1 + squareSize + lineGap, y1);\r
- LineTo(hdc, x1 + squareSize + lineGap, y1 + squareSize + lineGap);\r
- LineTo(hdc, x1, y1 + squareSize + lineGap);\r
- LineTo(hdc, x1, y1);\r
- SelectObject(hdc, oldPen);\r
-}\r
-\r
-VOID\r
-DrawHighlightsOnDC(HDC hdc)\r
-{\r
- int i;\r
- for (i=0; i<2; i++) {\r
- if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0) \r
- DrawHighlightOnDC(hdc, TRUE,\r
- highlightInfo.sq[i].x, highlightInfo.sq[i].y,\r
- HIGHLIGHT_PEN);\r
- }\r
- for (i=0; i<2; i++) {\r
- if (premoveHighlightInfo.sq[i].x >= 0 && \r
- premoveHighlightInfo.sq[i].y >= 0) {\r
- DrawHighlightOnDC(hdc, TRUE,\r
- premoveHighlightInfo.sq[i].x, \r
- premoveHighlightInfo.sq[i].y,\r
- PREMOVE_PEN);\r
- }\r
- }\r
-}\r
-\r
-/* Note: sqcolor is used only in monoMode */\r
-/* Note that this code is largely duplicated in woptions.c,\r
- function DrawSampleSquare, so that needs to be updated too */\r
-VOID\r
-DrawPieceOnDC(HDC hdc, ChessSquare piece, int color, int sqcolor, int x, int y, HDC tmphdc)\r
-{\r
- HBITMAP oldBitmap;\r
- HBRUSH oldBrush;\r
-\r
- if (appData.blindfold) return;\r
-\r
- if (appData.monoMode) {\r
- SelectObject(tmphdc, PieceBitmap(piece, \r
- color == sqcolor ? OUTLINE_PIECE : SOLID_PIECE));\r
- BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0,\r
- sqcolor ? SRCCOPY : NOTSRCCOPY);\r
- } else {\r
- if (color) {\r
- oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, WHITE_PIECE));\r
- oldBrush = SelectObject(hdc, whitePieceBrush);\r
- BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
-#if 0\r
- /* Use black piece color for outline of white pieces */\r
- /* Not sure this looks really good (though xboard does it).\r
- Maybe better to have another selectable color, default black */\r
- SelectObject(hdc, blackPieceBrush); /* could have own brush */\r
- SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));\r
- BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
-#else\r
- /* Use black for outline of white pieces */\r
- SelectObject(tmphdc, PieceBitmap(piece, OUTLINE_PIECE));\r
- BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, SRCAND);\r
-#endif\r
- } else {\r
-#if 0\r
- /* Use white piece color 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
- /* Not sure this looks really good (though xboard does it).\r
- Maybe better to have another selectable color, default medium gray? */\r
- oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, BLACK_PIECE));\r
- oldBrush = SelectObject(hdc, whitePieceBrush); /* could have own brush */\r
- BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
- SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
- SelectObject(hdc, blackPieceBrush);\r
- BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
-#else\r
- /* Use square color for details of black pieces */\r
- oldBitmap = SelectObject(tmphdc, PieceBitmap(piece, SOLID_PIECE));\r
- oldBrush = SelectObject(hdc, blackPieceBrush);\r
- BitBlt(hdc, x, y, squareSize, squareSize, tmphdc, 0, 0, 0x00B8074A);\r
-#endif\r
- }\r
- SelectObject(hdc, oldBrush);\r
- SelectObject(tmphdc, oldBitmap);\r
- }\r
-}\r
-\r
-VOID\r
-DrawBoardOnDC(HDC hdc, Board board, HDC tmphdc)\r
-{\r
- int row, column, x, y, square_color, piece_color;\r
- ChessSquare piece;\r
- HBRUSH oldBrush;\r
-\r
- for (row = 0; row < BOARD_SIZE; row++) {\r
- for (column = 0; column < BOARD_SIZE; column++) {\r
- \r
- SquareToPos(row, column, &x, &y);\r
-\r
- piece = board[row][column];\r
-\r
- square_color = ((column + row) % 2) == 1;\r
- piece_color = (int) piece < (int) BlackPawn;\r
-\r
- if (appData.monoMode) {\r
- if (piece == EmptySquare) {\r
- BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0,\r
- square_color ? WHITENESS : BLACKNESS);\r
- } else {\r
- DrawPieceOnDC(hdc, piece, piece_color, square_color, x, y, tmphdc);\r
- }\r
- } else {\r
- oldBrush = SelectObject(hdc, square_color ?\r
- lightSquareBrush : darkSquareBrush);\r
- BitBlt(hdc, x, y, squareSize, squareSize, 0, 0, 0, PATCOPY);\r
- SelectObject(hdc, oldBrush);\r
- if (piece != EmptySquare)\r
- DrawPieceOnDC(hdc, piece, piece_color, -1, x, y, tmphdc);\r
- }\r
- }\r
- }\r
-}\r
-\r
-#define MAX_CLIPS 200 /* more than enough */\r
-\r
-VOID\r
-HDCDrawPosition(HDC hdc, BOOLEAN repaint, Board board)\r
-{\r
- static Board lastReq, lastDrawn;\r
- static HighlightInfo lastDrawnHighlight, lastDrawnPremove;\r
- static int lastDrawnFlipView = 0;\r
- static int lastReqValid = 0, lastDrawnValid = 0;\r
- int releaseDC, x, y, x2, y2, row, column, num_clips = 0, i;\r
- HDC tmphdc;\r
- HDC hdcmem;\r
- HBITMAP bufferBitmap;\r
- HBITMAP oldBitmap;\r
- RECT Rect;\r
- HRGN clips[MAX_CLIPS];\r
- ChessSquare dragged_piece = EmptySquare;\r
-\r
- /* I'm undecided on this - this function figures out whether a full\r
- * repaint is necessary on its own, so there's no real reason to have the\r
- * caller tell it that. I think this can safely be set to FALSE - but\r
- * if we trust the callers not to request full repaints unnessesarily, then\r
- * we could skip some clipping work. In other words, only request a full\r
- * redraw when the majority of pieces have changed positions (ie. flip, \r
- * gamestart and similar) --Hawk\r
- */\r
- Boolean fullrepaint = repaint;\r
-\r
- if (board == NULL) {\r
- if (!lastReqValid) {\r
- return;\r
- }\r
- board = lastReq;\r
- } else {\r
- CopyBoard(lastReq, board);\r
- lastReqValid = 1;\r
- }\r
-\r
- if (doingSizing) {\r
- return;\r
- }\r
-\r
- if (IsIconic(hwndMain)) {\r
- return;\r
- }\r
-\r
- if (hdc == NULL) {\r
- hdc = GetDC(hwndMain);\r
- if (!appData.monoMode) {\r
- SelectPalette(hdc, hPal, FALSE);\r
- RealizePalette(hdc);\r
- }\r
- releaseDC = TRUE;\r
- } else {\r
- releaseDC = FALSE;\r
- }\r
-\r
-#if 0\r
- fprintf(debugFP, "*******************************\n"\r
- "repaint = %s\n"\r
- "dragInfo.from (%d,%d)\n"\r
- "dragInfo.start (%d,%d)\n"\r
- "dragInfo.pos (%d,%d)\n"\r
- "dragInfo.lastpos (%d,%d)\n", \r
- repaint ? "TRUE" : "FALSE",\r
- dragInfo.from.x, dragInfo.from.y, \r
- dragInfo.start.x, dragInfo.start.y,\r
- dragInfo.pos.x, dragInfo.pos.y,\r
- dragInfo.lastpos.x, dragInfo.lastpos.y);\r
- fprintf(debugFP, "prev: ");\r
- for (row = 0; row < 8; row++) {\r
- for (column = 0; column < 8; column++) {\r
- fprintf(debugFP, "%d ", lastDrawn[row][column]);\r
- }\r
- }\r
- fprintf(debugFP, "\n");\r
- fprintf(debugFP, "board: ");\r
- for (row = 0; row < 8; row++) {\r
- for (column = 0; column < 8; column++) {\r
- fprintf(debugFP, "%d ", board[row][column]);\r
- }\r
- }\r
- fprintf(debugFP, "\n");\r
- fflush(debugFP);\r
-#endif\r
-\r
- /* Create some work-DCs */\r
- hdcmem = CreateCompatibleDC(hdc);\r
- tmphdc = CreateCompatibleDC(hdc);\r
-\r
- /* Figure out which squares need updating by comparing the \r
- * newest board with the last drawn board and checking if\r
- * flipping has changed.\r
- */\r
- if (!fullrepaint && lastDrawnValid && lastDrawnFlipView == flipView) {\r
- for (row = 0; row < 8; row++) {\r
- for (column = 0; column < 8; column++) {\r
- if (lastDrawn[row][column] != board[row][column]) {\r
- SquareToPos(row, column, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x, y, x + squareSize, y + squareSize);\r
- }\r
- }\r
- }\r
- for (i=0; i<2; i++) {\r
- if (lastDrawnHighlight.sq[i].x != highlightInfo.sq[i].x ||\r
- lastDrawnHighlight.sq[i].y != highlightInfo.sq[i].y) {\r
- if (lastDrawnHighlight.sq[i].x >= 0 &&\r
- lastDrawnHighlight.sq[i].y >= 0) {\r
- SquareToPos(lastDrawnHighlight.sq[i].y,\r
- lastDrawnHighlight.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- if (highlightInfo.sq[i].x >= 0 && highlightInfo.sq[i].y >= 0) {\r
- SquareToPos(highlightInfo.sq[i].y, highlightInfo.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- }\r
- }\r
- for (i=0; i<2; i++) {\r
- if (lastDrawnPremove.sq[i].x != premoveHighlightInfo.sq[i].x ||\r
- lastDrawnPremove.sq[i].y != premoveHighlightInfo.sq[i].y) {\r
- if (lastDrawnPremove.sq[i].x >= 0 &&\r
- lastDrawnPremove.sq[i].y >= 0) {\r
- SquareToPos(lastDrawnPremove.sq[i].y,\r
- lastDrawnPremove.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- if (premoveHighlightInfo.sq[i].x >= 0 && \r
- premoveHighlightInfo.sq[i].y >= 0) {\r
- SquareToPos(premoveHighlightInfo.sq[i].y, \r
- premoveHighlightInfo.sq[i].x, &x, &y);\r
- clips[num_clips++] =\r
- CreateRectRgn(x - lineGap, y - lineGap, \r
- x + squareSize + lineGap, y + squareSize + lineGap);\r
- }\r
- }\r
- }\r
- } else {\r
- fullrepaint = TRUE;\r
- }\r
-\r
- /* Create a buffer bitmap - this is the actual bitmap\r
- * being written to. When all the work is done, we can\r
- * copy it to the real DC (the screen). This avoids\r
- * the problems with flickering.\r
- */\r
- GetClientRect(hwndMain, &Rect);\r
- bufferBitmap = CreateCompatibleBitmap(hdc, Rect.right-Rect.left+1,\r
- Rect.bottom-Rect.top+1);\r
- oldBitmap = SelectObject(hdcmem, bufferBitmap);\r
- if (!appData.monoMode) {\r
- SelectPalette(hdcmem, hPal, FALSE);\r
- }\r
-\r
- /* Create clips for dragging */\r
- if (!fullrepaint) {\r
- if (dragInfo.from.x >= 0) {\r
- SquareToPos(dragInfo.from.y, dragInfo.from.x, &x, &y);\r
- clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize);\r
- }\r
- if (dragInfo.start.x >= 0) {\r
- SquareToPos(dragInfo.start.y, dragInfo.start.x, &x, &y);\r
- clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize);\r
- }\r
- if (dragInfo.pos.x >= 0) {\r
- x = dragInfo.pos.x - squareSize / 2;\r
- y = dragInfo.pos.y - squareSize / 2;\r
- clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize);\r
- }\r
- if (dragInfo.lastpos.x >= 0) {\r
- x = dragInfo.lastpos.x - squareSize / 2;\r
- y = dragInfo.lastpos.y - squareSize / 2;\r
- clips[num_clips++] = CreateRectRgn(x, y, x+squareSize, y+squareSize);\r
- }\r
- }\r
-\r
- /* If dragging is in progress, we temporarely remove the piece */\r
- if (dragInfo.from.x >= 0 && dragInfo.pos.x >= 0) {\r
- dragged_piece = board[dragInfo.from.y][dragInfo.from.x];\r
- board[dragInfo.from.y][dragInfo.from.x] = EmptySquare;\r
- }\r
-\r
- /* Are we animating a move? \r
- * If so, \r
- * - remove the piece from the board (temporarely)\r
- * - calculate the clipping region\r
- */\r
- if (!fullrepaint) {\r
- if (animInfo.piece != EmptySquare) {\r
- board[animInfo.from.y][animInfo.from.x] = EmptySquare;\r
- x = boardRect.left + animInfo.lastpos.x;\r
- y = boardRect.top + animInfo.lastpos.y;\r
- x2 = boardRect.left + animInfo.pos.x;\r
- y2 = boardRect.top + animInfo.pos.y;\r
- clips[num_clips++] = CreateRectRgn(MIN(x,x2), MIN(y,y2), MAX(x,x2)+squareSize, MAX(y,y2)+squareSize);\r
- /* Slight kludge. The real problem is that after AnimateMove is\r
- done, the position on the screen does not match lastDrawn.\r
- This currently causes trouble only on e.p. captures in\r
- atomic, where the piece moves to an empty square and then\r
- explodes. The old and new positions both had an empty square\r
- at the destination, but animation has drawn a piece there and\r
- we have to remember to erase it. */\r
- lastDrawn[animInfo.to.y][animInfo.to.x] = animInfo.piece;\r
- }\r
- }\r
-\r
- /* No clips? Make sure we have fullrepaint set to TRUE */\r
- if (num_clips == 0)\r
- fullrepaint = TRUE;\r
-\r
- /* Set clipping on the memory DC */\r
- if (!fullrepaint) {\r
- SelectClipRgn(hdcmem, clips[0]);\r
- for (x = 1; x < num_clips; x++) {\r
- if (ExtSelectClipRgn(hdcmem, clips[x], RGN_OR) == ERROR)\r
- abort(); // this should never ever happen!\r
- }\r
- }\r
-\r
- /* Do all the drawing to the memory DC */\r
- DrawGridOnDC(hdcmem);\r
- DrawHighlightsOnDC(hdcmem);\r
- DrawBoardOnDC(hdcmem, board, tmphdc);\r
- DrawCoordsOnDC(hdcmem);\r
-\r
- /* Put the dragged piece back into place and draw it */\r
- if (dragged_piece != EmptySquare) {\r
- board[dragInfo.from.y][dragInfo.from.x] = dragged_piece;\r
- x = dragInfo.pos.x - squareSize / 2;\r
- y = dragInfo.pos.y - squareSize / 2;\r
- DrawPieceOnDC(hdcmem, dragged_piece,\r
- ((int) dragged_piece < (int) BlackPawn), \r
- (dragInfo.from.y + dragInfo.from.x) % 2, x, y, tmphdc);\r
- } \r
- \r
- /* Put the animated piece back into place and draw it */\r
- if (animInfo.piece != EmptySquare) {\r
- board[animInfo.from.y][animInfo.from.x] = animInfo.piece;\r
- x = boardRect.left + animInfo.pos.x;\r
- y = boardRect.top + animInfo.pos.y;\r
- DrawPieceOnDC(hdcmem, animInfo.piece,\r
- ((int) animInfo.piece < (int) BlackPawn),\r
- (animInfo.from.y + animInfo.from.x) % 2, x, y, tmphdc);\r
- }\r
-\r
- /* Release the bufferBitmap by selecting in the old bitmap \r
- * and delete the memory DC\r
- */\r
- SelectObject(hdcmem, oldBitmap);\r
- DeleteDC(hdcmem);\r
-\r
- /* Set clipping on the target DC */\r
- if (!fullrepaint) {\r
- SelectClipRgn(hdc, clips[0]);\r
- for (x = 1; x < num_clips; x++) {\r
- if (ExtSelectClipRgn(hdc, clips[x], RGN_OR) == ERROR)\r
- abort(); // this should never ever happen!\r
- } \r
- }\r
-\r
- /* Copy the new bitmap onto the screen in one go.\r
- * This way we avoid any flickering\r
- */\r
- oldBitmap = SelectObject(tmphdc, bufferBitmap);\r
- BitBlt(hdc, boardRect.left, boardRect.top,\r
- boardRect.right - boardRect.left,\r
- boardRect.bottom - boardRect.top,\r
- tmphdc, boardRect.left, boardRect.top, SRCCOPY);\r
- SelectObject(tmphdc, oldBitmap);\r
-\r
- /* Massive cleanup */\r
- for (x = 0; x < num_clips; x++)\r
- DeleteObject(clips[x]);\r
-\r
- DeleteDC(tmphdc);\r
- DeleteObject(bufferBitmap);\r
-\r
- if (releaseDC) \r
- ReleaseDC(hwndMain, hdc);\r
- \r
- if (lastDrawnFlipView != flipView) {\r
- if (flipView)\r
- CheckMenuItem(GetMenu(hwndMain),IDM_FlipView, MF_BYCOMMAND|MF_CHECKED);\r
- else\r
- CheckMenuItem(GetMenu(hwndMain),IDM_FlipView, MF_BYCOMMAND|MF_UNCHECKED);\r
- }\r
-\r
- CopyBoard(lastDrawn, board);\r
- lastDrawnHighlight = highlightInfo;\r
- lastDrawnPremove = premoveHighlightInfo;\r
- lastDrawnFlipView = flipView;\r
- lastDrawnValid = 1;\r
-}\r
-\r
-\r
-/*---------------------------------------------------------------------------*\\r
-| CLIENT PAINT PROCEDURE\r
-| This is the main event-handler for the WM_PAINT message.\r
-|\r
-\*---------------------------------------------------------------------------*/\r
-VOID\r
-PaintProc(HWND hwnd)\r
-{\r
- HDC hdc;\r
- PAINTSTRUCT ps;\r
- HFONT oldFont;\r
-\r
- if(hdc = BeginPaint(hwnd, &ps)) {\r
- if (IsIconic(hwnd)) {\r
- DrawIcon(hdc, 2, 2, iconCurrent);\r
- } else {\r
- if (!appData.monoMode) {\r
- SelectPalette(hdc, hPal, FALSE);\r
- RealizePalette(hdc);\r
- }\r
- HDCDrawPosition(hdc, 1, NULL);\r
- oldFont =\r
- SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);\r
- ExtTextOut(hdc, messageRect.left, messageRect.top,\r
- ETO_CLIPPED|ETO_OPAQUE,\r
- &messageRect, messageText, strlen(messageText), NULL);\r
- SelectObject(hdc, oldFont);\r
- DisplayBothClocks();\r
- }\r
- EndPaint(hwnd,&ps);\r
- }\r
-\r
- return;\r
-}\r
-\r
-\r
-/*\r
- * If the user selects on a border boundary, return -1; if off the board,\r
- * return -2. Otherwise map the event coordinate to the square.\r
- * The offset boardRect.left or boardRect.top must already have been\r
- * subtracted from x.\r
- */\r
-int\r
-EventToSquare(int x)\r
-{\r
- if (x <= 0)\r
- return -2;\r
- if (x < lineGap)\r
- return -1;\r
- x -= lineGap;\r
- if ((x % (squareSize + lineGap)) >= squareSize)\r
- return -1;\r
- x /= (squareSize + lineGap);\r
- if (x >= BOARD_SIZE)\r
- return -2;\r
- return x;\r
-}\r
-\r
-typedef struct {\r
- char piece;\r
- int command;\r
- char* name;\r
-} DropEnable;\r
-\r
-DropEnable dropEnables[] = {\r
- { 'P', DP_Pawn, "Pawn" },\r
- { 'N', DP_Knight, "Knight" },\r
- { 'B', DP_Bishop, "Bishop" },\r
- { 'R', DP_Rook, "Rook" },\r
- { 'Q', DP_Queen, "Queen" },\r
-};\r
-\r
-VOID\r
-SetupDropMenu(HMENU hmenu)\r
-{\r
- int i, count, enable;\r
- char *p;\r
- extern char white_holding[], black_holding[];\r
- char item[MSG_SIZ];\r
-\r
- for (i=0; i<sizeof(dropEnables)/sizeof(DropEnable); i++) {\r
- p = strchr(gameMode == IcsPlayingWhite ? white_holding : black_holding,\r
- dropEnables[i].piece);\r
- count = 0;\r
- while (p && *p++ == dropEnables[i].piece) count++;\r
- sprintf(item, "%s %d", dropEnables[i].name, count);\r
- enable = count > 0 || !appData.testLegality\r
- /*!!temp:*/ || (gameInfo.variant == VariantCrazyhouse\r
- && !appData.icsActive);\r
- ModifyMenu(hmenu, dropEnables[i].command,\r
- MF_BYCOMMAND | (enable ? MF_ENABLED : MF_GRAYED) | MF_STRING,\r
- dropEnables[i].command, item);\r
- }\r
-}\r
-\r
-static int fromX = -1, fromY = -1, toX, toY;\r
-\r
-/* Event handler for mouse messages */\r
-VOID\r
-MouseEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- int x, y;\r
- POINT pt;\r
- static int recursive = 0;\r
- HMENU hmenu;\r
- BOOLEAN saveAnimate;\r
- static BOOLEAN sameAgain = FALSE;\r
-\r
- if (recursive) {\r
- if (message == WM_MBUTTONUP) {\r
- /* Hideous kludge to fool TrackPopupMenu into paying attention\r
- to the middle button: we simulate pressing the left button too!\r
- */\r
- PostMessage(hwnd, WM_LBUTTONDOWN, wParam, lParam);\r
- PostMessage(hwnd, WM_LBUTTONUP, wParam, lParam);\r
- }\r
- return;\r
- }\r
- recursive++;\r
- \r
- pt.x = LOWORD(lParam);\r
- pt.y = HIWORD(lParam);\r
- x = EventToSquare(pt.x - boardRect.left);\r
- y = EventToSquare(pt.y - boardRect.top);\r
- if (!flipView && y >= 0) {\r
- y = BOARD_SIZE - 1 - y;\r
- }\r
- if (flipView && x >= 0) {\r
- x = BOARD_SIZE - 1 - x;\r
- }\r
-\r
- switch (message) {\r
- case WM_LBUTTONDOWN:\r
- ErrorPopDown();\r
- sameAgain = FALSE;\r
- if (y == -2) {\r
- /* Downclick vertically off board; check if on clock */\r
- if (PtInRect((LPRECT) &whiteRect, pt)) {\r
- if (gameMode == EditPosition) {\r
- SetWhiteToPlayEvent();\r
- } else if (gameMode == IcsPlayingBlack ||\r
- gameMode == MachinePlaysWhite) {\r
- CallFlagEvent();\r
- }\r
- } else if (PtInRect((LPRECT) &blackRect, pt)) {\r
- if (gameMode == EditPosition) {\r
- SetBlackToPlayEvent();\r
- } else if (gameMode == IcsPlayingWhite ||\r
- gameMode == MachinePlaysBlack) {\r
- CallFlagEvent();\r
- }\r
- }\r
- if (!appData.highlightLastMove) {\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- }\r
- fromX = fromY = -1;\r
- dragInfo.start.x = dragInfo.start.y = -1;\r
- dragInfo.from = dragInfo.start;\r
- break;\r
- } else if (x < 0 || y < 0) {\r
- break;\r
- } else if (fromX == x && fromY == y) {\r
- /* Downclick on same square again */\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- sameAgain = TRUE; \r
- } else if (fromX != -1) {\r
- /* Downclick on different square */\r
- ChessSquare pdown, pup;\r
- pdown = boards[currentMove][fromY][fromX];\r
- pup = boards[currentMove][y][x];\r
- if (gameMode == EditPosition ||\r
- !((WhitePawn <= pdown && pdown <= WhiteKing &&\r
- WhitePawn <= pup && pup <= WhiteKing) ||\r
- (BlackPawn <= pdown && pdown <= BlackKing &&\r
- BlackPawn <= pup && pup <= BlackKing))) {\r
- /* EditPosition, empty square, or different color piece;\r
- click-click move is possible */\r
- toX = x;\r
- toY = y;\r
- if (IsPromotion(fromX, fromY, toX, toY)) {\r
- if (appData.alwaysPromoteToQueen) {\r
- UserMoveEvent(fromX, fromY, toX, toY, 'q');\r
- if (!appData.highlightLastMove) {\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- }\r
- } else {\r
- SetHighlights(fromX, fromY, toX, toY);\r
- DrawPosition(FALSE, NULL);\r
- PromotionPopup(hwnd);\r
- }\r
- } else { /* not a promotion */\r
- if (appData.animate || appData.highlightLastMove) {\r
- SetHighlights(fromX, fromY, toX, toY);\r
- } else {\r
- ClearHighlights();\r
- }\r
- UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);\r
- if (appData.animate && !appData.highlightLastMove) {\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- }\r
- }\r
- if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
- fromX = fromY = -1;\r
- break;\r
- }\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- }\r
- /* First downclick, or restart on a square with same color piece */\r
- if (!frozen && OKToStartUserMove(x, y)) {\r
- fromX = x;\r
- fromY = y;\r
- dragInfo.lastpos = pt;\r
- dragInfo.from.x = fromX;\r
- dragInfo.from.y = fromY;\r
- dragInfo.start = dragInfo.from;\r
- SetCapture(hwndMain);\r
- } else {\r
- fromX = fromY = -1;\r
- dragInfo.start.x = dragInfo.start.y = -1;\r
- dragInfo.from = dragInfo.start;\r
- }\r
- break;\r
-\r
- case WM_LBUTTONUP:\r
- ReleaseCapture();\r
- if (fromX == -1) break;\r
- if (x == fromX && y == fromY) {\r
- dragInfo.from.x = dragInfo.from.y = -1;\r
- /* Upclick on same square */\r
- if (sameAgain) {\r
- /* Clicked same square twice: abort click-click move */\r
- fromX = fromY = -1;\r
- gotPremove = 0;\r
- ClearPremoveHighlights();\r
- } else {\r
- /* First square clicked: start click-click move */\r
- SetHighlights(fromX, fromY, -1, -1);\r
- }\r
- DrawPosition(FALSE, NULL);\r
- } else if (dragInfo.from.x < 0 || dragInfo.from.y < 0) {\r
- /* Errant click; ignore */\r
- break;\r
- } else {\r
- /* Finish drag move */\r
- dragInfo.from.x = dragInfo.from.y = -1;\r
- toX = x;\r
- toY = y;\r
- saveAnimate = appData.animate; /* sorry, Hawk :) */\r
- appData.animate = appData.animate && !appData.animateDragging;\r
- if (IsPromotion(fromX, fromY, toX, toY)) {\r
- if (appData.alwaysPromoteToQueen) {\r
- UserMoveEvent(fromX, fromY, toX, toY, 'q');\r
- } else {\r
- DrawPosition(FALSE, NULL);\r
- PromotionPopup(hwnd);\r
- }\r
- } else {\r
- UserMoveEvent(fromX, fromY, toX, toY, NULLCHAR);\r
- }\r
- if (gotPremove) SetPremoveHighlights(fromX, fromY, toX, toY);\r
- appData.animate = saveAnimate;\r
- fromX = fromY = -1;\r
- if (appData.highlightDragging && !appData.highlightLastMove) {\r
- ClearHighlights();\r
- }\r
- if (appData.animate || appData.animateDragging ||\r
- appData.highlightDragging || gotPremove) {\r
- DrawPosition(FALSE, NULL);\r
- }\r
- }\r
- dragInfo.start.x = dragInfo.start.y = -1; \r
- dragInfo.pos = dragInfo.lastpos = dragInfo.start;\r
- break;\r
-\r
- case WM_MOUSEMOVE:\r
- if ((appData.animateDragging || appData.highlightDragging)\r
- && (wParam & MK_LBUTTON)\r
- && dragInfo.from.x >= 0) {\r
- if (appData.animateDragging) {\r
- dragInfo.pos = pt;\r
- }\r
- if (appData.highlightDragging) {\r
- SetHighlights(fromX, fromY, x, y);\r
- }\r
- DrawPosition(FALSE, NULL);\r
- dragInfo.lastpos = dragInfo.pos;\r
- }\r
- break;\r
- case WM_MOUSEWHEEL:\r
- /* Mouse Wheel is being rolled forward \r
- * Play moves forward\r
- */\r
- if ((short)HIWORD(wParam) > 0) \r
- if (forwardMostMove > 0 && currentMove != forwardMostMove)\r
- ForwardEvent();\r
- /* Mouse Wheel is being rolled backward \r
- * Play moves backward\r
- */\r
- if ((short)HIWORD(wParam) < 0) \r
- if (currentMove > 0) BackwardEvent();\r
- break;\r
- case WM_MBUTTONDOWN:\r
- case WM_RBUTTONDOWN:\r
- ErrorPopDown();\r
- ReleaseCapture();\r
- fromX = fromY = -1;\r
- dragInfo.pos.x = dragInfo.pos.y = -1;\r
- dragInfo.start.x = dragInfo.start.y = -1;\r
- dragInfo.from = dragInfo.start;\r
- dragInfo.lastpos = dragInfo.pos;\r
- if (appData.highlightDragging) {\r
- ClearHighlights();\r
- }\r
- DrawPosition(TRUE, NULL);\r
-\r
- switch (gameMode) {\r
- case EditPosition:\r
- case IcsExamining:\r
- if (x < 0 || y < 0) break;\r
- fromX = x;\r
- fromY = y;\r
- if (message == WM_MBUTTONDOWN) {\r
- buttonCount = 3; /* even if system didn't think so */\r
- if (wParam & MK_SHIFT) \r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "BlackPieceMenu"), -1);\r
- else\r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "WhitePieceMenu"), -1);\r
- } else { /* message == WM_RBUTTONDOWN */\r
-#if 0\r
- if (buttonCount == 3) {\r
- if (wParam & MK_SHIFT) \r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "WhitePieceMenu"), -1);\r
- else\r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "BlackPieceMenu"), -1);\r
- } else {\r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\r
- }\r
-#else\r
- /* Just have one menu, on the right button. Windows users don't\r
- think to try the middle one, and sometimes other software steals\r
- it, or it doesn't really exist. */\r
- MenuPopup(hwnd, pt, LoadMenu(hInst, "PieceMenu"), -1);\r
-#endif\r
- }\r
- break;\r
- case IcsPlayingWhite:\r
- case IcsPlayingBlack:\r
- case EditGame:\r
- case MachinePlaysWhite:\r
- case MachinePlaysBlack:\r
- if (appData.testLegality &&\r
- gameInfo.variant != VariantBughouse &&\r
- gameInfo.variant != VariantCrazyhouse) break;\r
- if (x < 0 || y < 0) break;\r
- fromX = x;\r
- fromY = y;\r
- hmenu = LoadMenu(hInst, "DropPieceMenu");\r
- SetupDropMenu(hmenu);\r
- MenuPopup(hwnd, pt, hmenu, -1);\r
- break;\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
-\r
- recursive--;\r
-}\r
-\r
-/* Preprocess messages for buttons in main window */\r
-LRESULT CALLBACK\r
-ButtonProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- int id = GetWindowLong(hwnd, GWL_ID);\r
- int i, dir;\r
-\r
- for (i=0; i<N_BUTTONS; i++) {\r
- if (buttonDesc[i].id == id) break;\r
- }\r
- if (i == N_BUTTONS) return 0;\r
- switch (message) {\r
- case WM_KEYDOWN:\r
- switch (wParam) {\r
- case VK_LEFT:\r
- case VK_RIGHT:\r
- dir = (wParam == VK_LEFT) ? -1 : 1;\r
- SetFocus(buttonDesc[(i + dir + N_BUTTONS) % N_BUTTONS].hwnd);\r
- return TRUE;\r
- }\r
- break;\r
- case WM_CHAR:\r
- switch (wParam) {\r
- case '\r':\r
- SendMessage(hwndMain, WM_COMMAND, MAKEWPARAM(buttonDesc[i].id, 0), 0);\r
- return TRUE;\r
- case '\t':\r
- if (appData.icsActive) {\r
- if (GetKeyState(VK_SHIFT) < 0) {\r
- /* shifted */\r
- HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
- SetFocus(h);\r
- } else {\r
- /* unshifted */\r
- HWND h = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
- if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
- SetFocus(h);\r
- }\r
- return TRUE;\r
- }\r
- break;\r
- default:\r
- if (appData.icsActive) {\r
- HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
- SetFocus(h);\r
- SendMessage(h, WM_CHAR, wParam, lParam);\r
- return TRUE;\r
- } else if (isalpha((char)wParam) || isdigit((char)wParam)){\r
- PopUpMoveDialog((char)wParam);\r
- }\r
- break;\r
- }\r
- break;\r
- }\r
- return CallWindowProc(buttonDesc[i].wndproc, hwnd, message, wParam, lParam);\r
-}\r
-\r
-/* Process messages for Promotion dialog box */\r
-LRESULT CALLBACK\r
-Promotion(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- char promoChar;\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
- ShowWindow(GetDlgItem(hDlg, PB_King), \r
- (!appData.testLegality || gameInfo.variant == VariantSuicide ||\r
- gameInfo.variant == VariantGiveaway) ?\r
- SW_SHOW : SW_HIDE);\r
- return TRUE;\r
-\r
- case WM_COMMAND: /* message: received a command */\r
- switch (LOWORD(wParam)) {\r
- case IDCANCEL:\r
- EndDialog(hDlg, TRUE); /* Exit the dialog */\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- return TRUE;\r
- case PB_King:\r
- promoChar = 'k';\r
- break;\r
- case PB_Queen:\r
- promoChar = 'q';\r
- break;\r
- case PB_Rook:\r
- promoChar = 'r';\r
- break;\r
- case PB_Bishop:\r
- promoChar = 'b';\r
- break;\r
- case PB_Knight:\r
- promoChar = 'n';\r
- break;\r
- default:\r
- return FALSE;\r
- }\r
- EndDialog(hDlg, TRUE); /* Exit the dialog */\r
- UserMoveEvent(fromX, fromY, toX, toY, promoChar);\r
- if (!appData.highlightLastMove) {\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- }\r
- return TRUE;\r
- }\r
- return FALSE;\r
-}\r
-\r
-/* Pop up promotion dialog */\r
-VOID\r
-PromotionPopup(HWND hwnd)\r
-{\r
- FARPROC lpProc;\r
-\r
- lpProc = MakeProcInstance((FARPROC)Promotion, hInst);\r
- DialogBox(hInst, MAKEINTRESOURCE(DLG_PromotionKing),\r
- hwnd, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
-}\r
-\r
-/* Toggle ShowThinking */\r
-VOID\r
-ToggleShowThinking()\r
-{\r
- ShowThinkingEvent(!appData.showThinking);\r
-}\r
-\r
-VOID\r
-LoadGameDialog(HWND hwnd, char* title)\r
-{\r
- UINT number = 0;\r
- FILE *f;\r
- char fileTitle[MSG_SIZ];\r
- f = OpenFileDialog(hwnd, FALSE, "",\r
- appData.oldSaveStyle ? "gam" : "pgn",\r
- GAME_FILT,\r
- title, &number, fileTitle, NULL);\r
- if (f != NULL) {\r
- cmailMsgLoaded = FALSE;\r
- if (number == 0) {\r
- int error = GameListBuild(f);\r
- if (error) {\r
- DisplayError("Cannot build game list", error);\r
- } else if (!ListEmpty(&gameList) &&\r
- ((ListGame *) gameList.tailPred)->number > 1) {\r
- GameListPopUp(f, fileTitle);\r
- return;\r
- }\r
- GameListDestroy();\r
- number = 1;\r
- }\r
- LoadGame(f, number, fileTitle, FALSE);\r
- }\r
-}\r
-\r
-VOID\r
-ChangedConsoleFont()\r
-{\r
- CHARFORMAT cfmt;\r
- CHARRANGE tmpsel, sel;\r
- MyFont *f = font[boardSize][CONSOLE_FONT];\r
- HWND hText = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
- HWND hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- PARAFORMAT paraf;\r
-\r
- cfmt.cbSize = sizeof(CHARFORMAT);\r
- cfmt.dwMask = CFM_FACE|CFM_SIZE|CFM_CHARSET;\r
- strcpy(cfmt.szFaceName, font[boardSize][CONSOLE_FONT]->mfp.faceName);\r
- /* yHeight is expressed in twips. A twip is 1/20 of a font's point\r
- * size. This was undocumented in the version of MSVC++ that I had\r
- * when I wrote the code, but is apparently documented now.\r
- */\r
- cfmt.yHeight = (int)(f->mfp.pointSize * 20.0 + 0.5);\r
- cfmt.bCharSet = f->lf.lfCharSet;\r
- cfmt.bPitchAndFamily = f->lf.lfPitchAndFamily;\r
- SendMessage(hText, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cfmt); \r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &cfmt); \r
- /* Why are the following seemingly needed too? */\r
- SendMessage(hText, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM) &cfmt); \r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_DEFAULT, (LPARAM) &cfmt); \r
- SendMessage(hText, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- tmpsel.cpMin = 0;\r
- tmpsel.cpMax = -1; /*999999?*/\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&tmpsel);\r
- SendMessage(hText, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM) &cfmt); \r
- /* Trying putting this here too. It still seems to tickle a RichEdit\r
- * bug: sometimes RichEdit indents the first line of a paragraph too.\r
- */\r
- paraf.cbSize = sizeof(paraf);\r
- paraf.dwMask = PFM_OFFSET | PFM_STARTINDENT;\r
- paraf.dxStartIndent = 0;\r
- paraf.dxOffset = WRAP_INDENT;\r
- SendMessage(hText, EM_SETPARAFORMAT, 0, (LPARAM) ¶f);\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Window Proc for main window\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/* Process messages for main window, etc. */\r
-LRESULT CALLBACK\r
-WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- FARPROC lpProc;\r
- int wmId, wmEvent;\r
- char *defName;\r
- FILE *f;\r
- UINT number;\r
- char fileTitle[MSG_SIZ];\r
-\r
- switch (message) {\r
-\r
- case WM_PAINT: /* message: repaint portion of window */\r
- PaintProc(hwnd);\r
- break;\r
-\r
- case WM_ERASEBKGND:\r
- if (IsIconic(hwnd)) {\r
- /* Cheat; change the message */\r
- return (DefWindowProc(hwnd, WM_ICONERASEBKGND, wParam, lParam));\r
- } else {\r
- return (DefWindowProc(hwnd, message, wParam, lParam));\r
- }\r
- break;\r
-\r
- case WM_LBUTTONDOWN:\r
- case WM_MBUTTONDOWN:\r
- case WM_RBUTTONDOWN:\r
- case WM_LBUTTONUP:\r
- case WM_MBUTTONUP:\r
- case WM_RBUTTONUP:\r
- case WM_MOUSEMOVE:\r
- case WM_MOUSEWHEEL:\r
- MouseEvent(hwnd, message, wParam, lParam);\r
- break;\r
-\r
- case WM_CHAR:\r
- \r
- if (appData.icsActive) {\r
- if (wParam == '\t') {\r
- if (GetKeyState(VK_SHIFT) < 0) {\r
- /* shifted */\r
- HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
- SetFocus(h);\r
- } else {\r
- /* unshifted */\r
- HWND h = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
- if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
- SetFocus(h);\r
- }\r
- } else {\r
- HWND h = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- if (IsIconic(hwndConsole)) ShowWindow(hwndConsole, SW_RESTORE);\r
- SetFocus(h);\r
- SendMessage(h, message, wParam, lParam);\r
- }\r
- } else if (isalpha((char)wParam) || isdigit((char)wParam)) {\r
- PopUpMoveDialog((char)wParam);\r
- }\r
- break;\r
-\r
- case WM_PALETTECHANGED:\r
- if (hwnd != (HWND)wParam && !appData.monoMode) {\r
- int nnew;\r
- HDC hdc = GetDC(hwndMain);\r
- SelectPalette(hdc, hPal, TRUE);\r
- nnew = RealizePalette(hdc);\r
- if (nnew > 0) {\r
- paletteChanged = TRUE;\r
-#if 0\r
- UpdateColors(hdc);\r
-#else\r
- InvalidateRect(hwnd, &boardRect, FALSE);/*faster!*/\r
-#endif\r
- }\r
- ReleaseDC(hwnd, hdc);\r
- }\r
- break;\r
-\r
- case WM_QUERYNEWPALETTE:\r
- if (!appData.monoMode /*&& paletteChanged*/) {\r
- int nnew;\r
- HDC hdc = GetDC(hwndMain);\r
- paletteChanged = FALSE;\r
- SelectPalette(hdc, hPal, FALSE);\r
- nnew = RealizePalette(hdc);\r
- if (nnew > 0) {\r
- InvalidateRect(hwnd, &boardRect, FALSE);\r
- }\r
- ReleaseDC(hwnd, hdc);\r
- return TRUE;\r
- }\r
- return FALSE;\r
-\r
- case WM_COMMAND: /* message: command from application menu */\r
- wmId = LOWORD(wParam);\r
- wmEvent = HIWORD(wParam);\r
-\r
- switch (wmId) {\r
- case IDM_NewGame:\r
- ResetGameEvent();\r
- AnalysisPopDown();\r
- break;\r
-\r
- case IDM_LoadGame:\r
- LoadGameDialog(hwnd, "Load Game from File");\r
- break;\r
-\r
- case IDM_LoadNextGame:\r
- ReloadGame(1);\r
- break;\r
-\r
- case IDM_LoadPrevGame:\r
- ReloadGame(-1);\r
- break;\r
-\r
- case IDM_ReloadGame:\r
- ReloadGame(0);\r
- break;\r
-\r
- case IDM_LoadPosition:\r
- if (gameMode == AnalyzeMode || gameMode == AnalyzeFile) {\r
- Reset(FALSE, TRUE);\r
- }\r
- number = 1;\r
- f = OpenFileDialog(hwnd, FALSE, "",\r
- appData.oldSaveStyle ? "pos" : "fen",\r
- POSITION_FILT,\r
- "Load Position from File", &number, fileTitle, NULL);\r
- if (f != NULL) {\r
- LoadPosition(f, number, fileTitle);\r
- }\r
- break;\r
-\r
- case IDM_LoadNextPosition:\r
- ReloadPosition(1);\r
- break;\r
-\r
- case IDM_LoadPrevPosition:\r
- ReloadPosition(-1);\r
- break;\r
-\r
- case IDM_ReloadPosition:\r
- ReloadPosition(0);\r
- break;\r
-\r
- case IDM_SaveGame:\r
- defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn");\r
- f = OpenFileDialog(hwnd, TRUE, defName,\r
- appData.oldSaveStyle ? "gam" : "pgn",\r
- GAME_FILT,\r
- "Save Game to File", NULL, fileTitle, NULL);\r
- if (f != NULL) {\r
- SaveGame(f, 0, "");\r
- }\r
- break;\r
-\r
- case IDM_SavePosition:\r
- defName = DefaultFileName(appData.oldSaveStyle ? "pos" : "fen");\r
- f = OpenFileDialog(hwnd, TRUE, defName,\r
- appData.oldSaveStyle ? "pos" : "fen",\r
- POSITION_FILT,\r
- "Save Position to File", NULL, fileTitle, NULL);\r
- if (f != NULL) {\r
- SavePosition(f, 0, "");\r
- }\r
- break;\r
-\r
- case IDM_CopyGame:\r
- CopyGameToClipboard();\r
- break;\r
-\r
- case IDM_PasteGame:\r
- PasteGameFromClipboard();\r
- break;\r
-\r
- case IDM_CopyPosition:\r
- CopyFENToClipboard();\r
- break;\r
-\r
- case IDM_PastePosition:\r
- PasteFENFromClipboard();\r
- break;\r
-\r
- case IDM_MailMove:\r
- MailMoveEvent();\r
- break;\r
-\r
- case IDM_ReloadCMailMsg:\r
- Reset(TRUE, TRUE);\r
- ReloadCmailMsgEvent(FALSE);\r
- break;\r
-\r
- case IDM_Minimize:\r
- ShowWindow(hwnd, SW_MINIMIZE);\r
- break;\r
-\r
- case IDM_Exit:\r
- ExitEvent(0);\r
- break;\r
-\r
- case IDM_MachineWhite:\r
- MachineWhiteEvent();\r
- /*\r
- * refresh the tags dialog only if it's visible\r
- */\r
- if (gameMode == MachinePlaysWhite && IsWindowVisible(editTagsDialog)) {\r
- char *tags;\r
- tags = PGNTags(&gameInfo);\r
- TagsPopUp(tags, CmailMsg());\r
- free(tags);\r
- }\r
- break;\r
-\r
- case IDM_MachineBlack:\r
- MachineBlackEvent();\r
- /*\r
- * refresh the tags dialog only if it's visible\r
- */\r
- if (gameMode == MachinePlaysBlack && IsWindowVisible(editTagsDialog)) {\r
- char *tags;\r
- tags = PGNTags(&gameInfo);\r
- TagsPopUp(tags, CmailMsg());\r
- free(tags);\r
- }\r
- break;\r
-\r
- case IDM_TwoMachines:\r
- TwoMachinesEvent();\r
- /*\r
- * refresh the tags dialog only if it's visible\r
- */\r
- if (gameMode == TwoMachinesPlay && IsWindowVisible(editTagsDialog)) {\r
- char *tags;\r
- tags = PGNTags(&gameInfo);\r
- TagsPopUp(tags, CmailMsg());\r
- free(tags);\r
- }\r
- break;\r
-\r
- case IDM_AnalysisMode:\r
- if (!first.analysisSupport) {\r
- char buf[MSG_SIZ];\r
- sprintf(buf, "%s does not support analysis", first.tidy);\r
- DisplayError(buf, 0);\r
- } else {\r
- if (!appData.showThinking) ToggleShowThinking();\r
- AnalyzeModeEvent();\r
- }\r
- break;\r
-\r
- case IDM_AnalyzeFile:\r
- if (!first.analysisSupport) {\r
- char buf[MSG_SIZ];\r
- sprintf(buf, "%s does not support analysis", first.tidy);\r
- DisplayError(buf, 0);\r
- } else {\r
- if (!appData.showThinking) ToggleShowThinking();\r
- AnalyzeFileEvent();\r
- LoadGameDialog(hwnd, "Analyze Game from File");\r
- AnalysisPeriodicEvent(1);\r
- }\r
- break;\r
-\r
- case IDM_IcsClient:\r
- IcsClientEvent();\r
- break;\r
-\r
- case IDM_EditGame:\r
- EditGameEvent();\r
- break;\r
-\r
- case IDM_EditPosition:\r
- EditPositionEvent();\r
- break;\r
-\r
- case IDM_Training:\r
- TrainingEvent();\r
- break;\r
-\r
- case IDM_ShowGameList:\r
- ShowGameListProc();\r
- break;\r
-\r
- case IDM_EditTags:\r
- EditTagsProc();\r
- break;\r
-\r
- case IDM_EditComment:\r
- if (commentDialogUp && editComment) {\r
- CommentPopDown();\r
- } else {\r
- EditCommentEvent();\r
- }\r
- break;\r
-\r
- case IDM_Pause:\r
- PauseEvent();\r
- break;\r
-\r
- case IDM_Accept:\r
- AcceptEvent();\r
- break;\r
-\r
- case IDM_Decline:\r
- DeclineEvent();\r
- break;\r
-\r
- case IDM_Rematch:\r
- RematchEvent();\r
- break;\r
-\r
- case IDM_CallFlag:\r
- CallFlagEvent();\r
- break;\r
-\r
- case IDM_Draw:\r
- DrawEvent();\r
- break;\r
-\r
- case IDM_Adjourn:\r
- AdjournEvent();\r
- break;\r
-\r
- case IDM_Abort:\r
- AbortEvent();\r
- break;\r
-\r
- case IDM_Resign:\r
- ResignEvent();\r
- break;\r
-\r
- case IDM_StopObserving:\r
- StopObservingEvent();\r
- break;\r
-\r
- case IDM_StopExamining:\r
- StopExaminingEvent();\r
- break;\r
-\r
- case IDM_TypeInMove:\r
- PopUpMoveDialog('\000');\r
- break;\r
-\r
- case IDM_Backward:\r
- BackwardEvent();\r
- SetFocus(hwndMain);\r
- break;\r
-\r
- case IDM_Forward:\r
- ForwardEvent();\r
- SetFocus(hwndMain);\r
- break;\r
-\r
- case IDM_ToStart:\r
- ToStartEvent();\r
- SetFocus(hwndMain);\r
- break;\r
-\r
- case IDM_ToEnd:\r
- ToEndEvent();\r
- SetFocus(hwndMain);\r
- break;\r
-\r
- case IDM_Revert:\r
- RevertEvent();\r
- break;\r
-\r
- case IDM_TruncateGame:\r
- TruncateGameEvent();\r
- break;\r
-\r
- case IDM_MoveNow:\r
- MoveNowEvent();\r
- break;\r
-\r
- case IDM_RetractMove:\r
- RetractMoveEvent();\r
- break;\r
-\r
- case IDM_FlipView:\r
- flipView = !flipView;\r
- DrawPosition(FALSE, NULL);\r
- break;\r
-\r
- case IDM_GeneralOptions:\r
- GeneralOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_BoardOptions:\r
- BoardOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_IcsOptions:\r
- IcsOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_Fonts:\r
- FontsOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_Sounds:\r
- SoundOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_CommPort:\r
- CommPortOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_LoadOptions:\r
- LoadOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_SaveOptions:\r
- SaveOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_TimeControl:\r
- TimeControlOptionsPopup(hwnd);\r
- break;\r
-\r
- case IDM_SaveSettings:\r
- SaveSettings(settingsFileName);\r
- break;\r
-\r
- case IDM_SaveSettingsOnExit:\r
- saveSettingsOnExit = !saveSettingsOnExit;\r
- (void) CheckMenuItem(GetMenu(hwndMain), IDM_SaveSettingsOnExit,\r
- MF_BYCOMMAND|(saveSettingsOnExit ?\r
- MF_CHECKED : MF_UNCHECKED));\r
- break;\r
-\r
- case IDM_Hint:\r
- HintEvent();\r
- break;\r
-\r
- case IDM_Book:\r
- BookEvent();\r
- break;\r
-\r
- case IDM_AboutGame:\r
- AboutGameEvent();\r
- break;\r
-\r
- case IDM_Debug:\r
- appData.debugMode = !appData.debugMode;\r
- if (appData.debugMode) {\r
- char dir[MSG_SIZ];\r
- GetCurrentDirectory(MSG_SIZ, dir);\r
- SetCurrentDirectory(installDir);\r
- debugFP = fopen("WinBoard.debug", "w");\r
- SetCurrentDirectory(dir);\r
- setbuf(debugFP, NULL);\r
- } else {\r
- fclose(debugFP);\r
- debugFP = NULL;\r
- }\r
- break;\r
-\r
- case IDM_HELPCONTENTS:\r
- if (!WinHelp (hwnd, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS")) {\r
- MessageBox (GetFocus(),\r
- "Unable to activate help",\r
- szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
- }\r
- break;\r
-\r
- case IDM_HELPSEARCH:\r
- if (!WinHelp(hwnd, "winboard.hlp", HELP_PARTIALKEY, (DWORD)(LPSTR)"")) {\r
- MessageBox (GetFocus(),\r
- "Unable to activate help",\r
- szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
- }\r
- break;\r
-\r
- case IDM_HELPHELP:\r
- if(!WinHelp(hwnd, (LPSTR)NULL, HELP_HELPONHELP, 0)) {\r
- MessageBox (GetFocus(),\r
- "Unable to activate help",\r
- szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
- }\r
- break;\r
-\r
- case IDM_ABOUT:\r
- lpProc = MakeProcInstance((FARPROC)About, hInst);\r
- DialogBox(hInst, \r
- (gameInfo.event && strcmp(gameInfo.event, "Easter Egg Hunt") == 0) ?\r
- "AboutBox2" : "AboutBox", hwnd, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
- break;\r
-\r
- case IDM_DirectCommand1:\r
- AskQuestionEvent("Direct Command",\r
- "Send to chess program:", "", "1");\r
- break;\r
- case IDM_DirectCommand2:\r
- AskQuestionEvent("Direct Command",\r
- "Send to second chess program:", "", "2");\r
- break;\r
-\r
- case EP_WhitePawn:\r
- EditPositionMenuEvent(WhitePawn, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteKnight:\r
- EditPositionMenuEvent(WhiteKnight, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteBishop:\r
- EditPositionMenuEvent(WhiteBishop, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteRook:\r
- EditPositionMenuEvent(WhiteRook, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteQueen:\r
- EditPositionMenuEvent(WhiteQueen, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_WhiteKing:\r
- EditPositionMenuEvent(WhiteKing, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackPawn:\r
- EditPositionMenuEvent(BlackPawn, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackKnight:\r
- EditPositionMenuEvent(BlackKnight, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackBishop:\r
- EditPositionMenuEvent(BlackBishop, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackRook:\r
- EditPositionMenuEvent(BlackRook, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackQueen:\r
- EditPositionMenuEvent(BlackQueen, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_BlackKing:\r
- EditPositionMenuEvent(BlackKing, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_EmptySquare:\r
- EditPositionMenuEvent(EmptySquare, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_ClearBoard:\r
- EditPositionMenuEvent(ClearBoard, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_White:\r
- EditPositionMenuEvent(WhitePlay, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case EP_Black:\r
- EditPositionMenuEvent(BlackPlay, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Pawn:\r
- DropMenuEvent(WhitePawn, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Knight:\r
- DropMenuEvent(WhiteKnight, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Bishop:\r
- DropMenuEvent(WhiteBishop, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Rook:\r
- DropMenuEvent(WhiteRook, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- case DP_Queen:\r
- DropMenuEvent(WhiteQueen, fromX, fromY);\r
- fromX = fromY = -1;\r
- break;\r
-\r
- default:\r
- return (DefWindowProc(hwnd, message, wParam, lParam));\r
- }\r
- break;\r
-\r
- case WM_TIMER:\r
- switch (wParam) {\r
- case CLOCK_TIMER_ID:\r
- KillTimer(hwnd, clockTimerEvent); /* Simulate one-shot timer as in X */\r
- clockTimerEvent = 0;\r
- DecrementClocks(); /* call into back end */\r
- break;\r
- case LOAD_GAME_TIMER_ID:\r
- KillTimer(hwnd, loadGameTimerEvent); /* Simulate one-shot timer as in X*/\r
- loadGameTimerEvent = 0;\r
- AutoPlayGameLoop(); /* call into back end */\r
- break;\r
- case ANALYSIS_TIMER_ID:\r
- if ((gameMode == AnalyzeMode || gameMode == AnalyzeFile) && \r
- appData.periodicUpdates) {\r
- AnalysisPeriodicEvent(0);\r
- } else {\r
- KillTimer(hwnd, analysisTimerEvent);\r
- analysisTimerEvent = 0;\r
- }\r
- break;\r
- case DELAYED_TIMER_ID:\r
- KillTimer(hwnd, delayedTimerEvent);\r
- delayedTimerEvent = 0;\r
- delayedTimerCallback();\r
- break;\r
- }\r
- break;\r
-\r
- case WM_USER_Input:\r
- InputEvent(hwnd, message, wParam, lParam);\r
- break;\r
-\r
- case WM_ENTERSIZEMOVE:\r
- if (hwnd == hwndMain) {\r
- doingSizing = TRUE;\r
- lastSizing = 0;\r
- }\r
- break;\r
-\r
- case WM_SIZING:\r
- if (hwnd == hwndMain) {\r
- lastSizing = wParam;\r
- }\r
- break;\r
-\r
- case WM_EXITSIZEMOVE:\r
- if (hwnd == hwndMain) {\r
- RECT client;\r
- doingSizing = FALSE;\r
- InvalidateRect(hwnd, &boardRect, FALSE);\r
- GetClientRect(hwnd, &client);\r
- ResizeBoard(client.right, client.bottom, lastSizing);\r
- lastSizing = 0;\r
- }\r
- break;\r
-\r
- case WM_DESTROY: /* message: window being destroyed */\r
- PostQuitMessage(0);\r
- break;\r
-\r
- case WM_CLOSE:\r
- if (hwnd == hwndMain) {\r
- ExitEvent(0);\r
- }\r
- break;\r
-\r
- default: /* Passes it on if unprocessed */\r
- return (DefWindowProc(hwnd, message, wParam, lParam));\r
- }\r
- return 0;\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Misc utility routines\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/*\r
- * Decent random number generator, at least not as bad as Windows\r
- * standard rand, which returns a value in the range 0 to 0x7fff.\r
- */\r
-unsigned int randstate;\r
-\r
-int\r
-myrandom(void)\r
-{\r
- randstate = randstate * 1664525 + 1013904223;\r
- return (int) randstate & 0x7fffffff;\r
-}\r
-\r
-void\r
-mysrandom(unsigned int seed)\r
-{\r
- randstate = seed;\r
-}\r
-\r
-\r
-/* \r
- * returns TRUE if user selects a different color, FALSE otherwise \r
- */\r
-\r
-BOOL\r
-ChangeColor(HWND hwnd, COLORREF *which)\r
-{\r
- static BOOL firstTime = TRUE;\r
- static DWORD customColors[16];\r
- CHOOSECOLOR cc;\r
- COLORREF newcolor;\r
- int i;\r
- ColorClass ccl;\r
-\r
- if (firstTime) {\r
- /* Make initial colors in use available as custom colors */\r
- /* Should we put the compiled-in defaults here instead? */\r
- i = 0;\r
- customColors[i++] = lightSquareColor & 0xffffff;\r
- customColors[i++] = darkSquareColor & 0xffffff;\r
- customColors[i++] = whitePieceColor & 0xffffff;\r
- customColors[i++] = blackPieceColor & 0xffffff;\r
- customColors[i++] = highlightSquareColor & 0xffffff;\r
- customColors[i++] = premoveHighlightColor & 0xffffff;\r
-\r
- for (ccl = (ColorClass) 0; ccl < NColorClasses && i < 16; ccl++) {\r
- customColors[i++] = textAttribs[ccl].color;\r
- }\r
- while (i < 16) customColors[i++] = RGB(255, 255, 255);\r
- firstTime = FALSE;\r
- }\r
-\r
- cc.lStructSize = sizeof(cc);\r
- cc.hwndOwner = hwnd;\r
- cc.hInstance = NULL;\r
- cc.rgbResult = (DWORD) (*which & 0xffffff);\r
- cc.lpCustColors = (LPDWORD) customColors;\r
- cc.Flags = CC_RGBINIT|CC_FULLOPEN;\r
-\r
- if (!ChooseColor(&cc)) return FALSE;\r
-\r
- newcolor = (COLORREF) (0x2000000 | cc.rgbResult);\r
- if (newcolor == *which) return FALSE;\r
- *which = newcolor;\r
- return TRUE;\r
-\r
- /*\r
- InitDrawingColors();\r
- InvalidateRect(hwnd, &boardRect, FALSE);\r
- */\r
-}\r
-\r
-BOOLEAN\r
-MyLoadSound(MySound *ms)\r
-{\r
- BOOL ok = FALSE;\r
- struct stat st;\r
- FILE *f;\r
-\r
- if (ms->data) free(ms->data);\r
- ms->data = NULL;\r
-\r
- switch (ms->name[0]) {\r
- case NULLCHAR:\r
- /* Silence */\r
- ok = TRUE;\r
- break;\r
- case '$':\r
- /* System sound from Control Panel. Don't preload here. */\r
- ok = TRUE;\r
- break;\r
- case '!':\r
- if (ms->name[1] == NULLCHAR) {\r
- /* "!" alone = silence */\r
- ok = TRUE;\r
- } else {\r
- /* Builtin wave resource. Error if not found. */\r
- HANDLE h = FindResource(hInst, ms->name + 1, "WAVE");\r
- if (h == NULL) break;\r
- ms->data = (void *)LoadResource(hInst, h);\r
- if (h == NULL) break;\r
- ok = TRUE;\r
- }\r
- break;\r
- default:\r
- /* .wav file. Error if not found. */\r
- f = fopen(ms->name, "rb");\r
- if (f == NULL) break;\r
- if (fstat(fileno(f), &st) < 0) break;\r
- ms->data = malloc(st.st_size);\r
- if (fread(ms->data, st.st_size, 1, f) < 1) break;\r
- fclose(f);\r
- ok = TRUE;\r
- break;\r
- }\r
- if (!ok) {\r
- char buf[MSG_SIZ];\r
- sprintf(buf, "Error loading sound %s", ms->name);\r
- DisplayError(buf, GetLastError());\r
- }\r
- return ok;\r
-}\r
-\r
-BOOLEAN\r
-MyPlaySound(MySound *ms)\r
-{\r
- BOOLEAN ok = FALSE;\r
- switch (ms->name[0]) {\r
- case NULLCHAR:\r
- /* Silence */\r
- ok = TRUE;\r
- break;\r
- case '$':\r
- /* System sound from Control Panel (deprecated feature).\r
- "$" alone or an unset sound name gets default beep (still in use). */\r
- if (ms->name[1]) {\r
- ok = PlaySound(ms->name + 1, NULL, SND_ALIAS|SND_ASYNC);\r
- }\r
- if (!ok) ok = MessageBeep(MB_OK);\r
- break; \r
- case '!':\r
- /* Builtin wave resource, or "!" alone for silence */\r
- if (ms->name[1]) {\r
- if (ms->data == NULL) return FALSE;\r
- ok = PlaySound(ms->data, NULL, SND_MEMORY|SND_ASYNC);\r
- } else {\r
- ok = TRUE;\r
- }\r
- break;\r
- default:\r
- /* .wav file. Error if not found. */\r
- if (ms->data == NULL) return FALSE;\r
- ok = PlaySound(ms->data, NULL, SND_MEMORY|SND_ASYNC);\r
- break;\r
- }\r
- /* Don't print an error: this can happen innocently if the sound driver\r
- is busy; for instance, if another instance of WinBoard is playing\r
- a sound at about the same time. */\r
-#if 0\r
- if (!ok) {\r
- char buf[MSG_SIZ];\r
- sprintf(buf, "Error playing sound %s", ms->name);\r
- DisplayError(buf, GetLastError());\r
- }\r
-#endif\r
- return ok;\r
-}\r
-\r
-\r
-LRESULT CALLBACK\r
-OldOpenFileHook(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- BOOL ok;\r
- OPENFILENAME *ofn;\r
- static UINT *number; /* gross that this is static */\r
-\r
- switch (message) {\r
- case WM_INITDIALOG: /* message: initialize dialog box */\r
- /* Center the dialog over the application window */\r
- ofn = (OPENFILENAME *) lParam;\r
- if (ofn->Flags & OFN_ENABLETEMPLATE) {\r
- number = (UINT *) ofn->lCustData;\r
- SendMessage(GetDlgItem(hDlg, edt2), WM_SETTEXT, 0, (LPARAM) "");\r
- } else {\r
- number = NULL;\r
- }\r
- CenterWindow (hDlg, GetWindow (hDlg, GW_OWNER));\r
- return FALSE; /* Allow for further processing */\r
-\r
- case WM_COMMAND:\r
- if ((LOWORD(wParam) == IDOK) && (number != NULL)) {\r
- *number = GetDlgItemInt(hDlg, OPT_IndexNumberOld, &ok, FALSE);\r
- }\r
- return FALSE; /* Allow for further processing */\r
- }\r
- return FALSE;\r
-}\r
-\r
-UINT APIENTRY\r
-OpenFileHook(HWND hdlg, UINT uiMsg, WPARAM wParam, LPARAM lParam)\r
-{\r
- static UINT *number;\r
- OPENFILENAME *ofname;\r
- OFNOTIFY *ofnot;\r
- switch (uiMsg) {\r
- case WM_INITDIALOG:\r
- ofname = (OPENFILENAME *)lParam;\r
- number = (UINT *)(ofname->lCustData);\r
- break;\r
- case WM_NOTIFY:\r
- ofnot = (OFNOTIFY *)lParam;\r
- if (ofnot->hdr.code == CDN_FILEOK) {\r
- *number = GetDlgItemInt(hdlg, OPT_IndexNumber, NULL, FALSE);\r
- }\r
- break;\r
- }\r
- return 0;\r
-}\r
-\r
-\r
-FILE *\r
-OpenFileDialog(HWND hwnd, BOOL write, char *defName, char *defExt,\r
- char *nameFilt, char *dlgTitle, UINT *number,\r
- char fileTitle[MSG_SIZ], char fileName[MSG_SIZ])\r
-{\r
- OPENFILENAME openFileName;\r
- char buf1[MSG_SIZ];\r
- FILE *f;\r
-\r
- if (fileName == NULL) fileName = buf1;\r
- if (defName == NULL) {\r
- strcpy(fileName, "*.");\r
- strcat(fileName, defExt);\r
- } else {\r
- strcpy(fileName, defName);\r
- }\r
- if (fileTitle) strcpy(fileTitle, "");\r
- if (number) *number = 0;\r
-\r
- openFileName.lStructSize = sizeof(OPENFILENAME);\r
- openFileName.hwndOwner = hwnd;\r
- openFileName.hInstance = (HANDLE) hInst;\r
- openFileName.lpstrFilter = nameFilt;\r
- openFileName.lpstrCustomFilter = (LPSTR) NULL;\r
- openFileName.nMaxCustFilter = 0L;\r
- openFileName.nFilterIndex = 1L;\r
- openFileName.lpstrFile = fileName;\r
- openFileName.nMaxFile = MSG_SIZ;\r
- openFileName.lpstrFileTitle = fileTitle;\r
- openFileName.nMaxFileTitle = fileTitle ? MSG_SIZ : 0;\r
- openFileName.lpstrInitialDir = NULL;\r
- openFileName.lpstrTitle = dlgTitle;\r
- openFileName.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY \r
- | (write ? 0 : OFN_FILEMUSTEXIST) \r
- | (number ? OFN_ENABLETEMPLATE | OFN_ENABLEHOOK: 0)\r
- | (oldDialog ? 0 : OFN_EXPLORER);\r
- openFileName.nFileOffset = 0;\r
- openFileName.nFileExtension = 0;\r
- openFileName.lpstrDefExt = defExt;\r
- openFileName.lCustData = (LONG) number;\r
- openFileName.lpfnHook = oldDialog ?\r
- (LPOFNHOOKPROC) OldOpenFileHook : (LPOFNHOOKPROC) OpenFileHook;\r
- openFileName.lpTemplateName = (LPSTR)(oldDialog ? 1536 : DLG_IndexNumber);\r
-\r
- if (write ? GetSaveFileName(&openFileName) : \r
- GetOpenFileName(&openFileName)) {\r
- /* open the file */\r
- f = fopen(openFileName.lpstrFile, write ? "a" : "rb");\r
- if (f == NULL) {\r
- MessageBox(hwnd, "File open failed", NULL,\r
- MB_OK|MB_ICONEXCLAMATION);\r
- return NULL;\r
- }\r
- } else {\r
- int err = CommDlgExtendedError();\r
- if (err != 0) DisplayError("Internal error in file dialog box", err);\r
- return FALSE;\r
- }\r
- return f;\r
-}\r
-\r
-\r
-\r
-VOID APIENTRY\r
-MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def)\r
-{\r
- HMENU hmenuTrackPopup; /* floating pop-up menu */\r
-\r
- /*\r
- * Get the first pop-up menu in the menu template. This is the\r
- * menu that TrackPopupMenu displays.\r
- */\r
- hmenuTrackPopup = GetSubMenu(hmenu, 0);\r
-\r
- SetMenuDefaultItem(hmenuTrackPopup, def, FALSE);\r
-\r
- /*\r
- * TrackPopup uses screen coordinates, so convert the\r
- * coordinates of the mouse click to screen coordinates.\r
- */\r
- ClientToScreen(hwnd, (LPPOINT) &pt);\r
-\r
- /* Draw and track the floating pop-up menu. */\r
- TrackPopupMenu(hmenuTrackPopup, TPM_CENTERALIGN | TPM_RIGHTBUTTON,\r
- pt.x, pt.y, 0, hwnd, NULL);\r
-\r
- /* Destroy the menu.*/\r
- DestroyMenu(hmenu);\r
-}\r
- \r
-typedef struct {\r
- HWND hDlg, hText;\r
- int sizeX, sizeY, newSizeX, newSizeY;\r
- HDWP hdwp;\r
-} ResizeEditPlusButtonsClosure;\r
-\r
-BOOL CALLBACK\r
-ResizeEditPlusButtonsCallback(HWND hChild, LPARAM lparam)\r
-{\r
- ResizeEditPlusButtonsClosure *cl = (ResizeEditPlusButtonsClosure *)lparam;\r
- RECT rect;\r
- POINT pt;\r
-\r
- if (hChild == cl->hText) return TRUE;\r
- GetWindowRect(hChild, &rect); /* gives screen coords */\r
- pt.x = rect.left + (cl->newSizeX - cl->sizeX)/2;\r
- pt.y = rect.top + cl->newSizeY - cl->sizeY;\r
- ScreenToClient(cl->hDlg, &pt);\r
- cl->hdwp = DeferWindowPos(cl->hdwp, hChild, NULL, \r
- pt.x, pt.y, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);\r
- return TRUE;\r
-}\r
-\r
-/* Resize a dialog that has a (rich) edit field filling most of\r
- the top, with a row of buttons below */\r
-VOID\r
-ResizeEditPlusButtons(HWND hDlg, HWND hText, int sizeX, int sizeY, int newSizeX, int newSizeY)\r
-{\r
- RECT rectText;\r
- int newTextHeight, newTextWidth;\r
- ResizeEditPlusButtonsClosure cl;\r
- \r
- /*if (IsIconic(hDlg)) return;*/\r
- if (newSizeX == sizeX && newSizeY == sizeY) return;\r
- \r
- cl.hdwp = BeginDeferWindowPos(8);\r
-\r
- GetWindowRect(hText, &rectText); /* gives screen coords */\r
- newTextWidth = rectText.right - rectText.left + newSizeX - sizeX;\r
- newTextHeight = rectText.bottom - rectText.top + newSizeY - sizeY;\r
- if (newTextHeight < 0) {\r
- newSizeY += -newTextHeight;\r
- newTextHeight = 0;\r
- }\r
- cl.hdwp = DeferWindowPos(cl.hdwp, hText, NULL, 0, 0, \r
- newTextWidth, newTextHeight, SWP_NOZORDER|SWP_NOMOVE);\r
-\r
- cl.hDlg = hDlg;\r
- cl.hText = hText;\r
- cl.sizeX = sizeX;\r
- cl.sizeY = sizeY;\r
- cl.newSizeX = newSizeX;\r
- cl.newSizeY = newSizeY;\r
- EnumChildWindows(hDlg, ResizeEditPlusButtonsCallback, (LPARAM)&cl);\r
-\r
- EndDeferWindowPos(cl.hdwp);\r
-}\r
-\r
-/* Center one window over another */\r
-BOOL CenterWindow (HWND hwndChild, HWND hwndParent)\r
-{\r
- RECT rChild, rParent;\r
- int wChild, hChild, wParent, hParent;\r
- int wScreen, hScreen, xNew, yNew;\r
- HDC hdc;\r
-\r
- /* Get the Height and Width of the child window */\r
- GetWindowRect (hwndChild, &rChild);\r
- wChild = rChild.right - rChild.left;\r
- hChild = rChild.bottom - rChild.top;\r
-\r
- /* Get the Height and Width of the parent window */\r
- GetWindowRect (hwndParent, &rParent);\r
- wParent = rParent.right - rParent.left;\r
- hParent = rParent.bottom - rParent.top;\r
-\r
- /* Get the display limits */\r
- hdc = GetDC (hwndChild);\r
- wScreen = GetDeviceCaps (hdc, HORZRES);\r
- hScreen = GetDeviceCaps (hdc, VERTRES);\r
- ReleaseDC(hwndChild, hdc);\r
-\r
- /* Calculate new X position, then adjust for screen */\r
- xNew = rParent.left + ((wParent - wChild) /2);\r
- if (xNew < 0) {\r
- xNew = 0;\r
- } else if ((xNew+wChild) > wScreen) {\r
- xNew = wScreen - wChild;\r
- }\r
-\r
- /* Calculate new Y position, then adjust for screen */\r
- yNew = rParent.top + ((hParent - hChild) /2);\r
- if (yNew < 0) {\r
- yNew = 0;\r
- } else if ((yNew+hChild) > hScreen) {\r
- yNew = hScreen - hChild;\r
- }\r
-\r
- /* Set it, and return */\r
- return SetWindowPos (hwndChild, NULL,\r
- xNew, yNew, 0, 0, SWP_NOSIZE | SWP_NOZORDER);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Startup Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-void\r
-InitComboStrings(HANDLE hwndCombo, char **cd)\r
-{\r
- SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
-\r
- while (*cd != NULL) {\r
- SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) *cd);\r
- cd++;\r
- }\r
-}\r
-\r
-void\r
-InitComboStringsFromOption(HANDLE hwndCombo, char *str)\r
-{\r
- char buf1[ARG_MAX];\r
- int len;\r
-\r
- if (str[0] == '@') {\r
- FILE* f = fopen(str + 1, "r");\r
- if (f == NULL) {\r
- DisplayFatalError(str + 1, errno, 2);\r
- return;\r
- }\r
- len = fread(buf1, 1, sizeof(buf1)-1, f);\r
- fclose(f);\r
- buf1[len] = NULLCHAR;\r
- str = buf1;\r
- }\r
-\r
- SendMessage(hwndCombo, CB_RESETCONTENT, 0, 0);\r
-\r
- for (;;) {\r
- char buf[MSG_SIZ];\r
- char *end = strchr(str, '\n');\r
- if (end == NULL) return;\r
- memcpy(buf, str, end - str);\r
- buf[end - str] = NULLCHAR;\r
- SendMessage(hwndCombo, CB_ADDSTRING, 0, (LPARAM) buf);\r
- str = end + 1;\r
- }\r
-}\r
-\r
-void\r
-SetStartupDialogEnables(HWND hDlg)\r
-{\r
- EnableWindow(GetDlgItem(hDlg, OPT_ChessEngineName),\r
- IsDlgButtonChecked(hDlg, OPT_ChessEngine) ||\r
- appData.zippyPlay && IsDlgButtonChecked(hDlg, OPT_ChessServer));\r
- EnableWindow(GetDlgItem(hDlg, OPT_SecondChessEngineName),\r
- IsDlgButtonChecked(hDlg, OPT_ChessEngine));\r
- EnableWindow(GetDlgItem(hDlg, OPT_ChessServerName),\r
- IsDlgButtonChecked(hDlg, OPT_ChessServer));\r
- EnableWindow(GetDlgItem(hDlg, OPT_AdditionalOptions),\r
- IsDlgButtonChecked(hDlg, OPT_AnyAdditional));\r
- EnableWindow(GetDlgItem(hDlg, IDOK),\r
- IsDlgButtonChecked(hDlg, OPT_ChessEngine) ||\r
- IsDlgButtonChecked(hDlg, OPT_ChessServer) ||\r
- IsDlgButtonChecked(hDlg, OPT_View));\r
-}\r
-\r
-char *\r
-QuoteForFilename(char *filename)\r
-{\r
- int dquote, space;\r
- dquote = strchr(filename, '"') != NULL;\r
- space = strchr(filename, ' ') != NULL;\r
- if (dquote || space) {\r
- if (dquote) {\r
- return "'";\r
- } else {\r
- return "\"";\r
- }\r
- } else {\r
- return "";\r
- }\r
-}\r
-\r
-VOID\r
-InitEngineBox(HWND hDlg, HWND hwndCombo, char* nthcp, char* nthd, char* nthdir, char *nthnames)\r
-{\r
- char buf[MSG_SIZ];\r
- char *q;\r
-\r
- InitComboStringsFromOption(hwndCombo, nthnames);\r
- q = QuoteForFilename(nthcp);\r
- sprintf(buf, "%s%s%s", q, nthcp, q);\r
- if (*nthdir != NULLCHAR) {\r
- q = QuoteForFilename(nthdir);\r
- sprintf(buf + strlen(buf), " /%s=%s%s%s", nthd, q, nthdir, q);\r
- }\r
- if (*nthcp == NULLCHAR) {\r
- SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
- } else 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
-\r
-LRESULT CALLBACK\r
-StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- char buf[MSG_SIZ];\r
- HANDLE hwndCombo;\r
- char *p;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- /* Center the dialog */\r
- CenterWindow (hDlg, GetDesktopWindow());\r
- /* Initialize the dialog items */\r
- InitEngineBox(hDlg, GetDlgItem(hDlg, OPT_ChessEngineName),\r
- appData.firstChessProgram, "fd", appData.firstDirectory,\r
- firstChessProgramNames);\r
- InitEngineBox(hDlg, GetDlgItem(hDlg, OPT_SecondChessEngineName),\r
- appData.secondChessProgram, "sd", appData.secondDirectory,\r
- secondChessProgramNames);\r
- hwndCombo = GetDlgItem(hDlg, OPT_ChessServerName);\r
- InitComboStringsFromOption(hwndCombo, icsNames); \r
- sprintf(buf, "%s /icsport=%s", appData.icsHost, appData.icsPort);\r
- if (*appData.icsHelper != NULLCHAR) {\r
- char *q = QuoteForFilename(appData.icsHelper);\r
- sprintf(buf + strlen(buf), " /icshelper=%s%s%s", q, appData.icsHelper, q);\r
- }\r
- if (*appData.icsHost == NULLCHAR) {\r
- SendMessage(hwndCombo, CB_SETCURSEL, (WPARAM) 0, (LPARAM) 0);\r
- /*SendMessage(hwndCombo, CB_SHOWDROPDOWN, (WPARAM) TRUE, (LPARAM) 0); !!too soon */\r
- } else 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
- if (chessProgram) {\r
- CheckDlgButton(hDlg, OPT_ChessEngine, BST_CHECKED);\r
- } else if (appData.icsActive) {\r
- CheckDlgButton(hDlg, OPT_ChessServer, BST_CHECKED);\r
- } else if (appData.noChessProgram) {\r
- CheckDlgButton(hDlg, OPT_View, BST_CHECKED);\r
- }\r
- SetStartupDialogEnables(hDlg);\r
- return TRUE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- if (IsDlgButtonChecked(hDlg, OPT_ChessEngine)) {\r
- strcpy(buf, "/fcp=");\r
- GetDlgItemText(hDlg, OPT_ChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf));\r
- p = buf;\r
- ParseArgs(StringGet, &p);\r
- strcpy(buf, "/scp=");\r
- GetDlgItemText(hDlg, OPT_SecondChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf));\r
- p = buf;\r
- ParseArgs(StringGet, &p);\r
- appData.noChessProgram = FALSE;\r
- appData.icsActive = FALSE;\r
- } else if (IsDlgButtonChecked(hDlg, OPT_ChessServer)) {\r
- strcpy(buf, "/ics /icshost=");\r
- GetDlgItemText(hDlg, OPT_ChessServerName, buf + strlen(buf), sizeof(buf) - strlen(buf));\r
- p = buf;\r
- ParseArgs(StringGet, &p);\r
- if (appData.zippyPlay) {\r
- strcpy(buf, "/fcp=");\r
- GetDlgItemText(hDlg, OPT_ChessEngineName, buf + strlen(buf), sizeof(buf) - strlen(buf));\r
- p = buf;\r
- ParseArgs(StringGet, &p);\r
- }\r
- } else if (IsDlgButtonChecked(hDlg, OPT_View)) {\r
- appData.noChessProgram = TRUE;\r
- appData.icsActive = FALSE;\r
- } else {\r
- MessageBox(hDlg, "Choose an option, or cancel to exit",\r
- "Option Error", MB_OK|MB_ICONEXCLAMATION);\r
- return TRUE;\r
- }\r
- if (IsDlgButtonChecked(hDlg, OPT_AnyAdditional)) {\r
- GetDlgItemText(hDlg, OPT_AdditionalOptions, buf, sizeof(buf));\r
- p = buf;\r
- ParseArgs(StringGet, &p);\r
- }\r
- EndDialog(hDlg, TRUE);\r
- return TRUE;\r
-\r
- case IDCANCEL:\r
- ExitEvent(0);\r
- return TRUE;\r
-\r
- case IDM_HELPCONTENTS:\r
- if (!WinHelp (hDlg, "winboard.hlp", HELP_KEY,(DWORD)(LPSTR)"CONTENTS")) {\r
- MessageBox (GetFocus(),\r
- "Unable to activate help",\r
- szAppName, MB_SYSTEMMODAL|MB_OK|MB_ICONHAND);\r
- }\r
- break;\r
-\r
- default:\r
- SetStartupDialogEnables(hDlg);\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * About box dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-/* Process messages for "About" dialog box */\r
-LRESULT CALLBACK\r
-About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\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
- SetDlgItemText(hDlg, ABOUTBOX_Version, programVersion);\r
- return (TRUE);\r
-\r
- case WM_COMMAND: /* message: received a command */\r
- if (LOWORD(wParam) == IDOK /* "OK" box selected? */\r
- || LOWORD(wParam) == IDCANCEL) { /* System menu close command? */\r
- EndDialog(hDlg, TRUE); /* Exit the dialog */\r
- return (TRUE);\r
- }\r
- break;\r
- }\r
- return (FALSE);\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Comment Dialog functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-LRESULT CALLBACK\r
-CommentDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- static HANDLE hwndText = NULL;\r
- int len, newSizeX, newSizeY, flags;\r
- static int sizeX, sizeY;\r
- char *str;\r
- RECT rect;\r
- MINMAXINFO *mmi;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG: /* message: initialize dialog box */\r
- /* Initialize the dialog items */\r
- hwndText = GetDlgItem(hDlg, OPT_CommentText);\r
- SetDlgItemText(hDlg, OPT_CommentText, commentText);\r
- EnableWindow(GetDlgItem(hDlg, OPT_CancelComment), editComment);\r
- EnableWindow(GetDlgItem(hDlg, OPT_ClearComment), editComment);\r
- EnableWindow(GetDlgItem(hDlg, OPT_EditComment), !editComment);\r
- SendMessage(hwndText, EM_SETREADONLY, !editComment, 0);\r
- SetWindowText(hDlg, commentTitle);\r
- if (editComment) {\r
- SetFocus(hwndText);\r
- } else {\r
- SetFocus(GetDlgItem(hDlg, IDOK));\r
- }\r
- SendMessage(GetDlgItem(hDlg, OPT_CommentText),\r
- WM_SETFONT, (WPARAM)font[boardSize][COMMENT_FONT]->hf,\r
- MAKELPARAM(FALSE, 0));\r
- /* Size and position the dialog */\r
- if (!commentDialog) {\r
- commentDialog = hDlg;\r
- flags = SWP_NOZORDER;\r
- GetClientRect(hDlg, &rect);\r
- sizeX = rect.right;\r
- sizeY = rect.bottom;\r
- if (commentX != CW_USEDEFAULT && commentY != CW_USEDEFAULT &&\r
- commentW != CW_USEDEFAULT && commentH != CW_USEDEFAULT) {\r
- WINDOWPLACEMENT wp;\r
- EnsureOnScreen(&commentX, &commentY);\r
- wp.length = sizeof(WINDOWPLACEMENT);\r
- wp.flags = 0;\r
- wp.showCmd = SW_SHOW;\r
- wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
- wp.rcNormalPosition.left = commentX;\r
- wp.rcNormalPosition.right = commentX + commentW;\r
- wp.rcNormalPosition.top = commentY;\r
- wp.rcNormalPosition.bottom = commentY + commentH;\r
- SetWindowPlacement(hDlg, &wp);\r
-\r
- GetClientRect(hDlg, &rect);\r
- newSizeX = rect.right;\r
- newSizeY = rect.bottom;\r
- ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY,\r
- newSizeX, newSizeY);\r
- sizeX = newSizeX;\r
- sizeY = newSizeY;\r
- }\r
- }\r
- return FALSE;\r
-\r
- case WM_COMMAND: /* message: received a command */\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- if (editComment) {\r
- char *p, *q;\r
- /* Read changed options from the dialog box */\r
- hwndText = GetDlgItem(hDlg, OPT_CommentText);\r
- len = GetWindowTextLength(hwndText);\r
- str = (char *) malloc(len + 1);\r
- GetWindowText(hwndText, str, len + 1);\r
- p = q = str;\r
- while (*q) {\r
- if (*q == '\r')\r
- q++;\r
- else\r
- *p++ = *q++;\r
- }\r
- *p = NULLCHAR;\r
- ReplaceComment(commentIndex, str);\r
- free(str);\r
- }\r
- CommentPopDown();\r
- return TRUE;\r
-\r
- case IDCANCEL:\r
- case OPT_CancelComment:\r
- CommentPopDown();\r
- return TRUE;\r
-\r
- case OPT_ClearComment:\r
- SetDlgItemText(hDlg, OPT_CommentText, "");\r
- break;\r
-\r
- case OPT_EditComment:\r
- EditCommentEvent();\r
- return TRUE;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
-\r
- case WM_SIZE:\r
- newSizeX = LOWORD(lParam);\r
- newSizeY = HIWORD(lParam);\r
- ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, newSizeX, newSizeY);\r
- sizeX = newSizeX;\r
- sizeY = newSizeY;\r
- break;\r
-\r
- case WM_GETMINMAXINFO:\r
- /* Prevent resizing window too small */\r
- mmi = (MINMAXINFO *) lParam;\r
- mmi->ptMinTrackSize.x = 100;\r
- mmi->ptMinTrackSize.y = 100;\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-EitherCommentPopUp(int index, char *title, char *str, BOOLEAN edit)\r
-{\r
- FARPROC lpProc;\r
- char *p, *q;\r
-\r
- CheckMenuItem(GetMenu(hwndMain), IDM_EditComment, edit ? MF_CHECKED : MF_UNCHECKED);\r
-\r
- if (str == NULL) str = "";\r
- p = (char *) malloc(2 * strlen(str) + 2);\r
- q = p;\r
- while (*str) {\r
- if (*str == '\n') *q++ = '\r';\r
- *q++ = *str++;\r
- }\r
- *q = NULLCHAR;\r
- if (commentText != NULL) free(commentText);\r
-\r
- commentIndex = index;\r
- commentTitle = title;\r
- commentText = p;\r
- editComment = edit;\r
-\r
- if (commentDialog) {\r
- SendMessage(commentDialog, WM_INITDIALOG, 0, 0);\r
- if (!commentDialogUp) ShowWindow(commentDialog, SW_SHOW);\r
- } else {\r
- lpProc = MakeProcInstance((FARPROC)CommentDialog, hInst);\r
- CreateDialog(hInst, MAKEINTRESOURCE(DLG_EditComment),\r
- hwndMain, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
- }\r
- commentDialogUp = TRUE;\r
-}\r
-\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Type-in move dialog functions\r
- * \r
-\*---------------------------------------------------------------------------*/\r
-\r
-LRESULT CALLBACK\r
-TypeInMoveDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- char move[MSG_SIZ];\r
- HWND hInput;\r
- ChessMove moveType;\r
- int fromX, fromY, toX, toY;\r
- char promoChar;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- move[0] = (char) lParam;\r
- move[1] = NULLCHAR;\r
- CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
- hInput = GetDlgItem(hDlg, OPT_Move);\r
- SetWindowText(hInput, move);\r
- SetFocus(hInput);\r
- SendMessage(hInput, EM_SETSEL, (WPARAM)9999, (LPARAM)9999);\r
- return FALSE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- if (gameMode != EditGame && currentMove != forwardMostMove && \r
- gameMode != Training) {\r
- DisplayMoveError("Displayed move is not current");\r
- } else {\r
- GetDlgItemText(hDlg, OPT_Move, move, sizeof(move));\r
- if (ParseOneMove(move, gameMode == EditPosition ? blackPlaysFirst : currentMove, \r
- &moveType, &fromX, &fromY, &toX, &toY, &promoChar)) {\r
- if (gameMode != Training)\r
- forwardMostMove = currentMove;\r
- UserMoveEvent(fromX, fromY, toX, toY, promoChar); \r
- } else {\r
- DisplayMoveError("Could not parse move");\r
- }\r
- }\r
- EndDialog(hDlg, TRUE);\r
- return TRUE;\r
- case IDCANCEL:\r
- EndDialog(hDlg, FALSE);\r
- return TRUE;\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-PopUpMoveDialog(char firstchar)\r
-{\r
- FARPROC lpProc;\r
- \r
- if ((gameMode == BeginningOfGame && !appData.icsActive) || \r
- gameMode == MachinePlaysWhite || gameMode == MachinePlaysBlack ||\r
- gameMode == AnalyzeMode || gameMode == EditGame || \r
- gameMode == EditPosition || gameMode == IcsExamining ||\r
- gameMode == IcsPlayingWhite || gameMode == IcsPlayingBlack ||\r
- gameMode == Training) {\r
- lpProc = MakeProcInstance((FARPROC)TypeInMoveDialog, hInst);\r
- DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_TypeInMove),\r
- hwndMain, (DLGPROC)lpProc, (LPARAM)firstchar);\r
- FreeProcInstance(lpProc);\r
- }\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Error dialogs\r
- * \r
-\*---------------------------------------------------------------------------*/\r
-\r
-/* Nonmodal error box */\r
-LRESULT CALLBACK ErrorDialog(HWND hDlg, UINT message,\r
- WPARAM wParam, LPARAM lParam);\r
-\r
-VOID\r
-ErrorPopUp(char *title, char *content)\r
-{\r
- FARPROC lpProc;\r
- char *p, *q;\r
- BOOLEAN modal = hwndMain == NULL;\r
-\r
- p = content;\r
- q = errorMessage;\r
- while (*p) {\r
- if (*p == '\n') {\r
- if (modal) {\r
- *q++ = ' ';\r
- p++;\r
- } else {\r
- *q++ = '\r';\r
- *q++ = *p++;\r
- }\r
- } else {\r
- *q++ = *p++;\r
- }\r
- }\r
- *q = NULLCHAR;\r
- strncpy(errorTitle, title, sizeof(errorTitle));\r
- errorTitle[sizeof(errorTitle) - 1] = '\0';\r
- \r
- if (modal) {\r
- MessageBox(NULL, errorMessage, errorTitle, MB_OK|MB_ICONEXCLAMATION);\r
- } else {\r
- lpProc = MakeProcInstance((FARPROC)ErrorDialog, hInst);\r
- CreateDialog(hInst, MAKEINTRESOURCE(DLG_Error),\r
- hwndMain, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
- }\r
-}\r
-\r
-VOID\r
-ErrorPopDown()\r
-{\r
- if (!appData.popupMoveErrors && moveErrorMessageUp) DisplayMessage("", "");\r
- if (errorDialog == NULL) return;\r
- DestroyWindow(errorDialog);\r
- errorDialog = NULL;\r
-}\r
-\r
-LRESULT CALLBACK\r
-ErrorDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- HANDLE hwndText;\r
- RECT rChild;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- GetWindowRect(hDlg, &rChild);\r
- SetWindowPos(hDlg, NULL, rChild.left,\r
- rChild.top + boardRect.top - (rChild.bottom - rChild.top), \r
- 0, 0, SWP_NOZORDER|SWP_NOSIZE);\r
- errorDialog = hDlg;\r
- SetWindowText(hDlg, errorTitle);\r
- hwndText = GetDlgItem(hDlg, OPT_ErrorText);\r
- SetDlgItemText(hDlg, OPT_ErrorText, errorMessage);\r
- return FALSE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- case IDCANCEL:\r
- if (errorDialog == hDlg) errorDialog = NULL;\r
- DestroyWindow(hDlg);\r
- return TRUE;\r
-\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Ics Interaction console functions\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-#define HISTORY_SIZE 64\r
-static char *history[HISTORY_SIZE];\r
-int histIn = 0, histP = 0;\r
-\r
-VOID\r
-SaveInHistory(char *cmd)\r
-{\r
- if (history[histIn] != NULL) {\r
- free(history[histIn]);\r
- history[histIn] = NULL;\r
- }\r
- if (*cmd == NULLCHAR) return;\r
- history[histIn] = StrSave(cmd);\r
- histIn = (histIn + 1) % HISTORY_SIZE;\r
- if (history[histIn] != NULL) {\r
- free(history[histIn]);\r
- history[histIn] = NULL;\r
- }\r
- histP = histIn;\r
-}\r
-\r
-char *\r
-PrevInHistory(char *cmd)\r
-{\r
- int newhp;\r
- if (histP == histIn) {\r
- if (history[histIn] != NULL) free(history[histIn]);\r
- history[histIn] = StrSave(cmd);\r
- }\r
- newhp = (histP - 1 + HISTORY_SIZE) % HISTORY_SIZE;\r
- if (newhp == histIn || history[newhp] == NULL) return NULL;\r
- histP = newhp;\r
- return history[histP];\r
-}\r
-\r
-char *\r
-NextInHistory()\r
-{\r
- if (histP == histIn) return NULL;\r
- histP = (histP + 1) % HISTORY_SIZE;\r
- return history[histP];\r
-}\r
-\r
-typedef struct {\r
- char *item;\r
- char *command;\r
- BOOLEAN getname;\r
- BOOLEAN immediate;\r
-} IcsTextMenuEntry;\r
-#define ICS_TEXT_MENU_SIZE (IDM_CommandXLast - IDM_CommandX + 1)\r
-IcsTextMenuEntry icsTextMenuEntry[ICS_TEXT_MENU_SIZE];\r
-\r
-void\r
-ParseIcsTextMenu(char *icsTextMenuString)\r
-{\r
- int flags = 0;\r
- IcsTextMenuEntry *e = icsTextMenuEntry;\r
- char *p = icsTextMenuString;\r
- while (e->item != NULL && e < icsTextMenuEntry + ICS_TEXT_MENU_SIZE) {\r
- free(e->item);\r
- e->item = NULL;\r
- if (e->command != NULL) {\r
- free(e->command);\r
- e->command = NULL;\r
- }\r
- e++;\r
- }\r
- e = icsTextMenuEntry;\r
- while (*p && e < icsTextMenuEntry + ICS_TEXT_MENU_SIZE) {\r
- if (*p == ';' || *p == '\n') {\r
- e->item = strdup("-");\r
- e->command = NULL;\r
- p++;\r
- } else if (*p == '-') {\r
- e->item = strdup("-");\r
- e->command = NULL;\r
- p++;\r
- if (*p) p++;\r
- } else {\r
- char *q, *r, *s, *t;\r
- char c;\r
- q = strchr(p, ',');\r
- if (q == NULL) break;\r
- *q = NULLCHAR;\r
- r = strchr(q + 1, ',');\r
- if (r == NULL) break;\r
- *r = NULLCHAR;\r
- s = strchr(r + 1, ',');\r
- if (s == NULL) break;\r
- *s = NULLCHAR;\r
- c = ';';\r
- t = strchr(s + 1, c);\r
- if (t == NULL) {\r
- c = '\n';\r
- t = strchr(s + 1, c);\r
- }\r
- if (t != NULL) *t = NULLCHAR;\r
- e->item = strdup(p);\r
- e->command = strdup(q + 1);\r
- e->getname = *(r + 1) != '0';\r
- e->immediate = *(s + 1) != '0';\r
- *q = ',';\r
- *r = ',';\r
- *s = ',';\r
- if (t == NULL) break;\r
- *t = c;\r
- p = t + 1;\r
- }\r
- e++;\r
- } \r
-}\r
-\r
-HMENU\r
-LoadIcsTextMenu(IcsTextMenuEntry *e)\r
-{\r
- HMENU hmenu, h;\r
- int i = 0;\r
- hmenu = LoadMenu(hInst, "TextMenu");\r
- h = GetSubMenu(hmenu, 0);\r
- while (e->item) {\r
- if (strcmp(e->item, "-") == 0) {\r
- AppendMenu(h, MF_SEPARATOR, 0, 0);\r
- } else {\r
- if (e->item[0] == '|') {\r
- AppendMenu(h, MF_STRING|MF_MENUBARBREAK,\r
- IDM_CommandX + i, &e->item[1]);\r
- } else {\r
- AppendMenu(h, MF_STRING, IDM_CommandX + i, e->item);\r
- }\r
- }\r
- e++;\r
- i++;\r
- } \r
- return hmenu;\r
-}\r
-\r
-WNDPROC consoleTextWindowProc;\r
-\r
-void\r
-CommandX(HWND hwnd, char *command, BOOLEAN getname, BOOLEAN immediate)\r
-{\r
- char buf[MSG_SIZ], name[MSG_SIZ];\r
- HWND hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- CHARRANGE sel;\r
-\r
- if (!getname) {\r
- SetWindowText(hInput, command);\r
- if (immediate) {\r
- SendMessage(hInput, WM_CHAR, '\r', 0);\r
- } else {\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hInput, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SetFocus(hInput);\r
- }\r
- return;\r
- } \r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- /* Expand to surrounding word */\r
- TEXTRANGE tr;\r
- do {\r
- tr.chrg.cpMax = sel.cpMin;\r
- tr.chrg.cpMin = --sel.cpMin;\r
- if (sel.cpMin < 0) break;\r
- tr.lpstrText = name;\r
- SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM) &tr);\r
- } while (isalpha(name[0]) || isdigit(name[0]) || name[0] == '-');\r
- sel.cpMin++;\r
-\r
- do {\r
- tr.chrg.cpMin = sel.cpMax;\r
- tr.chrg.cpMax = ++sel.cpMax;\r
- tr.lpstrText = name;\r
- if (SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM) &tr) < 1) break;\r
- } while (isalpha(name[0]) || isdigit(name[0]) || name[0] == '-');\r
- sel.cpMax--;\r
-\r
- if (sel.cpMax == sel.cpMin || sel.cpMax - sel.cpMin > MSG_SIZ/2) {\r
- MessageBeep(MB_ICONEXCLAMATION);\r
- return;\r
- }\r
- tr.chrg = sel;\r
- tr.lpstrText = name;\r
- SendMessage(hwnd, EM_GETTEXTRANGE, 0, (LPARAM) &tr);\r
- } else {\r
- if (sel.cpMax - sel.cpMin > MSG_SIZ/2) {\r
- MessageBeep(MB_ICONEXCLAMATION);\r
- return;\r
- }\r
- SendMessage(hwnd, EM_GETSELTEXT, 0, (LPARAM) name);\r
- }\r
- if (immediate) {\r
- sprintf(buf, "%s %s", command, name);\r
- SetWindowText(hInput, buf);\r
- SendMessage(hInput, WM_CHAR, '\r', 0);\r
- } else {\r
- sprintf(buf, "%s %s ", command, name); /* trailing space */\r
- SetWindowText(hInput, buf);\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hInput, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SetFocus(hInput);\r
- }\r
-}\r
-\r
-LRESULT CALLBACK \r
-ConsoleTextSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- HWND hInput;\r
- CHARRANGE sel;\r
-\r
- switch (message) {\r
- case WM_KEYDOWN:\r
- if (!(GetKeyState(VK_CONTROL) & ~1)) break;\r
- switch (wParam) {\r
- case VK_PRIOR:\r
- SendMessage(hwnd, EM_LINESCROLL, 0, -999999);\r
- return 0;\r
- case VK_NEXT:\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SendMessage(hwnd, EM_SCROLLCARET, 0, 0);\r
- return 0;\r
- }\r
- break;\r
- case WM_CHAR:\r
- if (wParam == '\t') {\r
- if (GetKeyState(VK_SHIFT) < 0) {\r
- /* shifted */\r
- if (IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE);\r
- if (buttonDesc[0].hwnd) {\r
- SetFocus(buttonDesc[0].hwnd);\r
- } else {\r
- SetFocus(hwndMain);\r
- }\r
- } else {\r
- /* unshifted */\r
- SetFocus(GetDlgItem(hwndConsole, OPT_ConsoleInput));\r
- }\r
- } else {\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- SetFocus(hInput);\r
- SendMessage(hInput, message, wParam, lParam);\r
- }\r
- return 0;\r
- case WM_PASTE:\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- SetFocus(hInput);\r
- return SendMessage(hInput, message, wParam, lParam);\r
- case WM_MBUTTONDOWN:\r
- return SendMessage(hwnd, WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
- case WM_RBUTTONDOWN:\r
- if (!(GetKeyState(VK_SHIFT) & ~1)) {\r
- /* Move selection here if it was empty */\r
- POINT pt;\r
- pt.x = LOWORD(lParam);\r
- pt.y = HIWORD(lParam);\r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- sel.cpMin = SendMessage(hwnd, EM_CHARFROMPOS, 0, (LPARAM)&pt); /*doc is wrong*/\r
- sel.cpMax = sel.cpMin;\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- }\r
- SendMessage(hwnd, EM_HIDESELECTION, FALSE, FALSE);\r
- }\r
- return 0;\r
- case WM_RBUTTONUP:\r
- if (GetKeyState(VK_SHIFT) & ~1) {\r
- SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
- WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
- } else {\r
- POINT pt;\r
- HMENU hmenu = LoadIcsTextMenu(icsTextMenuEntry);\r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- EnableMenuItem(hmenu, IDM_Copy, MF_BYCOMMAND|MF_GRAYED);\r
- EnableMenuItem(hmenu, IDM_QuickPaste, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
- if (!IsClipboardFormatAvailable(CF_TEXT)) {\r
- EnableMenuItem(hmenu, IDM_Paste, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
- pt.x = LOWORD(lParam);\r
- pt.y = HIWORD(lParam);\r
- MenuPopup(hwnd, pt, hmenu, -1);\r
- }\r
- return 0;\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDM_QuickPaste:\r
- {\r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- MessageBeep(MB_ICONEXCLAMATION);\r
- return 0;\r
- }\r
- SendMessage(hwnd, WM_COPY, 0, 0);\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- SendMessage(hInput, WM_PASTE, 0, 0);\r
- SetFocus(hInput);\r
- return 0;\r
- }\r
- case IDM_Cut:\r
- SendMessage(hwnd, WM_CUT, 0, 0);\r
- return 0;\r
- case IDM_Paste:\r
- SendMessage(hwnd, WM_PASTE, 0, 0);\r
- return 0;\r
- case IDM_Copy:\r
- SendMessage(hwnd, WM_COPY, 0, 0);\r
- return 0;\r
- default:\r
- {\r
- int i = LOWORD(wParam) - IDM_CommandX;\r
- if (i >= 0 && i < ICS_TEXT_MENU_SIZE &&\r
- icsTextMenuEntry[i].command != NULL) {\r
- CommandX(hwnd, icsTextMenuEntry[i].command,\r
- icsTextMenuEntry[i].getname,\r
- icsTextMenuEntry[i].immediate);\r
- return 0;\r
- }\r
- }\r
- break;\r
- }\r
- break;\r
- }\r
- return (*consoleTextWindowProc)(hwnd, message, wParam, lParam);\r
-}\r
-\r
-WNDPROC consoleInputWindowProc;\r
-\r
-LRESULT CALLBACK\r
-ConsoleInputSubclass(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- char buf[MSG_SIZ];\r
- char *p;\r
- static BOOL sendNextChar = FALSE;\r
- static BOOL quoteNextChar = FALSE;\r
- InputSource *is = consoleInputSource;\r
- CHARFORMAT cf;\r
- CHARRANGE sel;\r
-\r
- switch (message) {\r
- case WM_CHAR:\r
- if (!appData.localLineEditing || sendNextChar) {\r
- is->buf[0] = (CHAR) wParam;\r
- is->count = 1;\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
- sendNextChar = FALSE;\r
- return 0;\r
- }\r
- if (quoteNextChar) {\r
- buf[0] = (char) wParam;\r
- buf[1] = NULLCHAR;\r
- SendMessage(hwnd, EM_REPLACESEL, TRUE, (LPARAM) buf);\r
- quoteNextChar = FALSE;\r
- return 0;\r
- }\r
- switch (wParam) {\r
- case '\r': /* Enter key */\r
- is->count = GetWindowText(hwnd, is->buf, INPUT_SOURCE_BUF_SIZE-1); \r
- if (consoleEcho) SaveInHistory(is->buf);\r
- is->buf[is->count++] = '\n';\r
- is->buf[is->count] = NULLCHAR;\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
- if (consoleEcho) {\r
- ConsoleOutput(is->buf, is->count, TRUE);\r
- } else if (appData.localLineEditing) {\r
- ConsoleOutput("\n", 1, TRUE);\r
- }\r
- /* fall thru */\r
- case '\033': /* Escape key */\r
- SetWindowText(hwnd, "");\r
- cf.cbSize = sizeof(CHARFORMAT);\r
- cf.dwMask = CFM_COLOR|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT;\r
- if (consoleEcho) {\r
- cf.crTextColor = textAttribs[ColorNormal].color;\r
- } else {\r
- cf.crTextColor = COLOR_ECHOOFF;\r
- }\r
- cf.dwEffects = textAttribs[ColorNormal].effects;\r
- SendMessage(hwnd, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
- return 0;\r
- case '\t': /* Tab key */\r
- if (GetKeyState(VK_SHIFT) < 0) {\r
- /* shifted */\r
- SetFocus(GetDlgItem(hwndConsole, OPT_ConsoleText));\r
- } else {\r
- /* unshifted */\r
- if (IsIconic(hwndMain)) ShowWindow(hwndMain, SW_RESTORE);\r
- if (buttonDesc[0].hwnd) {\r
- SetFocus(buttonDesc[0].hwnd);\r
- } else {\r
- SetFocus(hwndMain);\r
- }\r
- }\r
- return 0;\r
- case '\023': /* Ctrl+S */\r
- sendNextChar = TRUE;\r
- return 0;\r
- case '\021': /* Ctrl+Q */\r
- quoteNextChar = TRUE;\r
- return 0;\r
- default:\r
- break;\r
- }\r
- break;\r
- case WM_KEYDOWN:\r
- switch (wParam) {\r
- case VK_UP:\r
- GetWindowText(hwnd, buf, MSG_SIZ);\r
- p = PrevInHistory(buf);\r
- if (p != NULL) {\r
- SetWindowText(hwnd, p);\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- return 0;\r
- }\r
- break;\r
- case VK_DOWN:\r
- p = NextInHistory();\r
- if (p != NULL) {\r
- SetWindowText(hwnd, p);\r
- sel.cpMin = 999999;\r
- sel.cpMax = 999999;\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- return 0;\r
- }\r
- break;\r
- case VK_HOME:\r
- case VK_END:\r
- if (!(GetKeyState(VK_CONTROL) & ~1)) break;\r
- /* fall thru */\r
- case VK_PRIOR:\r
- case VK_NEXT:\r
- SendDlgItemMessage(hwndConsole, OPT_ConsoleText, message, wParam, lParam);\r
- return 0;\r
- }\r
- break;\r
- case WM_MBUTTONDOWN:\r
- SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
- WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
- break;\r
- case WM_RBUTTONUP:\r
- if (GetKeyState(VK_SHIFT) & ~1) {\r
- SendDlgItemMessage(hwndConsole, OPT_ConsoleText, \r
- WM_COMMAND, MAKEWPARAM(IDM_QuickPaste, 0), 0);\r
- } else {\r
- POINT pt;\r
- HMENU hmenu;\r
- hmenu = LoadMenu(hInst, "InputMenu");\r
- SendMessage(hwnd, EM_EXGETSEL, 0, (LPARAM)&sel);\r
- if (sel.cpMin == sel.cpMax) {\r
- EnableMenuItem(hmenu, IDM_Copy, MF_BYCOMMAND|MF_GRAYED);\r
- EnableMenuItem(hmenu, IDM_Cut, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
- if (!IsClipboardFormatAvailable(CF_TEXT)) {\r
- EnableMenuItem(hmenu, IDM_Paste, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
- pt.x = LOWORD(lParam);\r
- pt.y = HIWORD(lParam);\r
- MenuPopup(hwnd, pt, hmenu, -1);\r
- }\r
- return 0;\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) { \r
- case IDM_Undo:\r
- SendMessage(hwnd, EM_UNDO, 0, 0);\r
- return 0;\r
- case IDM_SelectAll:\r
- sel.cpMin = 0;\r
- sel.cpMax = -1; /*999999?*/\r
- SendMessage(hwnd, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- return 0;\r
- case IDM_Cut:\r
- SendMessage(hwnd, WM_CUT, 0, 0);\r
- return 0;\r
- case IDM_Paste:\r
- SendMessage(hwnd, WM_PASTE, 0, 0);\r
- return 0;\r
- case IDM_Copy:\r
- SendMessage(hwnd, WM_COPY, 0, 0);\r
- return 0;\r
- }\r
- break;\r
- }\r
- return (*consoleInputWindowProc)(hwnd, message, wParam, lParam);\r
-}\r
-\r
-#define CO_MAX 100000\r
-#define CO_TRIM 1000\r
-\r
-LRESULT CALLBACK\r
-ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- static HWND hText, hInput, hFocus;\r
- InputSource *is = consoleInputSource;\r
- RECT rect;\r
- static int sizeX, sizeY;\r
- int newSizeX, newSizeY;\r
- MINMAXINFO *mmi;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG: /* message: initialize dialog box */\r
- hwndConsole = hDlg;\r
- hText = GetDlgItem(hDlg, OPT_ConsoleText);\r
- hInput = GetDlgItem(hDlg, OPT_ConsoleInput);\r
- SetFocus(hInput);\r
- consoleTextWindowProc = (WNDPROC)\r
- SetWindowLong(hText, GWL_WNDPROC, (LONG) ConsoleTextSubclass);\r
- SendMessage(hText, EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
- consoleInputWindowProc = (WNDPROC)\r
- SetWindowLong(hInput, GWL_WNDPROC, (LONG) ConsoleInputSubclass);\r
- SendMessage(hInput, EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
- Colorize(ColorNormal, TRUE);\r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM) &consoleCF);\r
- ChangedConsoleFont();\r
- GetClientRect(hDlg, &rect);\r
- sizeX = rect.right;\r
- sizeY = rect.bottom;\r
- if (consoleX != CW_USEDEFAULT && consoleY != CW_USEDEFAULT &&\r
- consoleW != CW_USEDEFAULT && consoleH != CW_USEDEFAULT) {\r
- WINDOWPLACEMENT wp;\r
- EnsureOnScreen(&consoleX, &consoleY);\r
- wp.length = sizeof(WINDOWPLACEMENT);\r
- wp.flags = 0;\r
- wp.showCmd = SW_SHOW;\r
- wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
- wp.rcNormalPosition.left = consoleX;\r
- wp.rcNormalPosition.right = consoleX + consoleW;\r
- wp.rcNormalPosition.top = consoleY;\r
- wp.rcNormalPosition.bottom = consoleY + consoleH;\r
- SetWindowPlacement(hDlg, &wp);\r
- }\r
- return FALSE;\r
-\r
- case WM_SETFOCUS:\r
- SetFocus(hInput);\r
- return 0;\r
-\r
- case WM_CLOSE:\r
- ExitEvent(0);\r
- /* not reached */\r
- break;\r
-\r
- case WM_SIZE:\r
- if (IsIconic(hDlg)) break;\r
- newSizeX = LOWORD(lParam);\r
- newSizeY = HIWORD(lParam);\r
- if (sizeX != newSizeX || sizeY != newSizeY) {\r
- RECT rectText, rectInput;\r
- POINT pt;\r
- int newTextHeight, newTextWidth;\r
- GetWindowRect(hText, &rectText);\r
- newTextWidth = rectText.right - rectText.left + newSizeX - sizeX;\r
- newTextHeight = rectText.bottom - rectText.top + newSizeY - sizeY;\r
- if (newTextHeight < 0) {\r
- newSizeY += -newTextHeight;\r
- newTextHeight = 0;\r
- }\r
- SetWindowPos(hText, NULL, 0, 0,\r
- newTextWidth, newTextHeight, SWP_NOZORDER|SWP_NOMOVE);\r
- GetWindowRect(hInput, &rectInput); /* gives screen coords */\r
- pt.x = rectInput.left;\r
- pt.y = rectInput.top + newSizeY - sizeY;\r
- ScreenToClient(hDlg, &pt);\r
- SetWindowPos(hInput, NULL, \r
- pt.x, pt.y, /* needs client coords */ \r
- rectInput.right - rectInput.left + newSizeX - sizeX,\r
- rectInput.bottom - rectInput.top, SWP_NOZORDER);\r
- }\r
- sizeX = newSizeX;\r
- sizeY = newSizeY;\r
- break;\r
-\r
- case WM_GETMINMAXINFO:\r
- /* Prevent resizing window too small */\r
- mmi = (MINMAXINFO *) lParam;\r
- mmi->ptMinTrackSize.x = 100;\r
- mmi->ptMinTrackSize.y = 100;\r
- break;\r
- }\r
- return DefWindowProc(hDlg, message, wParam, lParam);\r
-}\r
-\r
-\r
-VOID\r
-ConsoleCreate()\r
-{\r
- HWND hCons;\r
- if (hwndConsole) return;\r
- hCons = CreateDialog(hInst, szConsoleName, 0, NULL);\r
- SendMessage(hCons, WM_INITDIALOG, 0, 0);\r
-}\r
-\r
-\r
-VOID\r
-ConsoleOutput(char* data, int length, int forceVisible)\r
-{\r
- HWND hText;\r
- int trim, exlen;\r
- char *p, *q;\r
- char buf[CO_MAX+1];\r
- POINT pEnd;\r
- RECT rect;\r
- static int delayLF = 0;\r
- CHARRANGE savesel, sel;\r
-\r
- if (hwndConsole == NULL || length > CO_MAX-100 || length == 0) return;\r
- p = data;\r
- q = buf;\r
- if (delayLF) {\r
- *q++ = '\r';\r
- *q++ = '\n';\r
- delayLF = 0;\r
- }\r
- while (length--) {\r
- if (*p == '\n') {\r
- if (*++p) {\r
- *q++ = '\r';\r
- *q++ = '\n';\r
- } else {\r
- delayLF = 1;\r
- }\r
- } else if (*p == '\007') {\r
- MyPlaySound(&sounds[(int)SoundBell]);\r
- p++;\r
- } else {\r
- *q++ = *p++;\r
- }\r
- }\r
- *q = NULLCHAR;\r
- hText = GetDlgItem(hwndConsole, OPT_ConsoleText);\r
- SendMessage(hText, EM_HIDESELECTION, TRUE, FALSE);\r
- /* Save current selection */\r
- SendMessage(hText, EM_EXGETSEL, 0, (LPARAM)&savesel);\r
- exlen = GetWindowTextLength(hText);\r
- /* Find out whether current end of text is visible */\r
- SendMessage(hText, EM_GETRECT, 0, (LPARAM) &rect);\r
- SendMessage(hText, EM_POSFROMCHAR, (WPARAM) &pEnd, exlen);\r
- /* Trim existing text if it's too long */\r
- if (exlen + (q - buf) > CO_MAX) {\r
- trim = (CO_TRIM > (q - buf)) ? CO_TRIM : (q - buf);\r
- sel.cpMin = 0;\r
- sel.cpMax = trim;\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SendMessage(hText, EM_REPLACESEL, 0, (LPARAM)"");\r
- exlen -= trim;\r
- savesel.cpMin -= trim;\r
- savesel.cpMax -= trim;\r
- if (exlen < 0) exlen = 0;\r
- if (savesel.cpMin < 0) savesel.cpMin = 0;\r
- if (savesel.cpMax < savesel.cpMin) savesel.cpMax = savesel.cpMin;\r
- }\r
- /* Append the new text */\r
- sel.cpMin = exlen;\r
- sel.cpMax = exlen;\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SendMessage(hText, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&consoleCF);\r
- SendMessage(hText, EM_REPLACESEL, 0, (LPARAM) buf);\r
- if (forceVisible || exlen == 0 ||\r
- (rect.left <= pEnd.x && pEnd.x < rect.right &&\r
- rect.top <= pEnd.y && pEnd.y < rect.bottom)) {\r
- /* Scroll to make new end of text visible if old end of text\r
- was visible or new text is an echo of user typein */\r
- sel.cpMin = 9999999;\r
- sel.cpMax = 9999999;\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- SendMessage(hText, EM_HIDESELECTION, FALSE, FALSE);\r
- SendMessage(hText, EM_SCROLLCARET, 0, 0);\r
- SendMessage(hText, EM_HIDESELECTION, TRUE, FALSE);\r
- }\r
- if (savesel.cpMax == exlen || forceVisible) {\r
- /* Move insert point to new end of text if it was at the old\r
- end of text or if the new text is an echo of user typein */\r
- sel.cpMin = 9999999;\r
- sel.cpMax = 9999999;\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&sel);\r
- } else {\r
- /* Restore previous selection */\r
- SendMessage(hText, EM_EXSETSEL, 0, (LPARAM)&savesel);\r
- }\r
- SendMessage(hText, EM_HIDESELECTION, FALSE, FALSE);\r
-}\r
-\r
-/*---------*/\r
-\r
-\r
-void\r
-DisplayAClock(HDC hdc, int timeRemaining, int highlight,\r
- RECT *rect, char *color)\r
-{\r
- char buf[100];\r
- char *str;\r
- COLORREF oldFg, oldBg;\r
- HFONT oldFont;\r
-\r
- if (appData.clockMode) {\r
- if (tinyLayout)\r
- sprintf(buf, "%c %s", color[0], TimeString(timeRemaining));\r
- else\r
- sprintf(buf, "%s: %s", color, TimeString(timeRemaining));\r
- str = buf;\r
- } else {\r
- str = color;\r
- }\r
-\r
- if (highlight) {\r
- oldFg = SetTextColor(hdc, RGB(255, 255, 255)); /* white */\r
- oldBg = SetBkColor(hdc, RGB(0, 0, 0)); /* black */\r
- } else {\r
- oldFg = SetTextColor(hdc, RGB(0, 0, 0)); /* black */\r
- oldBg = SetBkColor(hdc, RGB(255, 255, 255)); /* white */\r
- }\r
- oldFont = SelectObject(hdc, font[boardSize][CLOCK_FONT]->hf);\r
-\r
- ExtTextOut(hdc, rect->left + MESSAGE_LINE_LEFTMARGIN,\r
- rect->top, ETO_CLIPPED|ETO_OPAQUE,\r
- rect, str, strlen(str), NULL);\r
-\r
- (void) SetTextColor(hdc, oldFg);\r
- (void) SetBkColor(hdc, oldBg);\r
- (void) SelectObject(hdc, oldFont);\r
-}\r
-\r
-\r
-int\r
-DoReadFile(HANDLE hFile, char *buf, int count, DWORD *outCount,\r
- OVERLAPPED *ovl)\r
-{\r
- int ok, err;\r
-\r
- ResetEvent(ovl->hEvent);\r
- ovl->Offset = ovl->OffsetHigh = 0;\r
- ok = ReadFile(hFile, buf, count, outCount, ovl);\r
- if (ok) {\r
- err = NO_ERROR;\r
- } else {\r
- err = GetLastError();\r
- if (err == ERROR_IO_PENDING) {\r
- ok = GetOverlappedResult(hFile, ovl, outCount, TRUE);\r
- if (ok)\r
- err = NO_ERROR;\r
- else\r
- err = GetLastError();\r
- }\r
- }\r
- return err;\r
-}\r
-\r
-int\r
-DoWriteFile(HANDLE hFile, char *buf, int count, DWORD *outCount,\r
- OVERLAPPED *ovl)\r
-{\r
- int ok, err;\r
-\r
- ResetEvent(ovl->hEvent);\r
- ovl->Offset = ovl->OffsetHigh = 0;\r
- ok = WriteFile(hFile, buf, count, outCount, ovl);\r
- if (ok) {\r
- err = NO_ERROR;\r
- } else {\r
- err = GetLastError();\r
- if (err == ERROR_IO_PENDING) {\r
- ok = GetOverlappedResult(hFile, ovl, outCount, TRUE);\r
- if (ok)\r
- err = NO_ERROR;\r
- else\r
- err = GetLastError();\r
- }\r
- }\r
- return err;\r
-}\r
-\r
-\r
-DWORD\r
-InputThread(LPVOID arg)\r
-{\r
- InputSource *is;\r
- OVERLAPPED ovl;\r
-\r
- is = (InputSource *) arg;\r
- ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
- ovl.Internal = ovl.InternalHigh = ovl.Offset = ovl.OffsetHigh = 0;\r
- while (is->hThread != NULL) {\r
- is->error = DoReadFile(is->hFile, is->next,\r
- INPUT_SOURCE_BUF_SIZE - (is->next - is->buf),\r
- &is->count, &ovl);\r
- if (is->error == NO_ERROR) {\r
- is->next += is->count;\r
- } else {\r
- if (is->error == ERROR_BROKEN_PIPE) {\r
- /* Correct for MS brain damage. EOF reading a pipe is not an error. */\r
- is->count = 0;\r
- } else {\r
- is->count = (DWORD) -1;\r
- }\r
- }\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
- if (is->count <= 0) break; /* Quit on EOF or error */\r
- }\r
- CloseHandle(ovl.hEvent);\r
- CloseHandle(is->hFile);\r
- return 0;\r
-}\r
-\r
-\r
-/* Windows 95 beta 2 won't let you do overlapped i/o on a console or pipe */\r
-DWORD\r
-NonOvlInputThread(LPVOID arg)\r
-{\r
- InputSource *is;\r
- char *p, *q;\r
- int i;\r
- char prev;\r
-\r
- is = (InputSource *) arg;\r
- while (is->hThread != NULL) {\r
- is->error = ReadFile(is->hFile, is->next,\r
- INPUT_SOURCE_BUF_SIZE - (is->next - is->buf),\r
- &is->count, NULL) ? NO_ERROR : GetLastError();\r
- if (is->error == NO_ERROR) {\r
- /* Change CRLF to LF */\r
- if (is->next > is->buf) {\r
- p = is->next - 1;\r
- i = is->count + 1;\r
- } else {\r
- p = is->next;\r
- i = is->count;\r
- }\r
- q = p;\r
- prev = NULLCHAR;\r
- while (i > 0) {\r
- if (prev == '\r' && *p == '\n') {\r
- *(q-1) = '\n';\r
- is->count--;\r
- } else { \r
- *q++ = *p;\r
- }\r
- prev = *p++;\r
- i--;\r
- }\r
- *q = NULLCHAR;\r
- is->next = q;\r
- } else {\r
- if (is->error == ERROR_BROKEN_PIPE) {\r
- /* Correct for MS brain damage. EOF reading a pipe is not an error. */\r
- is->count = 0; \r
- } else {\r
- is->count = (DWORD) -1;\r
- }\r
- }\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
- if (is->count < 0) break; /* Quit on error */\r
- }\r
- CloseHandle(is->hFile);\r
- return 0;\r
-}\r
-\r
-DWORD\r
-SocketInputThread(LPVOID arg)\r
-{\r
- InputSource *is;\r
-\r
- is = (InputSource *) arg;\r
- while (is->hThread != NULL) {\r
- is->count = recv(is->sock, is->buf, INPUT_SOURCE_BUF_SIZE, 0);\r
- if ((int)is->count == SOCKET_ERROR) {\r
- is->count = (DWORD) -1;\r
- is->error = WSAGetLastError();\r
- } else {\r
- is->error = NO_ERROR;\r
- is->next += is->count;\r
- if (is->count == 0 && is->second == is) {\r
- /* End of file on stderr; quit with no message */\r
- break;\r
- }\r
- }\r
- SendMessage(hwndMain, WM_USER_Input, 0, (LPARAM) is);\r
- if (is->count <= 0) break; /* Quit on EOF or error */\r
- }\r
- return 0;\r
-}\r
-\r
-VOID\r
-InputEvent(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- InputSource *is;\r
-\r
- is = (InputSource *) lParam;\r
- if (is->lineByLine) {\r
- /* Feed in lines one by one */\r
- char *p = is->buf;\r
- char *q = p;\r
- while (q < is->next) {\r
- if (*q++ == '\n') {\r
- (is->func)(is, is->closure, p, q - p, NO_ERROR);\r
- p = q;\r
- }\r
- }\r
- /* Move any partial line to the start of the buffer */\r
- q = is->buf;\r
- while (p < is->next) {\r
- *q++ = *p++;\r
- }\r
- is->next = q;\r
- if (is->error != NO_ERROR || is->count == 0) {\r
- /* Notify backend of the error. Note: If there was a partial\r
- line at the end, it is not flushed through. */\r
- (is->func)(is, is->closure, is->buf, is->count, is->error); \r
- }\r
- } else {\r
- /* Feed in the whole chunk of input at once */\r
- (is->func)(is, is->closure, is->buf, is->count, is->error);\r
- is->next = is->buf;\r
- }\r
-}\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Menu enables. Used when setting various modes.\r
- *\r
-\*---------------------------------------------------------------------------*/\r
-\r
-typedef struct {\r
- int item;\r
- int flags;\r
-} Enables;\r
-\r
-VOID\r
-SetMenuEnables(HMENU hmenu, Enables *enab)\r
-{\r
- while (enab->item > 0) {\r
- (void) EnableMenuItem(hmenu, enab->item, enab->flags);\r
- enab++;\r
- }\r
-}\r
-\r
-Enables gnuEnables[] = {\r
- { IDM_MailMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_IcsClient, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Accept, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Decline, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Rematch, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Adjourn, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_StopExamining, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_StopObserving, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Revert, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables icsEnables[] = {\r
- { IDM_MailMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_AnalysisMode, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Hint, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Book, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_IcsOptions, MF_BYCOMMAND|MF_ENABLED },\r
- { -1, -1 }\r
-};\r
-\r
-#ifdef ZIPPY\r
-Enables zippyEnables[] = {\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Hint, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Book, MF_BYCOMMAND|MF_ENABLED },\r
- { -1, -1 }\r
-};\r
-#endif\r
-\r
-Enables ncpEnables[] = {\r
- { IDM_MailMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_AnalysisMode, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_AnalyzeFile, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_IcsClient, MF_BYCOMMAND|MF_GRAYED },\r
- { ACTION_POS, MF_BYPOSITION|MF_GRAYED },\r
- { IDM_Revert, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_RetractMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TimeControl, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Hint, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Book, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables trainingOnEnables[] = {\r
- { IDM_EditComment, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Pause, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Forward, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Backward, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ToEnd, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ToStart, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TruncateGame, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables trainingOffEnables[] = {\r
- { IDM_EditComment, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Pause, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Forward, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Backward, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ToEnd, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ToStart, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_MoveNow, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_TruncateGame, MF_BYCOMMAND|MF_ENABLED },\r
- { -1, -1 }\r
-};\r
-\r
-/* These modify either ncpEnables or gnuEnables */\r
-Enables cmailEnables[] = {\r
- { IDM_MailMove, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ReloadCMailMsg, MF_BYCOMMAND|MF_ENABLED },\r
- { ACTION_POS, MF_BYPOSITION|MF_ENABLED },\r
- { IDM_CallFlag, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Draw, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_Adjourn, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_Abort, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables machineThinkingEnables[] = {\r
- { IDM_LoadGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadNextGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadPrevGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_PasteGame, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadPosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadNextPosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_LoadPrevPosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_ReloadPosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_PastePosition, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineWhite, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_MachineBlack, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TwoMachines, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_TypeInMove, MF_BYCOMMAND|MF_GRAYED },\r
- { IDM_RetractMove, MF_BYCOMMAND|MF_GRAYED },\r
- { -1, -1 }\r
-};\r
-\r
-Enables userThinkingEnables[] = {\r
- { IDM_LoadGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadNextGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadPrevGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ReloadGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_PasteGame, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadPosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadNextPosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_LoadPrevPosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_ReloadPosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_PastePosition, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_MachineWhite, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_MachineBlack, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_TwoMachines, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_TypeInMove, MF_BYCOMMAND|MF_ENABLED },\r
- { IDM_RetractMove, MF_BYCOMMAND|MF_ENABLED },\r
- { -1, -1 }\r
-};\r
-\r
-/*---------------------------------------------------------------------------*\\r
- *\r
- * Front-end interface functions exported by XBoard.\r
- * Functions appear in same order as prototypes in frontend.h.\r
- * \r
-\*---------------------------------------------------------------------------*/\r
-VOID\r
-ModeHighlight()\r
-{\r
- static UINT prevChecked = 0;\r
- static int prevPausing = 0;\r
- UINT nowChecked;\r
-\r
- if (pausing != prevPausing) {\r
- prevPausing = pausing;\r
- (void) CheckMenuItem(GetMenu(hwndMain), IDM_Pause,\r
- MF_BYCOMMAND|(pausing ? MF_CHECKED : MF_UNCHECKED));\r
- if (hwndPause) SetWindowText(hwndPause, pausing ? "C" : "P");\r
- }\r
-\r
- switch (gameMode) {\r
- case BeginningOfGame:\r
- if (appData.icsActive)\r
- nowChecked = IDM_IcsClient;\r
- else if (appData.noChessProgram)\r
- nowChecked = IDM_EditGame;\r
- else\r
- nowChecked = IDM_MachineBlack;\r
- break;\r
- case MachinePlaysBlack:\r
- nowChecked = IDM_MachineBlack;\r
- break;\r
- case MachinePlaysWhite:\r
- nowChecked = IDM_MachineWhite;\r
- break;\r
- case TwoMachinesPlay:\r
- nowChecked = IDM_TwoMachines;\r
- break;\r
- case AnalyzeMode:\r
- nowChecked = IDM_AnalysisMode;\r
- break;\r
- case AnalyzeFile:\r
- nowChecked = IDM_AnalyzeFile;\r
- break;\r
- case EditGame:\r
- nowChecked = IDM_EditGame;\r
- break;\r
- case PlayFromGameFile:\r
- nowChecked = IDM_LoadGame;\r
- break;\r
- case EditPosition:\r
- nowChecked = IDM_EditPosition;\r
- break;\r
- case Training:\r
- nowChecked = IDM_Training;\r
- break;\r
- case IcsPlayingWhite:\r
- case IcsPlayingBlack:\r
- case IcsObserving:\r
- case IcsIdle:\r
- nowChecked = IDM_IcsClient;\r
- break;\r
- default:\r
- case EndOfGame:\r
- nowChecked = 0;\r
- break;\r
- }\r
- if (prevChecked != 0)\r
- (void) CheckMenuItem(GetMenu(hwndMain),\r
- prevChecked, MF_BYCOMMAND|MF_UNCHECKED);\r
- if (nowChecked != 0)\r
- (void) CheckMenuItem(GetMenu(hwndMain),\r
- nowChecked, MF_BYCOMMAND|MF_CHECKED);\r
-\r
- if (nowChecked == IDM_LoadGame || nowChecked == IDM_Training) {\r
- (void) EnableMenuItem(GetMenu(hwndMain), IDM_Training, \r
- MF_BYCOMMAND|MF_ENABLED);\r
- } else {\r
- (void) EnableMenuItem(GetMenu(hwndMain), \r
- IDM_Training, MF_BYCOMMAND|MF_GRAYED);\r
- }\r
-\r
- prevChecked = nowChecked;\r
-}\r
-\r
-VOID\r
-SetICSMode()\r
-{\r
- HMENU hmenu = GetMenu(hwndMain);\r
- SetMenuEnables(hmenu, icsEnables);\r
- EnableMenuItem(GetSubMenu(hmenu, OPTIONS_POS), ICS_POS,\r
- MF_BYPOSITION|MF_ENABLED);\r
-#ifdef ZIPPY\r
- if (appData.zippyPlay) {\r
- SetMenuEnables(hmenu, zippyEnables);\r
- }\r
-#endif\r
-}\r
-\r
-VOID\r
-SetGNUMode()\r
-{\r
- SetMenuEnables(GetMenu(hwndMain), gnuEnables);\r
-}\r
-\r
-VOID\r
-SetNCPMode()\r
-{\r
- HMENU hmenu = GetMenu(hwndMain);\r
- SetMenuEnables(hmenu, ncpEnables);\r
- EnableMenuItem(GetSubMenu(hmenu, OPTIONS_POS), SOUNDS_POS,\r
- MF_BYPOSITION|MF_GRAYED);\r
- DrawMenuBar(hwndMain);\r
-}\r
-\r
-VOID\r
-SetCmailMode()\r
-{\r
- SetMenuEnables(GetMenu(hwndMain), cmailEnables);\r
-}\r
-\r
-VOID \r
-SetTrainingModeOn()\r
-{\r
- int i;\r
- SetMenuEnables(GetMenu(hwndMain), trainingOnEnables);\r
- for (i = 0; i < N_BUTTONS; i++) {\r
- if (buttonDesc[i].hwnd != NULL)\r
- EnableWindow(buttonDesc[i].hwnd, FALSE);\r
- }\r
- CommentPopDown();\r
-}\r
-\r
-VOID SetTrainingModeOff()\r
-{\r
- int i;\r
- SetMenuEnables(GetMenu(hwndMain), trainingOffEnables);\r
- for (i = 0; i < N_BUTTONS; i++) {\r
- if (buttonDesc[i].hwnd != NULL)\r
- EnableWindow(buttonDesc[i].hwnd, TRUE);\r
- }\r
-}\r
-\r
-\r
-VOID\r
-SetUserThinkingEnables()\r
-{\r
- SetMenuEnables(GetMenu(hwndMain), userThinkingEnables);\r
-}\r
-\r
-VOID\r
-SetMachineThinkingEnables()\r
-{\r
- HMENU hMenu = GetMenu(hwndMain);\r
- int flags = MF_BYCOMMAND|MF_ENABLED;\r
-\r
- SetMenuEnables(hMenu, machineThinkingEnables);\r
-\r
- if (gameMode == MachinePlaysBlack) {\r
- (void)EnableMenuItem(hMenu, IDM_MachineBlack, flags);\r
- } else if (gameMode == MachinePlaysWhite) {\r
- (void)EnableMenuItem(hMenu, IDM_MachineWhite, flags);\r
- } else if (gameMode == TwoMachinesPlay) {\r
- (void)EnableMenuItem(hMenu, IDM_TwoMachines, flags);\r
- }\r
-}\r
-\r
-\r
-VOID\r
-DisplayTitle(char *str)\r
-{\r
- char title[MSG_SIZ], *host;\r
- if (str[0] != NULLCHAR) {\r
- strcpy(title, str);\r
- } else if (appData.icsActive) {\r
- if (appData.icsCommPort[0] != NULLCHAR)\r
- host = "ICS";\r
- else \r
- host = appData.icsHost;\r
- sprintf(title, "%s: %s", szTitle, host);\r
- } else if (appData.noChessProgram) {\r
- strcpy(title, szTitle);\r
- } else {\r
- strcpy(title, szTitle);\r
- strcat(title, ": ");\r
- strcat(title, first.tidy);\r
- }\r
- SetWindowText(hwndMain, title);\r
-}\r
-\r
-\r
-VOID\r
-DisplayMessage(char *str1, char *str2)\r
-{\r
- HDC hdc;\r
- HFONT oldFont;\r
- int remain = MESSAGE_TEXT_MAX - 1;\r
- int len;\r
-\r
- moveErrorMessageUp = FALSE; /* turned on later by caller if needed */\r
- messageText[0] = NULLCHAR;\r
- if (*str1) {\r
- len = strlen(str1);\r
- if (len > remain) len = remain;\r
- strncpy(messageText, str1, len);\r
- messageText[len] = NULLCHAR;\r
- remain -= len;\r
- }\r
- if (*str2 && remain >= 2) {\r
- if (*str1) {\r
- strcat(messageText, " ");\r
- remain -= 2;\r
- }\r
- len = strlen(str2);\r
- if (len > remain) len = remain;\r
- strncat(messageText, str2, len);\r
- }\r
- messageText[MESSAGE_TEXT_MAX - 1] = NULLCHAR;\r
-\r
- if (IsIconic(hwndMain)) return;\r
- hdc = GetDC(hwndMain);\r
- oldFont = SelectObject(hdc, font[boardSize][MESSAGE_FONT]->hf);\r
- ExtTextOut(hdc, messageRect.left, messageRect.top, ETO_CLIPPED|ETO_OPAQUE,\r
- &messageRect, messageText, strlen(messageText), NULL);\r
- (void) SelectObject(hdc, oldFont);\r
- (void) ReleaseDC(hwndMain, hdc);\r
-}\r
-\r
-VOID\r
-DisplayError(char *str, int error)\r
-{\r
- char buf[MSG_SIZ*2], buf2[MSG_SIZ];\r
- int len;\r
- \r
- if (error == 0) {\r
- strcpy(buf, str);\r
- } else {\r
- len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,\r
- NULL, error, LANG_NEUTRAL,\r
- (LPSTR) buf2, MSG_SIZ, NULL);\r
- if (len > 0) {\r
- sprintf(buf, "%s:\n%s", str, buf2);\r
- } else {\r
- ErrorMap *em = errmap;\r
- while (em->err != 0 && em->err != error) em++;\r
- if (em->err != 0) {\r
- sprintf(buf, "%s:\n%s", str, em->msg);\r
- } else {\r
- sprintf(buf, "%s:\nError code %d", str, error);\r
- }\r
- }\r
- }\r
- \r
- ErrorPopUp("Error", buf);\r
-}\r
-\r
-\r
-VOID\r
-DisplayMoveError(char *str)\r
-{\r
- fromX = fromY = -1;\r
- ClearHighlights();\r
- DrawPosition(FALSE, NULL);\r
- if (appData.popupMoveErrors) {\r
- ErrorPopUp("Error", str);\r
- } else {\r
- DisplayMessage(str, "");\r
- moveErrorMessageUp = TRUE;\r
- }\r
-}\r
-\r
-VOID\r
-DisplayFatalError(char *str, int error, int exitStatus)\r
-{\r
- char buf[2*MSG_SIZ], buf2[MSG_SIZ];\r
- int len;\r
- char *label = exitStatus ? "Fatal Error" : "Exiting";\r
-\r
- if (error != 0) {\r
- len = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM,\r
- NULL, error, LANG_NEUTRAL,\r
- (LPSTR) buf2, MSG_SIZ, NULL);\r
- if (len > 0) {\r
- sprintf(buf, "%s:\n%s", str, buf2);\r
- } else {\r
- ErrorMap *em = errmap;\r
- while (em->err != 0 && em->err != error) em++;\r
- if (em->err != 0) {\r
- sprintf(buf, "%s:\n%s", str, em->msg);\r
- } else {\r
- sprintf(buf, "%s:\nError code %d", str, error);\r
- }\r
- }\r
- str = buf;\r
- }\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "%s: %s\n", label, str);\r
- }\r
- if (appData.popupExitMessage) {\r
- (void) MessageBox(hwndMain, str, label, MB_OK|\r
- (exitStatus ? MB_ICONSTOP : MB_ICONINFORMATION));\r
- }\r
- ExitEvent(exitStatus);\r
-}\r
-\r
-\r
-VOID\r
-DisplayInformation(char *str)\r
-{\r
- (void) MessageBox(hwndMain, str, "Information", MB_OK|MB_ICONINFORMATION);\r
-}\r
-\r
-\r
-VOID\r
-DisplayNote(char *str)\r
-{\r
- ErrorPopUp("Note", str);\r
-}\r
-\r
-\r
-typedef struct {\r
- char *title, *question, *replyPrefix;\r
- ProcRef pr;\r
-} QuestionParams;\r
-\r
-LRESULT CALLBACK\r
-QuestionDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- static QuestionParams *qp;\r
- char reply[MSG_SIZ];\r
- int len, err;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG:\r
- qp = (QuestionParams *) lParam;\r
- CenterWindow(hDlg, GetWindow(hDlg, GW_OWNER));\r
- SetWindowText(hDlg, qp->title);\r
- SetDlgItemText(hDlg, OPT_QuestionText, qp->question);\r
- SetFocus(GetDlgItem(hDlg, OPT_QuestionInput));\r
- return FALSE;\r
-\r
- case WM_COMMAND:\r
- switch (LOWORD(wParam)) {\r
- case IDOK:\r
- strcpy(reply, qp->replyPrefix);\r
- if (*reply) strcat(reply, " ");\r
- len = strlen(reply);\r
- GetDlgItemText(hDlg, OPT_QuestionInput, reply + len, sizeof(reply) - len);\r
- strcat(reply, "\n");\r
- OutputToProcess(qp->pr, reply, strlen(reply), &err);\r
- EndDialog(hDlg, TRUE);\r
- if (err) DisplayFatalError("Error writing to chess program", err, 1);\r
- return TRUE;\r
- case IDCANCEL:\r
- EndDialog(hDlg, FALSE);\r
- return TRUE;\r
- default:\r
- break;\r
- }\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-AskQuestion(char* title, char *question, char *replyPrefix, ProcRef pr)\r
-{\r
- QuestionParams qp;\r
- FARPROC lpProc;\r
- \r
- qp.title = title;\r
- qp.question = question;\r
- qp.replyPrefix = replyPrefix;\r
- qp.pr = pr;\r
- lpProc = MakeProcInstance((FARPROC)QuestionDialog, hInst);\r
- DialogBoxParam(hInst, MAKEINTRESOURCE(DLG_Question),\r
- hwndMain, (DLGPROC)lpProc, (LPARAM)&qp);\r
- FreeProcInstance(lpProc);\r
-}\r
-\r
-\r
-VOID\r
-DisplayIcsInteractionTitle(char *str)\r
-{\r
- char consoleTitle[MSG_SIZ];\r
-\r
- sprintf(consoleTitle, "%s: %s", szConsoleTitle, str);\r
- SetWindowText(hwndConsole, consoleTitle);\r
-}\r
-\r
-void\r
-DrawPosition(int fullRedraw, Board board)\r
-{\r
- HDCDrawPosition(NULL, (BOOLEAN) fullRedraw, board); \r
-}\r
-\r
-\r
-VOID\r
-ResetFrontEnd()\r
-{\r
- fromX = fromY = -1;\r
- if (dragInfo.pos.x != -1 || dragInfo.pos.y != -1) {\r
- dragInfo.pos.x = dragInfo.pos.y = -1;\r
- dragInfo.pos.x = dragInfo.pos.y = -1;\r
- dragInfo.lastpos = dragInfo.pos;\r
- dragInfo.start.x = dragInfo.start.y = -1;\r
- dragInfo.from = dragInfo.start;\r
- ReleaseCapture();\r
- DrawPosition(TRUE, NULL);\r
- }\r
-}\r
-\r
-\r
-VOID\r
-CommentPopUp(char *title, char *str)\r
-{\r
- HWND hwnd = GetActiveWindow();\r
- EitherCommentPopUp(0, title, str, FALSE);\r
- SetActiveWindow(hwnd);\r
-}\r
-\r
-VOID\r
-CommentPopDown(void)\r
-{\r
- CheckMenuItem(GetMenu(hwndMain), IDM_EditComment, MF_UNCHECKED);\r
- if (commentDialog) {\r
- ShowWindow(commentDialog, SW_HIDE);\r
- }\r
- commentDialogUp = FALSE;\r
-}\r
-\r
-VOID\r
-EditCommentPopUp(int index, char *title, char *str)\r
-{\r
- EitherCommentPopUp(index, title, str, TRUE);\r
-}\r
-\r
-\r
-VOID\r
-RingBell()\r
-{\r
- MyPlaySound(&sounds[(int)SoundMove]);\r
-}\r
-\r
-VOID PlayIcsWinSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundIcsWin]);\r
-}\r
-\r
-VOID PlayIcsLossSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundIcsLoss]);\r
-}\r
-\r
-VOID PlayIcsDrawSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundIcsDraw]);\r
-}\r
-\r
-VOID PlayIcsUnfinishedSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundIcsUnfinished]);\r
-}\r
-\r
-VOID\r
-PlayAlarmSound()\r
-{\r
- MyPlaySound(&sounds[(int)SoundAlarm]);\r
-}\r
-\r
-\r
-VOID\r
-EchoOn()\r
-{\r
- HWND hInput;\r
- consoleEcho = TRUE;\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&consoleCF);\r
- SendMessage(hInput, EM_SETBKGNDCOLOR, FALSE, consoleBackgroundColor);\r
-}\r
-\r
-\r
-VOID\r
-EchoOff()\r
-{\r
- CHARFORMAT cf;\r
- HWND hInput;\r
- consoleEcho = FALSE;\r
- hInput = GetDlgItem(hwndConsole, OPT_ConsoleInput);\r
- /* This works OK: set text and background both to the same color */\r
- cf = consoleCF;\r
- cf.crTextColor = COLOR_ECHOOFF;\r
- SendMessage(hInput, EM_SETCHARFORMAT, SCF_ALL, (LPARAM)&cf);\r
- SendMessage(hInput, EM_SETBKGNDCOLOR, FALSE, cf.crTextColor);\r
-}\r
-\r
-/* No Raw()...? */\r
-\r
-void Colorize(ColorClass cc, int continuation)\r
-{\r
- currentColorClass = cc;\r
- consoleCF.dwMask = CFM_COLOR|CFM_BOLD|CFM_ITALIC|CFM_UNDERLINE|CFM_STRIKEOUT;\r
- consoleCF.crTextColor = textAttribs[cc].color;\r
- consoleCF.dwEffects = textAttribs[cc].effects;\r
- if (!continuation) MyPlaySound(&textAttribs[cc].sound);\r
-}\r
-\r
-char *\r
-UserName()\r
-{\r
- static char buf[MSG_SIZ];\r
- DWORD bufsiz = MSG_SIZ;\r
-\r
- if (!GetUserName(buf, &bufsiz)) {\r
- /*DisplayError("Error getting user name", GetLastError());*/\r
- strcpy(buf, "User");\r
- }\r
- return buf;\r
-}\r
-\r
-char *\r
-HostName()\r
-{\r
- static char buf[MSG_SIZ];\r
- DWORD bufsiz = MSG_SIZ;\r
-\r
- if (!GetComputerName(buf, &bufsiz)) {\r
- /*DisplayError("Error getting host name", GetLastError());*/\r
- strcpy(buf, "Unknown");\r
- }\r
- return buf;\r
-}\r
-\r
-\r
-int\r
-ClockTimerRunning()\r
-{\r
- return clockTimerEvent != 0;\r
-}\r
-\r
-int\r
-StopClockTimer()\r
-{\r
- if (clockTimerEvent == 0) return FALSE;\r
- KillTimer(hwndMain, clockTimerEvent);\r
- clockTimerEvent = 0;\r
- return TRUE;\r
-}\r
-\r
-void\r
-StartClockTimer(long millisec)\r
-{\r
- clockTimerEvent = SetTimer(hwndMain, (UINT) CLOCK_TIMER_ID,\r
- (UINT) millisec, NULL);\r
-}\r
-\r
-void\r
-DisplayWhiteClock(long timeRemaining, int highlight)\r
-{\r
- HDC hdc;\r
- hdc = GetDC(hwndMain);\r
- if (!IsIconic(hwndMain)) {\r
- DisplayAClock(hdc, timeRemaining, highlight, &whiteRect, "White");\r
- }\r
- if (highlight && iconCurrent == iconBlack) {\r
- iconCurrent = iconWhite;\r
- PostMessage(hwndMain, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent);\r
- if (IsIconic(hwndMain)) {\r
- DrawIcon(hdc, 2, 2, iconCurrent);\r
- }\r
- }\r
- (void) ReleaseDC(hwndMain, hdc);\r
- if (hwndConsole)\r
- PostMessage(hwndConsole, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent);\r
-}\r
-\r
-void\r
-DisplayBlackClock(long timeRemaining, int highlight)\r
-{\r
- HDC hdc;\r
- hdc = GetDC(hwndMain);\r
- if (!IsIconic(hwndMain)) {\r
- DisplayAClock(hdc, timeRemaining, highlight, &blackRect, "Black");\r
- }\r
- if (highlight && iconCurrent == iconWhite) {\r
- iconCurrent = iconBlack;\r
- PostMessage(hwndMain, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent);\r
- if (IsIconic(hwndMain)) {\r
- DrawIcon(hdc, 2, 2, iconCurrent);\r
- }\r
- }\r
- (void) ReleaseDC(hwndMain, hdc);\r
- if (hwndConsole)\r
- PostMessage(hwndConsole, WM_SETICON, (WPARAM) TRUE, (LPARAM) iconCurrent);\r
-}\r
-\r
-\r
-int\r
-LoadGameTimerRunning()\r
-{\r
- return loadGameTimerEvent != 0;\r
-}\r
-\r
-int\r
-StopLoadGameTimer()\r
-{\r
- if (loadGameTimerEvent == 0) return FALSE;\r
- KillTimer(hwndMain, loadGameTimerEvent);\r
- loadGameTimerEvent = 0;\r
- return TRUE;\r
-}\r
-\r
-void\r
-StartLoadGameTimer(long millisec)\r
-{\r
- loadGameTimerEvent = SetTimer(hwndMain, (UINT) LOAD_GAME_TIMER_ID,\r
- (UINT) millisec, NULL);\r
-}\r
-\r
-void\r
-AutoSaveGame()\r
-{\r
- char *defName;\r
- FILE *f;\r
- char fileTitle[MSG_SIZ];\r
-\r
- defName = DefaultFileName(appData.oldSaveStyle ? "gam" : "pgn");\r
- f = OpenFileDialog(hwndMain, TRUE, defName,\r
- appData.oldSaveStyle ? "gam" : "pgn",\r
- GAME_FILT, \r
- "Save Game to File", NULL, fileTitle, NULL);\r
- if (f != NULL) {\r
- SaveGame(f, 0, "");\r
- fclose(f);\r
- }\r
-}\r
-\r
-\r
-void\r
-ScheduleDelayedEvent(DelayedEventCallback cb, long millisec)\r
-{\r
- if (delayedTimerEvent != 0) {\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "ScheduleDelayedEvent: event already scheduled\n");\r
- }\r
- KillTimer(hwndMain, delayedTimerEvent);\r
- delayedTimerEvent = 0;\r
- delayedTimerCallback();\r
- }\r
- delayedTimerCallback = cb;\r
- delayedTimerEvent = SetTimer(hwndMain, (UINT) DELAYED_TIMER_ID,\r
- (UINT) millisec, NULL);\r
-}\r
-\r
-DelayedEventCallback\r
-GetDelayedEvent()\r
-{\r
- if (delayedTimerEvent) {\r
- return delayedTimerCallback;\r
- } else {\r
- return NULL;\r
- }\r
-}\r
-\r
-void\r
-CancelDelayedEvent()\r
-{\r
- if (delayedTimerEvent) {\r
- KillTimer(hwndMain, delayedTimerEvent);\r
- delayedTimerEvent = 0;\r
- }\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
- Exit with fatal error if anything goes wrong.\r
- Returns an opaque pointer that can be used to destroy the process\r
- later.\r
-*/\r
-int\r
-StartChildProcess(char *cmdLine, char *dir, ProcRef *pr)\r
-{\r
-#define BUFSIZE 4096\r
-\r
- HANDLE hChildStdinRd, hChildStdinWr,\r
- hChildStdoutRd, hChildStdoutWr;\r
- HANDLE hChildStdinWrDup, hChildStdoutRdDup;\r
- SECURITY_ATTRIBUTES saAttr;\r
- BOOL fSuccess;\r
- PROCESS_INFORMATION piProcInfo;\r
- STARTUPINFO siStartInfo;\r
- ChildProc *cp;\r
- char buf[MSG_SIZ];\r
- DWORD err;\r
-\r
- if (appData.debugMode) {\r
- fprintf(debugFP, "StartChildProcess (dir=\"%s\") %s\n", dir, cmdLine);\r
- }\r
-\r
- *pr = NoProc;\r
-\r
- /* Set the bInheritHandle flag so pipe handles are inherited. */\r
- saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);\r
- saAttr.bInheritHandle = TRUE;\r
- saAttr.lpSecurityDescriptor = NULL;\r
-\r
- /*\r
- * The steps for redirecting child's STDOUT:\r
- * 1. Create anonymous pipe to be STDOUT for child.\r
- * 2. Create a noninheritable duplicate of read handle,\r
- * and close the inheritable read handle.\r
- */\r
-\r
- /* Create a pipe for the child's STDOUT. */\r
- if (! CreatePipe(&hChildStdoutRd, &hChildStdoutWr, &saAttr, 0)) {\r
- return GetLastError();\r
- }\r
-\r
- /* Duplicate the read handle to the pipe, so it is not inherited. */\r
- fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdoutRd,\r
- GetCurrentProcess(), &hChildStdoutRdDup, 0,\r
- FALSE, /* not inherited */\r
- DUPLICATE_SAME_ACCESS);\r
- if (! fSuccess) {\r
- return GetLastError();\r
- }\r
- CloseHandle(hChildStdoutRd);\r
-\r
- /*\r
- * The steps for redirecting child's STDIN:\r
- * 1. Create anonymous pipe to be STDIN for child.\r
- * 2. Create a noninheritable duplicate of write handle,\r
- * and close the inheritable write handle.\r
- */\r
-\r
- /* Create a pipe for the child's STDIN. */\r
- if (! CreatePipe(&hChildStdinRd, &hChildStdinWr, &saAttr, 0)) {\r
- return GetLastError();\r
- }\r
-\r
- /* Duplicate the write handle to the pipe, so it is not inherited. */\r
- fSuccess = DuplicateHandle(GetCurrentProcess(), hChildStdinWr,\r
- GetCurrentProcess(), &hChildStdinWrDup, 0,\r
- FALSE, /* not inherited */\r
- DUPLICATE_SAME_ACCESS);\r
- if (! fSuccess) {\r
- return GetLastError();\r
- }\r
- CloseHandle(hChildStdinWr);\r
-\r
- /* Arrange to (1) look in dir for the child .exe file, and\r
- * (2) have dir be the child's working directory. Interpret\r
- * dir relative to the directory WinBoard loaded from. */\r
- GetCurrentDirectory(MSG_SIZ, buf);\r
- SetCurrentDirectory(installDir);\r
- SetCurrentDirectory(dir);\r
-\r
- /* Now create the child process. */\r
-\r
- siStartInfo.cb = sizeof(STARTUPINFO);\r
- siStartInfo.lpReserved = NULL;\r
- siStartInfo.lpDesktop = NULL;\r
- siStartInfo.lpTitle = NULL;\r
- siStartInfo.dwFlags = STARTF_USESTDHANDLES;\r
- siStartInfo.cbReserved2 = 0;\r
- siStartInfo.lpReserved2 = NULL;\r
- siStartInfo.hStdInput = hChildStdinRd;\r
- siStartInfo.hStdOutput = hChildStdoutWr;\r
- siStartInfo.hStdError = hChildStdoutWr;\r
-\r
- fSuccess = CreateProcess(NULL,\r
- cmdLine, /* command line */\r
- NULL, /* process security attributes */\r
- NULL, /* primary thread security attrs */\r
- TRUE, /* handles are inherited */\r
- DETACHED_PROCESS|CREATE_NEW_PROCESS_GROUP,\r
- NULL, /* use parent's environment */\r
- NULL,\r
- &siStartInfo, /* STARTUPINFO pointer */\r
- &piProcInfo); /* receives PROCESS_INFORMATION */\r
-\r
- err = GetLastError();\r
- SetCurrentDirectory(buf); /* return to prev directory */\r
- if (! fSuccess) {\r
- return err;\r
- }\r
-\r
- /* Close the handles we don't need in the parent */\r
- CloseHandle(piProcInfo.hThread);\r
- CloseHandle(hChildStdinRd);\r
- CloseHandle(hChildStdoutWr);\r
-\r
- /* Prepare return value */\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPReal;\r
- cp->hProcess = piProcInfo.hProcess;\r
- cp->pid = piProcInfo.dwProcessId;\r
- cp->hFrom = hChildStdoutRdDup;\r
- cp->hTo = hChildStdinWrDup;\r
-\r
- *pr = (void *) cp;\r
-\r
- /* Klaus Friedel says that this Sleep solves a problem under Windows\r
- 2000 where engines sometimes don't see the initial command(s)\r
- from WinBoard and hang. I don't understand how that can happen,\r
- but the Sleep is harmless, so I've put it in. Others have also\r
- reported what may be the same problem, so hopefully this will fix\r
- it for them too. */\r
- Sleep(500);\r
-\r
- return NO_ERROR;\r
-}\r
-\r
-\r
-void\r
-DestroyChildProcess(ProcRef pr, int/*boolean*/ signal)\r
-{\r
- ChildProc *cp;\r
-\r
- cp = (ChildProc *) pr;\r
- if (cp == NULL) return;\r
-\r
- switch (cp->kind) {\r
- case CPReal:\r
- /* TerminateProcess is considered harmful, so... */\r
- CloseHandle(cp->hTo); /* Closing this will give the child an EOF and hopefully kill it */\r
- if (cp->hFrom) CloseHandle(cp->hFrom); /* if NULL, InputThread will close it */\r
- /* The following doesn't work because the chess program\r
- doesn't "have the same console" as WinBoard. Maybe\r
- we could arrange for this even though neither WinBoard\r
- nor the chess program uses a console for stdio? */\r
- /*!!if (signal) GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, cp->pid);*/\r
- CloseHandle(cp->hProcess);\r
- break;\r
-\r
- case CPComm:\r
- if (cp->hFrom) CloseHandle(cp->hFrom);\r
- break;\r
-\r
- case CPSock:\r
- closesocket(cp->sock);\r
- WSACleanup();\r
- break;\r
-\r
- case CPRcmd:\r
- if (signal) send(cp->sock2, "\017", 1, 0); /* 017 = 15 = SIGTERM */\r
- closesocket(cp->sock);\r
- closesocket(cp->sock2);\r
- WSACleanup();\r
- break;\r
- }\r
- free(cp);\r
-}\r
-\r
-void\r
-InterruptChildProcess(ProcRef pr)\r
-{\r
- ChildProc *cp;\r
-\r
- cp = (ChildProc *) pr;\r
- if (cp == NULL) return;\r
- switch (cp->kind) {\r
- case CPReal:\r
- /* The following doesn't work because the chess program\r
- doesn't "have the same console" as WinBoard. Maybe\r
- we could arrange for this even though neither WinBoard\r
- nor the chess program uses a console for stdio */\r
- /*!!GenerateConsoleCtrlEvent(CTRL_C_EVENT, cp->pid);*/\r
- break;\r
-\r
- case CPComm:\r
- case CPSock:\r
- /* Can't interrupt */\r
- break;\r
-\r
- case CPRcmd:\r
- send(cp->sock2, "\002", 1, 0); /* 2 = SIGINT */\r
- break;\r
- }\r
-}\r
-\r
-\r
-int\r
-OpenTelnet(char *host, char *port, ProcRef *pr)\r
-{\r
- char cmdLine[MSG_SIZ];\r
-\r
- if (port[0] == NULLCHAR) {\r
- sprintf(cmdLine, "%s %s", appData.telnetProgram, host);\r
- } else {\r
- sprintf(cmdLine, "%s %s %s", appData.telnetProgram, host, port);\r
- }\r
- return StartChildProcess(cmdLine, "", pr);\r
-}\r
-\r
-\r
-/* Code to open TCP sockets */\r
-\r
-int\r
-OpenTCP(char *host, char *port, ProcRef *pr)\r
-{\r
- ChildProc *cp;\r
- int err;\r
- SOCKET s;\r
- struct sockaddr_in sa, mysa;\r
- struct hostent FAR *hp;\r
- unsigned short uport;\r
- WORD wVersionRequested;\r
- WSADATA wsaData;\r
-\r
- /* Initialize socket DLL */\r
- wVersionRequested = MAKEWORD(1, 1);\r
- err = WSAStartup(wVersionRequested, &wsaData);\r
- if (err != 0) return err;\r
-\r
- /* Make socket */\r
- if ((s = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {\r
- err = WSAGetLastError();\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- /* Bind local address using (mostly) don't-care values.\r
- */\r
- memset((char *) &mysa, 0, sizeof(struct sockaddr_in));\r
- mysa.sin_family = AF_INET;\r
- mysa.sin_addr.s_addr = INADDR_ANY;\r
- uport = (unsigned short) 0;\r
- mysa.sin_port = htons(uport);\r
- if (bind(s, (struct sockaddr *) &mysa, sizeof(struct sockaddr_in))\r
- == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- /* Resolve remote host name */\r
- memset((char *) &sa, 0, sizeof(struct sockaddr_in));\r
- if (!(hp = gethostbyname(host))) {\r
- unsigned int b0, b1, b2, b3;\r
-\r
- err = WSAGetLastError();\r
-\r
- if (sscanf(host, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) == 4) {\r
- hp = (struct hostent *) calloc(1, sizeof(struct hostent));\r
- hp->h_addrtype = AF_INET;\r
- hp->h_length = 4;\r
- hp->h_addr_list = (char **) calloc(2, sizeof(char *));\r
- hp->h_addr_list[0] = (char *) malloc(4);\r
- hp->h_addr_list[0][0] = (char) b0;\r
- hp->h_addr_list[0][1] = (char) b1;\r
- hp->h_addr_list[0][2] = (char) b2;\r
- hp->h_addr_list[0][3] = (char) b3;\r
- } else {\r
- WSACleanup();\r
- return err;\r
- }\r
- }\r
- sa.sin_family = hp->h_addrtype;\r
- uport = (unsigned short) atoi(port);\r
- sa.sin_port = htons(uport);\r
- memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);\r
-\r
- /* Make connection */\r
- if (connect(s, (struct sockaddr *) &sa,\r
- sizeof(struct sockaddr_in)) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- /* Prepare return value */\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPSock;\r
- cp->sock = s;\r
- *pr = (ProcRef *) cp;\r
-\r
- return NO_ERROR;\r
-}\r
-\r
-int\r
-OpenCommPort(char *name, ProcRef *pr)\r
-{\r
- HANDLE h;\r
- COMMTIMEOUTS ct;\r
- ChildProc *cp;\r
- char fullname[MSG_SIZ];\r
-\r
- if (*name != '\\')\r
- sprintf(fullname, "\\\\.\\%s", name);\r
- else\r
- strcpy(fullname, name);\r
-\r
- h = CreateFile(name, GENERIC_READ | GENERIC_WRITE,\r
- 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);\r
- if (h == (HANDLE) -1) {\r
- return GetLastError();\r
- }\r
- hCommPort = h;\r
-\r
- if (!SetCommState(h, (LPDCB) &dcb)) return GetLastError();\r
-\r
- /* Accumulate characters until a 100ms pause, then parse */\r
- ct.ReadIntervalTimeout = 100;\r
- ct.ReadTotalTimeoutMultiplier = 0;\r
- ct.ReadTotalTimeoutConstant = 0;\r
- ct.WriteTotalTimeoutMultiplier = 0;\r
- ct.WriteTotalTimeoutConstant = 0;\r
- if (!SetCommTimeouts(h, (LPCOMMTIMEOUTS) &ct)) return GetLastError();\r
-\r
- /* Prepare return value */\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPComm;\r
- cp->hFrom = h;\r
- cp->hTo = h;\r
- *pr = (ProcRef *) cp;\r
-\r
- return NO_ERROR;\r
-}\r
-\r
-int\r
-OpenLoopback(ProcRef *pr)\r
-{\r
- DisplayFatalError("Not implemented", 0, 1);\r
- return NO_ERROR;\r
-}\r
-\r
-\r
-int\r
-OpenRcmd(char* host, char* user, char* cmd, ProcRef* pr)\r
-{\r
- ChildProc *cp;\r
- int err;\r
- SOCKET s, s2, s3;\r
- struct sockaddr_in sa, mysa;\r
- struct hostent FAR *hp;\r
- unsigned short uport;\r
- WORD wVersionRequested;\r
- WSADATA wsaData;\r
- int fromPort;\r
- char stderrPortStr[MSG_SIZ];\r
-\r
- /* Initialize socket DLL */\r
- wVersionRequested = MAKEWORD(1, 1);\r
- err = WSAStartup(wVersionRequested, &wsaData);\r
- if (err != 0) return err;\r
-\r
- /* Resolve remote host name */\r
- memset((char *) &sa, 0, sizeof(struct sockaddr_in));\r
- if (!(hp = gethostbyname(host))) {\r
- unsigned int b0, b1, b2, b3;\r
-\r
- err = WSAGetLastError();\r
-\r
- if (sscanf(host, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) == 4) {\r
- hp = (struct hostent *) calloc(1, sizeof(struct hostent));\r
- hp->h_addrtype = AF_INET;\r
- hp->h_length = 4;\r
- hp->h_addr_list = (char **) calloc(2, sizeof(char *));\r
- hp->h_addr_list[0] = (char *) malloc(4);\r
- hp->h_addr_list[0][0] = (char) b0;\r
- hp->h_addr_list[0][1] = (char) b1;\r
- hp->h_addr_list[0][2] = (char) b2;\r
- hp->h_addr_list[0][3] = (char) b3;\r
- } else {\r
- WSACleanup();\r
- return err;\r
- }\r
- }\r
- sa.sin_family = hp->h_addrtype;\r
- uport = (unsigned short) 514;\r
- sa.sin_port = htons(uport);\r
- memcpy((char *) &sa.sin_addr, hp->h_addr, hp->h_length);\r
-\r
- /* Bind local socket to unused "privileged" port address\r
- */\r
- s = INVALID_SOCKET;\r
- memset((char *) &mysa, 0, sizeof(struct sockaddr_in));\r
- mysa.sin_family = AF_INET;\r
- mysa.sin_addr.s_addr = INADDR_ANY;\r
- for (fromPort = 1023;; fromPort--) {\r
- if (fromPort < 0) {\r
- WSACleanup();\r
- return WSAEADDRINUSE;\r
- }\r
- if (s == INVALID_SOCKET) {\r
- if ((s = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {\r
- err = WSAGetLastError();\r
- WSACleanup();\r
- return err;\r
- }\r
- }\r
- uport = (unsigned short) fromPort;\r
- mysa.sin_port = htons(uport);\r
- if (bind(s, (struct sockaddr *) &mysa, sizeof(struct sockaddr_in))\r
- == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- if (err == WSAEADDRINUSE) continue;\r
- WSACleanup();\r
- return err;\r
- }\r
- if (connect(s, (struct sockaddr *) &sa,\r
- sizeof(struct sockaddr_in)) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- if (err == WSAEADDRINUSE) {\r
- closesocket(s);\r
- s = -1;\r
- continue;\r
- }\r
- WSACleanup();\r
- return err;\r
- }\r
- break;\r
- }\r
-\r
- /* Bind stderr local socket to unused "privileged" port address\r
- */\r
- s2 = INVALID_SOCKET;\r
- memset((char *) &mysa, 0, sizeof(struct sockaddr_in));\r
- mysa.sin_family = AF_INET;\r
- mysa.sin_addr.s_addr = INADDR_ANY;\r
- for (fromPort = 1023;; fromPort--) {\r
- if (fromPort == prevStderrPort) continue; // don't reuse port\r
- if (fromPort < 0) {\r
- (void) closesocket(s);\r
- WSACleanup();\r
- return WSAEADDRINUSE;\r
- }\r
- if (s2 == INVALID_SOCKET) {\r
- if ((s2 = socket(PF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {\r
- err = WSAGetLastError();\r
- closesocket(s);\r
- WSACleanup();\r
- return err;\r
- }\r
- }\r
- uport = (unsigned short) fromPort;\r
- mysa.sin_port = htons(uport);\r
- if (bind(s2, (struct sockaddr *) &mysa, sizeof(struct sockaddr_in))\r
- == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- if (err == WSAEADDRINUSE) continue;\r
- (void) closesocket(s);\r
- WSACleanup();\r
- return err;\r
- }\r
- if (listen(s2, 1) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- if (err == WSAEADDRINUSE) {\r
- closesocket(s2);\r
- s2 = INVALID_SOCKET;\r
- continue;\r
- }\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
- break;\r
- }\r
- prevStderrPort = fromPort; // remember port used\r
- sprintf(stderrPortStr, "%d", fromPort);\r
-\r
- if (send(s, stderrPortStr, strlen(stderrPortStr) + 1, 0) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- if (send(s, UserName(), strlen(UserName()) + 1, 0) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
- if (*user == NULLCHAR) user = UserName();\r
- if (send(s, user, strlen(user) + 1, 0) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
- if (send(s, cmd, strlen(cmd) + 1, 0) == SOCKET_ERROR) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
-\r
- if ((s3 = accept(s2, NULL, NULL)) == INVALID_SOCKET) {\r
- err = WSAGetLastError();\r
- (void) closesocket(s);\r
- (void) closesocket(s2);\r
- WSACleanup();\r
- return err;\r
- }\r
- (void) closesocket(s2); /* Stop listening */\r
-\r
- /* Prepare return value */\r
- cp = (ChildProc *) calloc(1, sizeof(ChildProc));\r
- cp->kind = CPRcmd;\r
- cp->sock = s;\r
- cp->sock2 = s3;\r
- *pr = (ProcRef *) cp;\r
-\r
- return NO_ERROR;\r
-}\r
-\r
-\r
-InputSourceRef\r
-AddInputSource(ProcRef pr, int lineByLine,\r
- InputCallback func, VOIDSTAR closure)\r
-{\r
- InputSource *is, *is2;\r
- ChildProc *cp = (ChildProc *) pr;\r
-\r
- is = (InputSource *) calloc(1, sizeof(InputSource));\r
- is->lineByLine = lineByLine;\r
- is->func = func;\r
- is->closure = closure;\r
- is->second = NULL;\r
- is->next = is->buf;\r
- if (pr == NoProc) {\r
- is->kind = CPReal;\r
- consoleInputSource = is;\r
- } else {\r
- is->kind = cp->kind;\r
- switch (cp->kind) {\r
- case CPReal:\r
- is->hFile = cp->hFrom;\r
- cp->hFrom = NULL; /* now owned by InputThread */\r
- is->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) NonOvlInputThread,\r
- (LPVOID) is, 0, &is->id);\r
- break;\r
-\r
- case CPComm:\r
- is->hFile = cp->hFrom;\r
- cp->hFrom = NULL; /* now owned by InputThread */\r
- is->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) InputThread,\r
- (LPVOID) is, 0, &is->id);\r
- break;\r
-\r
- case CPSock:\r
- is->sock = cp->sock;\r
- is->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SocketInputThread,\r
- (LPVOID) is, 0, &is->id);\r
- break;\r
-\r
- case CPRcmd:\r
- is2 = (InputSource *) calloc(1, sizeof(InputSource));\r
- *is2 = *is;\r
- is->sock = cp->sock;\r
- is->second = is2;\r
- is2->sock = cp->sock2;\r
- is2->second = is2;\r
- is->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SocketInputThread,\r
- (LPVOID) is, 0, &is->id);\r
- is2->hThread =\r
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) SocketInputThread,\r
- (LPVOID) is2, 0, &is2->id);\r
- break;\r
- }\r
- }\r
- return (InputSourceRef) is;\r
-}\r
-\r
-void\r
-RemoveInputSource(InputSourceRef isr)\r
-{\r
- InputSource *is;\r
-\r
- is = (InputSource *) isr;\r
- is->hThread = NULL; /* tell thread to stop */\r
- CloseHandle(is->hThread);\r
- if (is->second != NULL) {\r
- is->second->hThread = NULL;\r
- CloseHandle(is->second->hThread);\r
- }\r
-}\r
-\r
-\r
-int\r
-OutputToProcess(ProcRef pr, char *message, int count, int *outError)\r
-{\r
- DWORD dOutCount;\r
- int outCount = SOCKET_ERROR;\r
- ChildProc *cp = (ChildProc *) pr;\r
- static OVERLAPPED ovl;\r
-\r
- if (pr == NoProc) {\r
- ConsoleOutput(message, count, FALSE);\r
- return count;\r
- } \r
-\r
- if (ovl.hEvent == NULL) {\r
- ovl.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);\r
- }\r
- ovl.Internal = ovl.InternalHigh = ovl.Offset = ovl.OffsetHigh = 0;\r
-\r
- switch (cp->kind) {\r
- case CPSock:\r
- case CPRcmd:\r
- outCount = send(cp->sock, message, count, 0);\r
- if (outCount == SOCKET_ERROR) {\r
- *outError = WSAGetLastError();\r
- } else {\r
- *outError = NO_ERROR;\r
- }\r
- break;\r
-\r
- case CPReal:\r
- if (WriteFile(((ChildProc *)pr)->hTo, message, count,\r
- &dOutCount, NULL)) {\r
- *outError = NO_ERROR;\r
- outCount = (int) dOutCount;\r
- } else {\r
- *outError = GetLastError();\r
- }\r
- break;\r
-\r
- case CPComm:\r
- *outError = DoWriteFile(((ChildProc *)pr)->hTo, message, count,\r
- &dOutCount, &ovl);\r
- if (*outError == NO_ERROR) {\r
- outCount = (int) dOutCount;\r
- }\r
- break;\r
- }\r
- return outCount;\r
-}\r
-\r
-int\r
-OutputToProcessDelayed(ProcRef pr, char *message, int count, int *outError,\r
- long msdelay)\r
-{\r
- /* Ignore delay, not implemented for WinBoard */\r
- return OutputToProcess(pr, message, count, outError);\r
-}\r
-\r
-\r
-void\r
-CmailSigHandlerCallBack(InputSourceRef isr, VOIDSTAR closure,\r
- char *buf, int count, int error)\r
-{\r
- DisplayFatalError("Not implemented", 0, 1);\r
-}\r
-\r
-/* see wgamelist.c for Game List functions */\r
-/* see wedittags.c for Edit Tags functions */\r
-\r
-\r
-VOID\r
-ICSInitScript()\r
-{\r
- FILE *f;\r
- char buf[MSG_SIZ];\r
- char *dummy;\r
-\r
- if (SearchPath(installDir, appData.icsLogon, NULL, MSG_SIZ, buf, &dummy)) {\r
- f = fopen(buf, "r");\r
- if (f != NULL) {\r
- ProcessICSInitScript(f);\r
- fclose(f);\r
- }\r
- }\r
-}\r
-\r
-\r
-VOID\r
-StartAnalysisClock()\r
-{\r
- if (analysisTimerEvent) return;\r
- analysisTimerEvent = SetTimer(hwndMain, (UINT) ANALYSIS_TIMER_ID,\r
- (UINT) 2000, NULL);\r
-}\r
-\r
-LRESULT CALLBACK\r
-AnalysisDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)\r
-{\r
- static HANDLE hwndText;\r
- RECT rect;\r
- static int sizeX, sizeY;\r
- int newSizeX, newSizeY, flags;\r
- MINMAXINFO *mmi;\r
-\r
- switch (message) {\r
- case WM_INITDIALOG: /* message: initialize dialog box */\r
- /* Initialize the dialog items */\r
- hwndText = GetDlgItem(hDlg, OPT_AnalysisText);\r
- SetWindowText(hDlg, analysisTitle);\r
- SetDlgItemText(hDlg, OPT_AnalysisText, analysisText);\r
- /* Size and position the dialog */\r
- if (!analysisDialog) {\r
- analysisDialog = hDlg;\r
- flags = SWP_NOZORDER;\r
- GetClientRect(hDlg, &rect);\r
- sizeX = rect.right;\r
- sizeY = rect.bottom;\r
- if (analysisX != CW_USEDEFAULT && analysisY != CW_USEDEFAULT &&\r
- analysisW != CW_USEDEFAULT && analysisH != CW_USEDEFAULT) {\r
- WINDOWPLACEMENT wp;\r
- EnsureOnScreen(&analysisX, &analysisY);\r
- wp.length = sizeof(WINDOWPLACEMENT);\r
- wp.flags = 0;\r
- wp.showCmd = SW_SHOW;\r
- wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;\r
- wp.rcNormalPosition.left = analysisX;\r
- wp.rcNormalPosition.right = analysisX + analysisW;\r
- wp.rcNormalPosition.top = analysisY;\r
- wp.rcNormalPosition.bottom = analysisY + analysisH;\r
- SetWindowPlacement(hDlg, &wp);\r
-\r
- GetClientRect(hDlg, &rect);\r
- newSizeX = rect.right;\r
- newSizeY = rect.bottom;\r
- ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY,\r
- newSizeX, newSizeY);\r
- sizeX = newSizeX;\r
- sizeY = newSizeY;\r
- }\r
- }\r
- return FALSE;\r
-\r
- case WM_COMMAND: /* message: received a command */\r
- switch (LOWORD(wParam)) {\r
- case IDCANCEL:\r
- EditGameEvent();\r
- return TRUE;\r
- default:\r
- break;\r
- }\r
- break;\r
-\r
- case WM_SIZE:\r
- newSizeX = LOWORD(lParam);\r
- newSizeY = HIWORD(lParam);\r
- ResizeEditPlusButtons(hDlg, hwndText, sizeX, sizeY, newSizeX, newSizeY);\r
- sizeX = newSizeX;\r
- sizeY = newSizeY;\r
- break;\r
-\r
- case WM_GETMINMAXINFO:\r
- /* Prevent resizing window too small */\r
- mmi = (MINMAXINFO *) lParam;\r
- mmi->ptMinTrackSize.x = 100;\r
- mmi->ptMinTrackSize.y = 100;\r
- break;\r
- }\r
- return FALSE;\r
-}\r
-\r
-VOID\r
-AnalysisPopUp(char* title, char* str)\r
-{\r
- FARPROC lpProc;\r
- char *p, *q;\r
-\r
- if (str == NULL) str = "";\r
- p = (char *) malloc(2 * strlen(str) + 2);\r
- q = p;\r
- while (*str) {\r
- if (*str == '\n') *q++ = '\r';\r
- *q++ = *str++;\r
- }\r
- *q = NULLCHAR;\r
- if (analysisText != NULL) free(analysisText);\r
- analysisText = p;\r
-\r
- if (analysisDialog) {\r
- SetWindowText(analysisDialog, title);\r
- SetDlgItemText(analysisDialog, OPT_AnalysisText, analysisText);\r
- ShowWindow(analysisDialog, SW_SHOW);\r
- } else {\r
- analysisTitle = title;\r
- lpProc = MakeProcInstance((FARPROC)AnalysisDialog, hInst);\r
- CreateDialog(hInst, MAKEINTRESOURCE(DLG_Analysis),\r
- hwndMain, (DLGPROC)lpProc);\r
- FreeProcInstance(lpProc);\r
- }\r
- analysisDialogUp = TRUE; \r
-}\r
-\r
-VOID\r
-AnalysisPopDown()\r
-{\r
- if (analysisDialog) {\r
- ShowWindow(analysisDialog, SW_HIDE);\r
- }\r
- analysisDialogUp = FALSE; \r
-}\r
-\r
-\r
-VOID\r
-SetHighlights(int fromX, int fromY, int toX, int toY)\r
-{\r
- highlightInfo.sq[0].x = fromX;\r
- highlightInfo.sq[0].y = fromY;\r
- highlightInfo.sq[1].x = toX;\r
- highlightInfo.sq[1].y = toY;\r
-}\r
-\r
-VOID\r
-ClearHighlights()\r
-{\r
- highlightInfo.sq[0].x = highlightInfo.sq[0].y = \r
- highlightInfo.sq[1].x = highlightInfo.sq[1].y = -1;\r
-}\r
-\r
-VOID\r
-SetPremoveHighlights(int fromX, int fromY, int toX, int toY)\r
-{\r
- premoveHighlightInfo.sq[0].x = fromX;\r
- premoveHighlightInfo.sq[0].y = fromY;\r
- premoveHighlightInfo.sq[1].x = toX;\r
- premoveHighlightInfo.sq[1].y = toY;\r
-}\r
-\r
-VOID\r
-ClearPremoveHighlights()\r
-{\r
- premoveHighlightInfo.sq[0].x = premoveHighlightInfo.sq[0].y = \r
- premoveHighlightInfo.sq[1].x = premoveHighlightInfo.sq[1].y = -1;\r
-}\r
-\r
-VOID\r
-ShutDownFrontEnd()\r
-{\r
- if (saveSettingsOnExit) SaveSettings(settingsFileName);\r
- DeleteClipboardTempFiles();\r
-}\r
-\r
-void\r
-BoardToTop()\r
-{\r
- if (IsIconic(hwndMain))\r
- ShowWindow(hwndMain, SW_RESTORE);\r
-\r
- SetActiveWindow(hwndMain);\r
-}\r
-\r
-/*\r
- * Prototypes for animation support routines\r
- */\r
-static void ScreenSquare(int column, int row, POINT * pt);\r
-static void Tween( POINT * start, POINT * mid, POINT * finish, int factor,\r
- POINT frames[], int * nFrames);\r
-\r
-\r
-#define kFactor 4\r
-\r
-void\r
-AnimateMove(board, fromX, fromY, toX, toY)\r
- Board board;\r
- int fromX;\r
- int fromY;\r
- int toX;\r
- int toY;\r
-{\r
- ChessSquare piece;\r
- POINT start, finish, mid;\r
- POINT frames[kFactor * 2 + 1];\r
- int nFrames, n;\r
-\r
- if (!appData.animate) return;\r
- if (doingSizing) return;\r
- if (fromY < 0 || fromX < 0) return;\r
- piece = board[fromY][fromX];\r
- if (piece >= EmptySquare) return;\r
-\r
- ScreenSquare(fromX, fromY, &start);\r
- ScreenSquare(toX, toY, &finish);\r
-\r
- /* All pieces except knights move in straight line */\r
- if (piece != WhiteKnight && piece != BlackKnight) {\r
- mid.x = start.x + (finish.x - start.x) / 2;\r
- mid.y = start.y + (finish.y - start.y) / 2;\r
- } else {\r
- /* Knight: make diagonal movement then straight */\r
- if (abs(toY - fromY) < abs(toX - fromX)) {\r
- mid.x = start.x + (finish.x - start.x) / 2;\r
- mid.y = finish.y;\r
- } else {\r
- mid.x = finish.x;\r
- mid.y = start.y + (finish.y - start.y) / 2;\r
- }\r
- }\r
- \r
- /* Don't use as many frames for very short moves */\r
- if (abs(toY - fromY) + abs(toX - fromX) <= 2)\r
- Tween(&start, &mid, &finish, kFactor - 1, frames, &nFrames);\r
- else\r
- Tween(&start, &mid, &finish, kFactor, frames, &nFrames);\r
-\r
- animInfo.from.x = fromX;\r
- animInfo.from.y = fromY;\r
- animInfo.to.x = toX;\r
- animInfo.to.y = toY;\r
- animInfo.lastpos = start;\r
- animInfo.piece = piece;\r
- for (n = 0; n < nFrames; n++) {\r
- animInfo.pos = frames[n];\r
- DrawPosition(FALSE, NULL);\r
- animInfo.lastpos = animInfo.pos;\r
- Sleep(appData.animSpeed);\r
- }\r
- animInfo.pos = finish;\r
- DrawPosition(FALSE, NULL);\r
- animInfo.piece = EmptySquare;\r
-}\r
-\r
-/* Convert board position to corner of screen rect and color */\r
-\r
-static void\r
-ScreenSquare(column, row, pt)\r
- int column; int row; POINT * pt;\r
-{\r
- if (flipView) {\r
- pt->x = lineGap + ((BOARD_SIZE-1)-column) * (squareSize + lineGap);\r
- pt->y = lineGap + row * (squareSize + lineGap);\r
- } else {\r
- pt->x = lineGap + column * (squareSize + lineGap);\r
- pt->y = lineGap + ((BOARD_SIZE-1)-row) * (squareSize + lineGap);\r
- }\r
-}\r
-\r
-/* Generate a series of frame coords from start->mid->finish.\r
- The movement rate doubles until the half way point is\r
- reached, then halves back down to the final destination,\r
- which gives a nice slow in/out effect. The algorithmn\r
- may seem to generate too many intermediates for short\r
- moves, but remember that the purpose is to attract the\r
- viewers attention to the piece about to be moved and\r
- then to where it ends up. Too few frames would be less\r
- noticeable. */\r
-\r
-static void\r
-Tween(start, mid, finish, factor, frames, nFrames)\r
- POINT * start; POINT * mid;\r
- POINT * finish; int factor;\r
- POINT frames[]; int * nFrames;\r
-{\r
- int n, fraction = 1, count = 0;\r
-\r
- /* Slow in, stepping 1/16th, then 1/8th, ... */\r
- for (n = 0; n < factor; n++)\r
- fraction *= 2;\r
- for (n = 0; n < factor; n++) {\r
- frames[count].x = start->x + (mid->x - start->x) / fraction;\r
- frames[count].y = start->y + (mid->y - start->y) / fraction;\r
- count ++;\r
- fraction = fraction / 2;\r
- }\r
- \r
- /* Midpoint */\r
- frames[count] = *mid;\r
- count ++;\r
- \r
- /* Slow out, stepping 1/2, then 1/4, ... */\r
- fraction = 2;\r
- for (n = 0; n < factor; n++) {\r
- frames[count].x = finish->x - (finish->x - mid->x) / fraction;\r
- frames[count].y = finish->y - (finish->y - mid->y) / fraction;\r
- count ++;\r
- fraction = fraction * 2;\r
- }\r
- *nFrames = count;\r
-}\r
-\r
-void\r
-HistorySet(char movelist[][2*MOVE_LEN], int first, int last, int current)\r
-{\r
- /* Currently not implemented in WinBoard */\r
-}\r
-\r
-\r
+/*
+ * WinBoard.c -- Windows NT front end to XBoard
+ * $Id$
+ *
+ * Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts.
+ * Enhancements Copyright 1992-2001 Free Software Foundation, Inc.
+ *
+ * XBoard borrows its colors and the bitmaps.xchess bitmap set from XChess,
+ * which was written and is copyrighted by Wayne Christopher.
+ *
+ * The following terms apply to Digital Equipment Corporation's copyright
+ * interest in XBoard:
+ * ------------------------------------------------------------------------
+ * All Rights Reserved
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notice appear in all copies and that
+ * both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of Digital not be
+ * used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ *
+ * DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ * DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * ------------------------------------------------------------------------
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * ------------------------------------------------------------------------
+ */
+
+#include "config.h"
+
+#include <windows.h>
+#include <winuser.h>
+#include <winsock.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <math.h>
+#include <commdlg.h>
+#include <dlgs.h>
+#include <richedit.h>
+#include <mmsystem.h>
+
+#if __GNUC__
+#include <errno.h>
+#include <string.h>
+#endif
+
+#include "common.h"
+#include "winboard.h"
+#include "frontend.h"
+#include "backend.h"
+#include "moves.h"
+#include "wclipbrd.h"
+#include "wgamelist.h"
+#include "wedittags.h"
+#include "woptions.h"
+#include "wsockerr.h"
+#include "defaults.h"
+
+typedef struct {
+ ChessSquare piece;
+ POINT pos; /* window coordinates of current pos */
+ POINT lastpos; /* window coordinates of last pos - used for clipping */
+ POINT from; /* board coordinates of the piece's orig pos */
+ POINT to; /* board coordinates of the piece's new pos */
+} AnimInfo;
+
+static AnimInfo animInfo = { EmptySquare, {-1,-1}, {-1,-1}, {-1,-1} };
+
+typedef struct {
+ POINT start; /* window coordinates of start pos */
+ POINT pos; /* window coordinates of current pos */
+ POINT lastpos; /* window coordinates of last pos - used for clipping */
+ POINT from; /* board coordinates of the piece's orig pos */
+} DragInfo;
+
+static DragInfo dragInfo = { {-1,-1}, {-1,-1}, {-1,-1}, {-1,-1} };
+
+typedef struct {
+ POINT sq[2]; /* board coordinates of from, to squares */
+} HighlightInfo;
+
+static HighlightInfo highlightInfo = { {{-1, -1}, {-1, -1}} };
+static HighlightInfo premoveHighlightInfo = { {{-1, -1}, {-1, -1}} };
+
+/* Window class names */
+char szAppName[] = "WinBoard";
+char szConsoleName[] = "WBConsole";
+
+/* Title bar text */
+char szTitle[] = "WinBoard";
+char szConsoleTitle[] = "ICS Interaction";
+
+char *programName;
+char *settingsFileName;
+BOOLEAN saveSettingsOnExit;
+char installDir[MSG_SIZ];
+
+BoardSize boardSize;
+BOOLEAN chessProgram;
+static int boardX, boardY, consoleX, consoleY, consoleW, consoleH;
+static int squareSize, lineGap;
+static int winWidth, winHeight;
+static RECT messageRect, whiteRect, blackRect;
+static char messageText[MESSAGE_TEXT_MAX];
+static int clockTimerEvent = 0;
+static int loadGameTimerEvent = 0;
+static int analysisTimerEvent = 0;
+static DelayedEventCallback delayedTimerCallback;
+static int delayedTimerEvent = 0;
+static int buttonCount = 2;
+char *icsTextMenuString;
+char *icsNames;
+char *firstChessProgramNames;
+char *secondChessProgramNames;
+
+#define ARG_MAX 20000
+
+#define PALETTESIZE 256
+
+HINSTANCE hInst; /* current instance */
+HWND hwndMain = NULL; /* root window*/
+HWND hwndConsole = NULL;
+BOOLEAN alwaysOnTop = FALSE;
+RECT boardRect;
+COLORREF lightSquareColor, darkSquareColor, whitePieceColor,
+ blackPieceColor, highlightSquareColor, premoveHighlightColor;
+HPALETTE hPal;
+ColorClass currentColorClass;
+
+HWND hCommPort = NULL; /* currently open comm port */
+static HWND hwndPause; /* pause button */
+static HBITMAP pieceBitmap[3][(int) WhiteKing + 1];
+static HBRUSH lightSquareBrush, darkSquareBrush,
+ whitePieceBrush, blackPieceBrush, iconBkgndBrush, outlineBrush;
+static POINT gridEndpoints[(BOARD_SIZE + 1) * 4];
+static DWORD gridVertexCounts[(BOARD_SIZE + 1) * 2];
+static HPEN gridPen = NULL;
+static HPEN highlightPen = NULL;
+static HPEN premovePen = NULL;
+static NPLOGPALETTE pLogPal;
+static BOOL paletteChanged = FALSE;
+static HICON iconWhite, iconBlack, iconCurrent;
+static int doingSizing = FALSE;
+static int lastSizing = 0;
+static int prevStderrPort;
+
+#if __GNUC__ && !defined(_winmajor)
+#define oldDialog 0 /* cygwin doesn't define _winmajor; mingw does */
+#else
+#define oldDialog (_winmajor < 4)
+#endif
+
+char *defaultTextAttribs[] =
+{
+ COLOR_SHOUT, COLOR_SSHOUT, COLOR_CHANNEL1, COLOR_CHANNEL, COLOR_KIBITZ,
+ COLOR_TELL, COLOR_CHALLENGE, COLOR_REQUEST, COLOR_SEEK, COLOR_NORMAL,
+ COLOR_NONE
+};
+
+typedef struct {
+ char *name;
+ int squareSize;
+ int lineGap;
+ int smallLayout;
+ int tinyLayout;
+ int cliWidth, cliHeight;
+} SizeInfo;
+
+SizeInfo sizeInfo[] =
+{
+ { "tiny", 21, 0, 1, 1, 0, 0 },
+ { "teeny", 25, 1, 1, 1, 0, 0 },
+ { "dinky", 29, 1, 1, 1, 0, 0 },
+ { "petite", 33, 1, 1, 1, 0, 0 },
+ { "slim", 37, 2, 1, 0, 0, 0 },
+ { "small", 40, 2, 1, 0, 0, 0 },
+ { "mediocre", 45, 2, 1, 0, 0, 0 },
+ { "middling", 49, 2, 0, 0, 0, 0 },
+ { "average", 54, 2, 0, 0, 0, 0 },
+ { "moderate", 58, 3, 0, 0, 0, 0 },
+ { "medium", 64, 3, 0, 0, 0, 0 },
+ { "bulky", 72, 3, 0, 0, 0, 0 },
+ { "large", 80, 3, 0, 0, 0, 0 },
+ { "big", 87, 3, 0, 0, 0, 0 },
+ { "huge", 95, 3, 0, 0, 0, 0 },
+ { "giant", 108, 3, 0, 0, 0, 0 },
+ { "colossal", 116, 4, 0, 0, 0, 0 },
+ { "titanic", 129, 4, 0, 0, 0, 0 },
+ { NULL, 0, 0, 0, 0, 0, 0 }
+};
+
+#define MF(x) {x, {0, }, {0, }, 0}
+MyFont fontRec[NUM_SIZES][NUM_FONTS] =
+{
+ { MF(CLOCK_FONT_TINY), MF(MESSAGE_FONT_TINY),
+ MF(COORD_FONT_TINY), MF(CONSOLE_FONT_TINY),
+ MF(COMMENT_FONT_TINY), MF(EDITTAGS_FONT_TINY) },
+ { MF(CLOCK_FONT_TEENY), MF(MESSAGE_FONT_TEENY),
+ MF(COORD_FONT_TEENY), MF(CONSOLE_FONT_TEENY),
+ MF(COMMENT_FONT_TEENY), MF(EDITTAGS_FONT_TEENY) },
+ { MF(CLOCK_FONT_DINKY), MF(MESSAGE_FONT_DINKY),
+ MF(COORD_FONT_DINKY), MF(CONSOLE_FONT_DINKY),
+ MF(COMMENT_FONT_DINKY), MF(EDITTAGS_FONT_DINKY) },
+ { MF(CLOCK_FONT_PETITE), MF(MESSAGE_FONT_PETITE),
+ MF(COORD_FONT_PETITE), MF(CONSOLE_FONT_PETITE),
+ MF(COMMENT_FONT_PETITE), MF(EDITTAGS_FONT_PETITE) },
+ { MF(CLOCK_FONT_SLIM), MF(MESSAGE_FONT_SLIM),
+ MF(COORD_FONT_SLIM), MF(CONSOLE_FONT_SLIM),
+ MF(COMMENT_FONT_SLIM), MF(EDITTAGS_FONT_SLIM) },
+ { MF(CLOCK_FONT_SMALL), MF(MESSAGE_FONT_SMALL),
+ MF(COORD_FONT_SMALL), MF(CONSOLE_FONT_SMALL),
+ MF(COMMENT_FONT_SMALL), MF(EDITTAGS_FONT_SMALL) },
+ { MF(CLOCK_FONT_MEDIOCRE), MF(MESSAGE_FONT_MEDIOCRE),
+ MF(COORD_FONT_MEDIOCRE), MF(CONSOLE_FONT_MEDIOCRE),
+ MF(COMMENT_FONT_MEDIOCRE), MF(EDITTAGS_FONT_MEDIOCRE) },
+ { MF(CLOCK_FONT_MIDDLING), MF(MESSAGE_FONT_MIDDLING),
+ MF(COORD_FONT_MIDDLING), MF(CONSOLE_FONT_MIDDLING),
+ MF(COMMENT_FONT_MIDDLING), MF(EDITTAGS_FONT_MIDDLING) },
+ { MF(CLOCK_FONT_AVERAGE), MF(MESSAGE_FONT_AVERAGE),
+ MF(COORD_FONT_AVERAGE), MF(CONSOLE_FONT_AVERAGE),
+ MF(COMMENT_FONT_AVERAGE), MF(EDITTAGS_FONT_AVERAGE) },
+ { MF(CLOCK_FONT_MODERATE), MF(MESSAGE_FONT_MODERATE),
+ MF(COORD_FONT_MODERATE), MF(CONSOLE_FONT_MODERATE),
+ MF(COMMENT_FONT_MODERATE), MF(EDITTAGS_FONT_MODERATE) },
+ { MF(CLOCK_FONT_MEDIUM), MF(MESSAGE_FONT_MEDIUM),
+ MF(COORD_FONT_MEDIUM), MF(CONSOLE_FONT_MEDIUM),
+ MF(COMMENT_FONT_MEDIUM), MF(EDITTAGS_FONT_MEDIUM) },
+ { MF(CLOCK_FONT_BULKY), MF(MESSAGE_FONT_BULKY),
+ MF(COORD_FONT_BULKY), MF(CONSOLE_FONT_BULKY),
+ MF(COMMENT_FONT_BULKY), MF(EDITTAGS_FONT_BULKY) },
+ { MF(CLOCK_FONT_LARGE), MF(MESSAGE_FONT_LARGE),
+ MF(COORD_FONT_LARGE), MF(CONSOLE_FONT_LARGE),
+ MF(COMMENT_FONT_LARGE), MF(EDITTAGS_FONT_LARGE) },
+ { MF(CLOCK_FONT_BIG), MF(MESSAGE_FONT_BIG),
+ MF(COORD_FONT_BIG), MF(CONSOLE_FONT_BIG),
+ MF(COMMENT_FONT_BIG), MF(EDITTAGS_FONT_BIG) },
+ { MF(CLOCK_FONT_HUGE), MF(MESSAGE_FONT_HUGE),
+ MF(COORD_FONT_HUGE), MF(CONSOLE_FONT_HUGE),
+ MF(COMMENT_FONT_HUGE), MF(EDITTAGS_FONT_HUGE) },
+ { MF(CLOCK_FONT_GIANT), MF(MESSAGE_FONT_GIANT),
+ MF(COORD_FONT_GIANT), MF(CONSOLE_FONT_GIANT),
+ MF(COMMENT_FONT_GIANT), MF(EDITTAGS_FONT_GIANT) },
+ { MF(CLOCK_FONT_COLOSSAL), MF(MESSAGE_FONT_COLOSSAL),
+ MF(COORD_FONT_COLOSSAL), MF(CONSOLE_FONT_COLOSSAL),
+ MF(COMMENT_FONT_COLOSSAL), MF(EDITTAGS_FONT_COLOSSAL) },
+ { MF(CLOCK_FONT_TITANIC), MF(MESSAGE_FONT_TITANIC),
+ MF(COORD_FONT_TITANIC), MF(CONSOLE_FONT_TITANIC),
+ MF(COMMENT_FONT_TITANIC), MF(EDITTAGS_FONT_TITANIC) },
+};
+
+MyFont *font[NUM_SIZES][NUM_FONTS];
+
+typedef struct {
+ char *label;
+ int id;
+ HWND hwnd;
+ WNDPROC wndproc;
+} MyButtonDesc;
+
+#define BUTTON_WIDTH (tinyLayout ? 16 : 32)
+#define N_BUTTONS 5
+
+MyButtonDesc buttonDesc[N_BUTTONS] =
+{
+ {"<<", IDM_ToStart, NULL, NULL},
+ {"<", IDM_Backward, NULL, NULL},
+ {"P", IDM_Pause, NULL, NULL},
+ {">", IDM_Forward, NULL, NULL},
+ {">>", IDM_ToEnd, NULL, NULL},
+};
+
+int tinyLayout = 0, smallLayout = 0;
+#define MENU_BAR_ITEMS 6
+char *menuBarText[2][MENU_BAR_ITEMS+1] = {
+ { "&File", "&Mode", "&Action", "&Step", "&Options", "&Help", NULL },
+ { "&F", "&M", "&A", "&S", "&O", "&H", NULL },
+};
+
+
+MySound sounds[(int)NSoundClasses];
+MyTextAttribs textAttribs[(int)NColorClasses];
+
+MyColorizeAttribs colorizeAttribs[] = {
+ { (COLORREF)0, 0, "Shout Text" },
+ { (COLORREF)0, 0, "SShout/CShout" },
+ { (COLORREF)0, 0, "Channel 1 Text" },
+ { (COLORREF)0, 0, "Channel Text" },
+ { (COLORREF)0, 0, "Kibitz Text" },
+ { (COLORREF)0, 0, "Tell Text" },
+ { (COLORREF)0, 0, "Challenge Text" },
+ { (COLORREF)0, 0, "Request Text" },
+ { (COLORREF)0, 0, "Seek Text" },
+ { (COLORREF)0, 0, "Normal Text" },
+ { (COLORREF)0, 0, "None" }
+};
+
+
+
+static char *commentTitle;
+static char *commentText;
+static int commentIndex;
+static Boolean editComment = FALSE;
+HWND commentDialog = NULL;
+BOOLEAN commentDialogUp = FALSE;
+static int commentX, commentY, commentH, commentW;
+
+static char *analysisTitle;
+static char *analysisText;
+HWND analysisDialog = NULL;
+BOOLEAN analysisDialogUp = FALSE;
+static int analysisX, analysisY, analysisH, analysisW;
+
+char errorTitle[MSG_SIZ];
+char errorMessage[2*MSG_SIZ];
+HWND errorDialog = NULL;
+BOOLEAN moveErrorMessageUp = FALSE;
+BOOLEAN consoleEcho = TRUE;
+CHARFORMAT consoleCF;
+COLORREF consoleBackgroundColor;
+
+char *programVersion;
+
+#define CPReal 1
+#define CPComm 2
+#define CPSock 3
+#define CPRcmd 4
+typedef int CPKind;
+
+typedef struct {
+ CPKind kind;
+ HANDLE hProcess;
+ DWORD pid;
+ HANDLE hTo;
+ HANDLE hFrom;
+ SOCKET sock;
+ SOCKET sock2; /* stderr socket for OpenRcmd */
+} ChildProc;
+
+#define INPUT_SOURCE_BUF_SIZE 4096
+
+typedef struct _InputSource {
+ CPKind kind;
+ HANDLE hFile;
+ SOCKET sock;
+ int lineByLine;
+ HANDLE hThread;
+ DWORD id;
+ char buf[INPUT_SOURCE_BUF_SIZE];
+ char *next;
+ DWORD count;
+ int error;
+ InputCallback func;
+ struct _InputSource *second; /* for stderr thread on CPRcmd */
+ VOIDSTAR closure;
+} InputSource;
+
+InputSource *consoleInputSource;
+
+DCB dcb;
+
+/* forward */
+VOID ConsoleOutput(char* data, int length, int forceVisible);
+VOID ConsoleCreate();
+LRESULT CALLBACK
+ ConsoleWndProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+VOID ColorizeTextPopup(HWND hwnd, ColorClass cc);
+VOID PrintCommSettings(FILE *f, char *name, DCB *dcb);
+VOID ParseCommSettings(char *arg, DCB *dcb);
+LRESULT CALLBACK
+ StartupDialog(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
+VOID APIENTRY MenuPopup(HWND hwnd, POINT pt, HMENU hmenu, UINT def);
+void ParseIcsTextMenu(char *icsTextMenuString);
+VOID PopUpMoveDialog(char firstchar);
+VOID UpdateSampleText(HWND hDlg, int id, MyColorizeAttribs *mca);
+
+/*
+ * Setting "frozen" should disable all user input other than deleting
+ * the window. We do this while engines are initializing themselves.
+ */
+static int frozen = 0;
+static int oldMenuItemState[MENU_BAR_ITEMS];
+void FreezeUI()
+{
+ HMENU hmenu;
+ int i;
+
+ if (frozen) return;
+ frozen = 1;
+ hmenu = GetMenu(hwndMain);
+ for (i=0; i<MENU_BAR_ITEMS; i++) {
+ oldMenuItemState[i] = EnableMenuItem(hmenu, i, MF_BYPOSITION|MF_GRAYED);
+ }
+ DrawMenuBar(hwndMain);
+}
+
+/* Undo a FreezeUI */
+void ThawUI()
+{
+ HMENU hmenu;
+ int i;
+
+ if (!frozen) return;
+ frozen = 0;
+ hmenu = GetMenu(hwndMain);
+ for (i=0; i<MENU_BAR_ITEMS; i++) {
+ EnableMenuItem(hmenu, i, MF_BYPOSITION|oldMenuItemState[i]);
+ }
+ DrawMenuBar(hwndMain);
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * WinMain
+ *
+\*---------------------------------------------------------------------------*/
+
+int APIENTRY
+WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+ LPSTR lpCmdLine, int nCmdShow)
+{
+ MSG msg;
+ HANDLE hAccelMain, hAccelNoAlt;
+
+ debugFP = stderr;
+
+ LoadLibrary("RICHED32.DLL");
+ consoleCF.cbSize = sizeof(CHARFORMAT);
+
+ if (!InitApplication(hInstance)) {
+ return (FALSE);
+ }
+ if (!InitInstance(hInstance, nCmdShow, lpCmdLine)) {
+ return (FALSE);
+ }
+
+ hAccelMain = LoadAccelerators (hInstance, szAppName);
+ hAccelNoAlt = LoadAccelerators (hInstance, "NO_ALT");
+
+ /* Acquire and dispatch messages until a WM_QUIT message is received. */
+
+ while (GetMessage(&msg, /* message structure */
+ NULL, /* handle of window receiving the message */
+ 0, /* lowest message to examine */
+ 0)) /* highest message to examine */
+ {
+ if (!(commentDialog && IsDialogMessage(commentDialog, &msg)) &&
+ !(editTagsDialog && IsDialogMessage(editTagsDialog, &msg)) &&
+ !(gameListDialog && IsDialogMessage(gameListDialog, &msg)) &&
+ !(errorDialog && IsDialogMessage(errorDialog, &msg)) &&
+ !(!frozen && TranslateAccelerator(hwndMain, hAccelMain, &msg)) &&
+ !(!hwndConsole && TranslateAccelerator(hwndMain, hAccelNoAlt, &msg))) {
+ TranslateMessage(&msg); /* Translates virtual key codes */
+ DispatchMessage(&msg); /* Dispatches message to window */
+ }
+ }
+
+
+ return (msg.wParam); /* Returns the value from PostQuitMessage */
+}
+
+/*---------------------------------------------------------------------------*\
+ *
+ * Initialization functions
+ *
+\*---------------------------------------------------------------------------*/
+
+BOOL
+InitApplication(HINSTANCE hInstance)
+{
+ WNDCLASS wc;
+
+ /* Fill in window class structure with parameters that describe the */
+ /* main window. */
+
+ wc.style = CS_HREDRAW | CS_VREDRAW; /* Class style(s). */
+ wc.lpfnWndProc = (WNDPROC)WndProc; /* Window Procedure */
+ wc.cbClsExtra = 0; /* No per-class extra data. */
+ wc.cbWndExtra = 0; /* No per-window extra data. */
+ wc.hInstance = hInstance; /* Owner of this class */
+ wc.hIcon = LoadIcon(hInstance, "icon_white");
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW); /* Cursor */
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); /* Default color */
+ wc.lpszMenuName = szAppName; /* Menu name from .RC */
+ wc.lpszClassName = szAppName; /* Name to register as */
+
+ /* Register the window class and return success/failure code. */
+ if (!RegisterClass(&wc)) return FALSE;
+
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = (WNDPROC)ConsoleWndProc;
+ wc.cbClsExtra = 0;
+ wc.cbWndExtra = DLGWINDOWEXTRA;
+ wc.hInstance = hInstance;
+ wc.hIcon = LoadIcon(hInstance, "icon_white");
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = (HBRUSH)(COLOR_MENU+1);
+ wc.lpszMenuName = NULL;
+ wc.lpszClassName = szConsoleName;
+
+ if (!RegisterClass(&wc)) return FALSE;
+ return TRUE;
+}
+
+
+/* Set by InitInstance, used by EnsureOnScreen */
+int screenHeight, screenWidth;
+
+void
+EnsureOnScreen(int *x, int *y)
+{
+ /* Be sure window at (x,y) is not off screen (or even mostly off screen) */
+ if (*x > screenWidth - 32) *x = 0;
+ if (*y > screenHeight - 32) *y = 0;
+}
+
+BOOL
+InitInstance(HINSTANCE hInstance, int nCmdShow, LPSTR lpCmdLine)
+{
+ HWND hwnd; /* Main window handle. */
+ int ibs;
+ WINDOWPLACEMENT wp;
+ char *filepart;
+
+ hInst = hInstance; /* Store instance handle in our global variable */
+
+ if (SearchPath(NULL, "WinBoard.exe", NULL, MSG_SIZ, installDir, &filepart)) {
+ *filepart = NULLCHAR;
+ } else {
+ GetCurrentDirectory(MSG_SIZ, installDir);
+ }
+ InitAppData(lpCmdLine); /* Get run-time parameters */
+ if (appData.debugMode) {
+ debugFP = fopen("winboard.debug", "w");
+ setbuf(debugFP, NULL);
+ }
+
+ InitBackEnd1();
+
+ /* Create a main window for this application instance. */
+ hwnd = CreateWindow(szAppName, szTitle,
+ (WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX),
+ CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,
+ NULL, NULL, hInstance, NULL);
+ hwndMain = hwnd;
+
+ /* If window could not be created, return "failure" */
+ if (!hwnd) {
+ return (FALSE);
+ }
+
+ iconWhite = LoadIcon(hInstance, "icon_white");
+ iconBlack = LoadIcon(hInstance, "icon_black");
+ iconCurrent = iconWhite;
+ InitDrawingColors();
+ screenHeight = GetSystemMetrics(SM_CYSCREEN);
+ screenWidth = GetSystemMetrics(SM_CXSCREEN);
+ for (ibs = (int) NUM_SIZES - 1; ibs >= 0; ibs--) {
+ /* Compute window size for each board size, and use the largest
+ size that fits on this screen as the default. */
+ InitDrawingSizes((BoardSize)ibs, 0);
+ if (boardSize == (BoardSize)-1 &&
+ winHeight <= screenHeight && winWidth <= screenWidth) {
+ boardSize = (BoardSize)ibs;
+ }
+ }
+ InitDrawingSizes(boardSize, 0);
+ InitMenuChecks();
+ buttonCount = GetSystemMetrics(SM_CMOUSEBUTTONS);
+
+ InitBackEnd2();
+
+ /* Make the window visible; update its client area; and return "success" */
+ EnsureOnScreen(&boardX, &boardY);
+ wp.length = sizeof(WINDOWPLACEMENT);
+ wp.flags = 0;
+ wp.showCmd = nCmdShow;
+ wp.ptMaxPosition.x = wp.ptMaxPosition.y = 0;
+ wp.rcNormalPosition.left = boardX;
+ wp.rcNormalPosition.right = boardX + winWidth;
+ wp.rcNormalPosition.top = boardY;
+ wp.rcNormalPosition.bottom = boardY + winHeight;
+ SetWindowPlacement(hwndMain, &wp);
+
+ SetWindowPos(hwndMain, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
+ 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+ if (hwndConsole) {
+#if AOT_CONSOLE
+ SetWindowPos(hwndConsole, alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST,
+ 0, 0, 0, 0, SWP_NOMOVE|SWP_NOSIZE);
+#endif
+ ShowWindow(hwndConsole, nCmdShow);
+ }
+ UpdateWindow(hwnd);
+
+ return TRUE;
+
+}
+
+
+typedef enum {
+ ArgString, ArgInt, ArgFloat, ArgBoolean, ArgTrue, ArgFalse, ArgNone,
+ ArgColor, ArgAttribs, ArgFilename, ArgBoardSize, ArgFont, ArgCommSettings,
+ ArgSettingsFilename
+} ArgType;
+
+typedef struct {
+ char *argName;
+ ArgType argType;
+ /***
+ union {
+ String *pString; // ArgString
+ int *pInt; // ArgInt
+ float *pFloat; // ArgFloat
+ Boolean *pBoolean; // ArgBoolean
+ COLORREF *pColor; // ArgColor
+ ColorClass cc; // ArgAttribs
+ String *pFilename; // ArgFilename
+ BoardSize *pBoardSize; // ArgBoardSize
+ int whichFont; // ArgFont
+ DCB *pDCB; // ArgCommSettings
+ String *pFilename; // ArgSettingsFilename
+ } argLoc;
+ ***/
+ LPVOID argLoc;
+ BOOL save;
+} ArgDescriptor;
+
+int junk;
+ArgDescriptor argDescriptors[] = {
+ /* positional arguments */
+ { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
+ { "", ArgNone, NULL },
+ /* keyword arguments */
+ { "whitePieceColor", ArgColor, (LPVOID) &whitePieceColor, TRUE },
+ { "wpc", ArgColor, (LPVOID) &whitePieceColor, FALSE },
+ { "blackPieceColor", ArgColor, (LPVOID) &blackPieceColor, TRUE },
+ { "bpc", ArgColor, (LPVOID) &blackPieceColor, FALSE },
+ { "lightSquareColor", ArgColor, (LPVOID) &lightSquareColor, TRUE },
+ { "lsc", ArgColor, (LPVOID) &lightSquareColor, FALSE },
+ { "darkSquareColor", ArgColor, (LPVOID) &darkSquareColor, TRUE },
+ { "dsc", ArgColor, (LPVOID) &darkSquareColor, FALSE },
+ { "highlightSquareColor", ArgColor, (LPVOID) &highlightSquareColor, TRUE },
+ { "hsc", ArgColor, (LPVOID) &highlightSquareColor, FALSE },
+ { "premoveHighlightColor", ArgColor, (LPVOID) &premoveHighlightColor, TRUE },
+ { "phc", ArgColor, (LPVOID) &premoveHighlightColor, FALSE },
+ { "movesPerSession", ArgInt, (LPVOID) &appData.movesPerSession, TRUE },
+ { "mps", ArgInt, (LPVOID) &appData.movesPerSession, FALSE },
+ { "initString", ArgString, (LPVOID) &appData.initString, FALSE },
+ { "firstInitString", ArgString, (LPVOID) &appData.initString, FALSE },
+ { "secondInitString", ArgString, (LPVOID) &appData.secondInitString, FALSE },
+ { "firstComputerString", ArgString, (LPVOID) &appData.firstComputerString,
+ FALSE },
+ { "secondComputerString", ArgString, (LPVOID) &appData.secondComputerString,
+ FALSE },
+ { "firstChessProgram", ArgFilename, (LPVOID) &appData.firstChessProgram,
+ FALSE },
+ { "fcp", ArgFilename, (LPVOID) &appData.firstChessProgram, FALSE },
+ { "secondChessProgram", ArgFilename, (LPVOID) &appData.secondChessProgram,
+ FALSE },
+ { "scp", ArgFilename, (LPVOID) &appData.secondChessProgram, FALSE },
+ { "firstPlaysBlack", ArgBoolean, (LPVOID) &appData.firstPlaysBlack, FALSE },
+ { "fb", ArgTrue, (LPVOID) &appData.firstPlaysBlack, FALSE },
+ { "xfb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
+ { "-fb", ArgFalse, (LPVOID) &appData.firstPlaysBlack, FALSE },
+ { "noChessProgram", ArgBoolean, (LPVOID) &appData.noChessProgram, FALSE },
+ { "ncp", ArgTrue, (LPVOID) &appData.noChessProgram, FALSE },
+ { "xncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
+ { "-ncp", ArgFalse, (LPVOID) &appData.noChessProgram, FALSE },
+ { "firstHost", ArgString, (LPVOID) &appData.firstHost, FALSE },
+ { "fh", ArgString, (LPVOID) &appData.firstHost, FALSE },
+ { "secondHost", ArgString, (LPVOID) &appData.secondHost, FALSE },
+ { "sh", ArgString, (LPVOID) &appData.secondHost, FALSE },
+ { "firstDirectory", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
+ { "fd", ArgFilename, (LPVOID) &appData.firstDirectory, FALSE },
+ { "secondDirectory", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
+ { "sd", ArgFilename, (LPVOID) &appData.secondDirectory, FALSE },
+ /*!!bitmapDirectory?*/
+ { "remoteShell", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
+ { "rsh", ArgFilename, (LPVOID) &appData.remoteShell, FALSE },
+ { "remoteUser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
+ { "ruser", ArgString, (LPVOID) &appData.remoteUser, FALSE },
+ { "timeDelay", ArgFloat, (LPVOID) &appData.timeDelay, TRUE },
+ { "td", ArgFloat, (LPVOID) &appData.timeDelay, FALSE },
+ { "timeControl", ArgString, (LPVOID) &appData.timeControl, TRUE },
+ { "tc", ArgString, (LPVOID) &appData.timeControl, FALSE },
+ { "timeIncrement", ArgInt, (LPVOID) &appData.timeIncrement, TRUE },
+ { "inc", ArgInt, (LPVOID) &appData.timeIncrement, FALSE },
+ { "internetChessServerMode", ArgBoolean, (LPVOID) &appData.icsActive, FALSE },
+ { "ics", ArgTrue, (LPVOID) &appData.icsActive, FALSE },
+ { "xics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
+ { "-ics", ArgFalse, (LPVOID) &appData.icsActive, FALSE },
+ { "internetChessServerHost", ArgString, (LPVOID) &appData.icsHost, FALSE },
+ { "icshost", ArgString, (LPVOID) &appData.icsHost, FALSE },
+ { "internetChessServerPort", ArgString, (LPVOID) &appData.icsPort, FALSE },
+ { "icsport", ArgString, (LPVOID) &appData.icsPort, FALSE },
+ { "internetChessServerCommPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
+ { "icscomm", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
+ { "internetChessServerComPort", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
+ { "icscom", ArgString, (LPVOID) &appData.icsCommPort, FALSE },
+ { "internetChessServerLogonScript", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
+ { "icslogon", ArgFilename, (LPVOID) &appData.icsLogon, FALSE },
+ { "useTelnet", ArgBoolean, (LPVOID) &appData.useTelnet, FALSE },
+ { "telnet", ArgTrue, (LPVOID) &appData.useTelnet, FALSE },
+ { "xtelnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
+ { "-telnet", ArgFalse, (LPVOID) &appData.useTelnet, FALSE },
+ { "telnetProgram", ArgFilename, (LPVOID) &appData.telnetProgram, FALSE },
+ { "icshelper", ArgFilename, (LPVOID) &appData.icsHelper, FALSE },
+ { "gateway", ArgString, (LPVOID) &appData.gateway, FALSE },
+ { "loadGameFile", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
+ { "lgf", ArgFilename, (LPVOID) &appData.loadGameFile, FALSE },
+ { "loadGameIndex", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
+ { "lgi", ArgInt, (LPVOID) &appData.loadGameIndex, FALSE },
+ { "saveGameFile", ArgFilename, (LPVOID) &appData.saveGameFile, TRUE },
+ { "sgf", ArgFilename, (LPVOID) &appData.saveGameFile, FALSE },
+ { "autoSaveGames", ArgBoolean, (LPVOID) &appData.autoSaveGames, TRUE },
+ { "autosave", ArgTrue, (LPVOID) &appData.autoSaveGames, FALSE },
+ { "xautosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
+ { "-autosave", ArgFalse, (LPVOID) &appData.autoSaveGames, FALSE },
+ { "loadPositionFile", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
+ { "lpf", ArgFilename, (LPVOID) &appData.loadPositionFile, FALSE },
+ { "loadPositionIndex", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
+ { "lpi", ArgInt, (LPVOID) &appData.loadPositionIndex, FALSE },
+ { "savePositionFile", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
+ { "spf", ArgFilename, (LPVOID) &appData.savePositionFile, FALSE },
+ { "matchMode", ArgBoolean, (LPVOID) &appData.matchMode, FALSE },
+ { "mm", ArgTrue, (LPVOID) &appData.matchMode, FALSE },
+ { "xmm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
+ { "-mm", ArgFalse, (LPVOID) &appData.matchMode, FALSE },
+ { "matchGames", ArgInt, (LPVOID) &appData.matchGames, FALSE },
+ { "mg", ArgInt, (LPVOID) &appData.matchGames, FALSE },
+ { "monoMode", ArgBoolean, (LPVOID) &appData.monoMode, TRUE },
+ { "mono", ArgTrue, (LPVOID) &appData.monoMode, FALSE },
+ { "xmono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
+ { "-mono", ArgFalse, (LPVOID) &appData.monoMode, FALSE },
+ { "debugMode", ArgBoolean, (LPVOID) &appData.debugMode, FALSE },
+ { "debug", ArgTrue, (LPVOID) &appData.debugMode, FALSE },
+ { "xdebug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
+ { "-debug", ArgFalse, (LPVOID) &appData.debugMode, FALSE },
+ { "clockMode", ArgBoolean, (LPVOID) &appData.clockMode, FALSE },
+ { "clock", ArgTrue, (LPVOID) &appData.clockMode, FALSE },
+ { "xclock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
+ { "-clock", ArgFalse, (LPVOID) &appData.clockMode, FALSE },
+ { "searchTime", ArgString, (LPVOID) &appData.searchTime, FALSE },
+ { "st", ArgString, (LPVOID) &appData.searchTime, FALSE },
+ { "searchDepth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
+ { "depth", ArgInt, (LPVOID) &appData.searchDepth, FALSE },
+ { "showCoords", ArgBoolean, (LPVOID) &appData.showCoords, TRUE },
+ { "coords", ArgTrue, (LPVOID) &appData.showCoords, FALSE },
+ { "xcoords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
+ { "-coords", ArgFalse, (LPVOID) &appData.showCoords, FALSE },
+ { "showThinking", ArgBoolean, (LPVOID) &appData.showThinking, TRUE },
+ { "thinking", ArgTrue, (LPVOID) &appData.showThinking, FALSE },
+ { "xthinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
+ { "-thinking", ArgFalse, (LPVOID) &appData.showThinking, FALSE },
+ { "ponderNextMove", ArgBoolean, (LPVOID) &appData.ponderNextMove, TRUE },
+ { "ponder", ArgTrue, (LPVOID) &appData.ponderNextMove, FALSE },
+ { "xponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
+ { "-ponder", ArgFalse, (LPVOID) &appData.ponderNextMove, FALSE },
+ { "periodicUpdates", ArgBoolean, (LPVOID) &appData.periodicUpdates, TRUE },
+ { "periodic", ArgTrue, (LPVOID) &appData.periodicUpdates, FALSE },
+ { "xperiodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
+ { "-periodic", ArgFalse, (LPVOID) &appData.periodicUpdates, FALSE },
+ { "popupExitMessage", ArgBoolean, (LPVOID) &appData.popupExitMessage, TRUE },
+ { "exit", ArgTrue, (LPVOID) &appData.popupExitMessage, FALSE },
+ { "xexit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
+ { "-exit", ArgFalse, (LPVOID) &appData.popupExitMessage, FALSE },
+ { "popupMoveErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors, TRUE },
+ { "popup", ArgTrue, (LPVOID) &appData.popupMoveErrors, FALSE },
+ { "xpopup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
+ { "-popup", ArgFalse, (LPVOID) &appData.popupMoveErrors, FALSE },
+ { "popUpErrors", ArgBoolean, (LPVOID) &appData.popupMoveErrors,
+ FALSE }, /* only so that old WinBoard.ini files from betas can be read */
+ { "clockFont", ArgFont, (LPVOID) CLOCK_FONT, TRUE },
+ { "messageFont", ArgFont, (LPVOID) MESSAGE_FONT, TRUE },
+ { "coordFont", ArgFont, (LPVOID) COORD_FONT, TRUE },
+ { "tagsFont", ArgFont, (LPVOID) EDITTAGS_FONT, TRUE },
+ { "commentFont", ArgFont, (LPVOID) COMMENT_FONT, TRUE },
+ { "icsFont", ArgFont, (LPVOID) CONSOLE_FONT, TRUE },
+ { "boardSize", ArgBoardSize, (LPVOID) &boardSize,
+ TRUE }, /* must come after all fonts */
+ { "size", ArgBoardSize, (LPVOID) &boardSize, FALSE },
+ { "ringBellAfterMoves", ArgBoolean, (LPVOID) &appData.ringBellAfterMoves,
+ FALSE }, /* historical; kept only so old winboard.ini files will parse */
+ { "alwaysOnTop", ArgBoolean, (LPVOID) &alwaysOnTop, TRUE },
+ { "top", ArgTrue, (LPVOID) &alwaysOnTop, FALSE },
+ { "xtop", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
+ { "-top", ArgFalse, (LPVOID) &alwaysOnTop, FALSE },
+ { "autoCallFlag", ArgBoolean, (LPVOID) &appData.autoCallFlag, TRUE },
+ { "autoflag", ArgTrue, (LPVOID) &appData.autoCallFlag, FALSE },
+ { "xautoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
+ { "-autoflag", ArgFalse, (LPVOID) &appData.autoCallFlag, FALSE },
+ { "autoComment", ArgBoolean, (LPVOID) &appData.autoComment, TRUE },
+ { "autocomm", ArgTrue, (LPVOID) &appData.autoComment, FALSE },
+ { "xautocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
+ { "-autocomm", ArgFalse, (LPVOID) &appData.autoComment, FALSE },
+ { "autoObserve", ArgBoolean, (LPVOID) &appData.autoObserve, TRUE },
+ { "autobs", ArgTrue, (LPVOID) &appData.autoObserve, FALSE },
+ { "xautobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
+ { "-autobs", ArgFalse, (LPVOID) &appData.autoObserve, FALSE },
+ { "flipView", ArgBoolean, (LPVOID) &appData.flipView, FALSE },
+ { "flip", ArgTrue, (LPVOID) &appData.flipView, FALSE },
+ { "xflip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
+ { "-flip", ArgFalse, (LPVOID) &appData.flipView, FALSE },
+ { "autoFlipView", ArgBoolean, (LPVOID) &appData.autoFlipView, TRUE },
+ { "autoflip", ArgTrue, (LPVOID) &appData.autoFlipView, FALSE },
+ { "xautoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
+ { "-autoflip", ArgFalse, (LPVOID) &appData.autoFlipView, FALSE },
+ { "autoRaiseBoard", ArgBoolean, (LPVOID) &appData.autoRaiseBoard, TRUE },
+ { "autoraise", ArgTrue, (LPVOID) &appData.autoRaiseBoard, FALSE },
+ { "xautoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
+ { "-autoraise", ArgFalse, (LPVOID) &appData.autoRaiseBoard, FALSE },
+#if 0
+ { "cmailGameName", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
+ { "cmail", ArgString, (LPVOID) &appData.cmailGameName, FALSE },
+#endif
+ { "alwaysPromoteToQueen", ArgBoolean, (LPVOID) &appData.alwaysPromoteToQueen, TRUE },
+ { "queen", ArgTrue, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
+ { "xqueen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
+ { "-queen", ArgFalse, (LPVOID) &appData.alwaysPromoteToQueen, FALSE },
+ { "oldSaveStyle", ArgBoolean, (LPVOID) &appData.oldSaveStyle, TRUE },
+ { "oldsave", ArgTrue, (LPVOID) &appData.oldSaveStyle, FALSE },
+ { "xoldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
+ { "-oldsave", ArgFalse, (LPVOID) &appData.oldSaveStyle, FALSE },
+ { "quietPlay", ArgBoolean, (LPVOID) &appData.quietPlay, TRUE },
+ { "quiet", ArgTrue, (LPVOID) &appData.quietPlay, FALSE },
+ { "xquiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
+ { "-quiet", ArgFalse, (LPVOID) &appData.quietPlay, FALSE },
+ { "getMoveList", ArgBoolean, (LPVOID) &appData.getMoveList, TRUE },
+ { "moves", ArgTrue, (LPVOID) &appData.getMoveList, FALSE },
+ { "xmoves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
+ { "-moves", ArgFalse, (LPVOID) &appData.getMoveList, FALSE },
+ { "testLegality", ArgBoolean, (LPVOID) &appData.testLegality, TRUE },
+ { "legal", ArgTrue, (LPVOID) &appData.testLegality, FALSE },
+ { "xlegal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
+ { "-legal", ArgFalse, (LPVOID) &appData.testLegality, FALSE },
+ { "premove", ArgBoolean, (LPVOID) &appData.premove, TRUE },
+ { "pre", ArgTrue, (LPVOID) &appData.premove, FALSE },
+ { "xpre", ArgFalse, (LPVOID) &appData.premove, FALSE },
+ { "-pre", ArgFalse, (LPVOID) &appData.premove, FALSE },
+ { "premoveWhite", ArgBoolean, (LPVOID) &appData.premoveWhite, TRUE },
+ { "prewhite", ArgTrue, (LPVOID) &appData.premoveWhite, FALSE },
+ { "xprewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
+ { "-prewhite", ArgFalse, (LPVOID) &appData.premoveWhite, FALSE },
+ { "premoveWhiteText", ArgString, (LPVOID) &appData.premoveWhiteText, TRUE },
+ { "premoveBlack", ArgBoolean, (LPVOID) &appData.premoveBlack, TRUE },
+ { "preblack", ArgTrue, (LPVOID) &appData.premoveBlack, FALSE },
+ { "xpreblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
+ { "-preblack", ArgFalse, (LPVOID) &appData.premoveBlack, FALSE },
+ { "premoveBlackText", ArgString, (LPVOID) &appData.premoveBlackText, TRUE },
+ { "icsAlarm", ArgBoolean, (LPVOID) &appData.icsAlarm, TRUE},
+ { "alarm", ArgTrue, (LPVOID) &appData.icsAlarm, FALSE},
+ { "xalarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
+ { "-alarm", ArgFalse, (LPVOID) &appData.icsAlarm, FALSE},
+ { "icsAlarmTime", ArgInt, (LPVOID) &appData.icsAlarmTime, TRUE},
+ { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
+ { "localLineEditing", ArgBoolean, (LPVOID) &appData.localLineEditing, FALSE},
+ { "edit", ArgTrue, (LPVOID) &appData.localLineEditing, FALSE },
+ { "xedit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
+ { "-edit", ArgFalse, (LPVOID) &appData.localLineEditing, FALSE },
+ { "animateMoving", ArgBoolean, (LPVOID) &appData.animate, TRUE },
+ { "animate", ArgTrue, (LPVOID) &appData.animate, FALSE },
+ { "xanimate", ArgFalse, (LPVOID) &appData.animate, FALSE },
+ { "-animate", ArgFalse, (LPVOID) &appData.animate, FALSE },
+ { "animateSpeed", ArgInt, (LPVOID) &appData.animSpeed, TRUE },
+ { "animateDragging", ArgBoolean, (LPVOID) &appData.animateDragging, TRUE },
+ { "drag", ArgTrue, (LPVOID) &appData.animateDragging, FALSE },
+ { "xdrag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
+ { "-drag", ArgFalse, (LPVOID) &appData.animateDragging, FALSE },
+ { "blindfold", ArgBoolean, (LPVOID) &appData.blindfold, TRUE },
+ { "blind", ArgTrue, (LPVOID) &appData.blindfold, FALSE },
+ { "xblind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
+ { "-blind", ArgFalse, (LPVOID) &appData.blindfold, FALSE },
+ { "highlightLastMove", ArgBoolean,
+ (LPVOID) &appData.highlightLastMove, TRUE },
+ { "highlight", ArgTrue, (LPVOID) &appData.highlightLastMove, FALSE },
+ { "xhighlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
+ { "-highlight", ArgFalse, (LPVOID) &appData.highlightLastMove, FALSE },
+ { "highlightDragging", ArgBoolean,
+ (LPVOID) &appData.highlightDragging, TRUE },
+ { "highdrag", ArgTrue, (LPVOID) &appData.highlightDragging, FALSE },
+ { "xhighdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
+ { "-highdrag", ArgFalse, (LPVOID) &appData.highlightDragging, FALSE },
+ { "colorizeMessages", ArgBoolean, (LPVOID) &appData.colorize, TRUE },
+ { "colorize", ArgTrue, (LPVOID) &appData.colorize, FALSE },
+ { "xcolorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
+ { "-colorize", ArgFalse, (LPVOID) &appData.colorize, FALSE },
+ { "colorShout", ArgAttribs, (LPVOID) ColorShout, TRUE },
+ { "colorSShout", ArgAttribs, (LPVOID) ColorSShout, TRUE },
+ { "colorChannel1", ArgAttribs, (LPVOID) ColorChannel1, TRUE },
+ { "colorChannel", ArgAttribs, (LPVOID) ColorChannel, TRUE },
+ { "colorKibitz", ArgAttribs, (LPVOID) ColorKibitz, TRUE },
+ { "colorTell", ArgAttribs, (LPVOID) ColorTell, TRUE },
+ { "colorChallenge", ArgAttribs, (LPVOID) ColorChallenge, TRUE },
+ { "colorRequest", ArgAttribs, (LPVOID) ColorRequest, TRUE },
+ { "colorSeek", ArgAttribs, (LPVOID) ColorSeek, TRUE },
+ { "colorNormal", ArgAttribs, (LPVOID) ColorNormal, TRUE },
+ { "colorBackground", ArgColor, (LPVOID) &consoleBackgroundColor, TRUE },
+ { "soundShout", ArgFilename,
+ (LPVOID) &textAttribs[ColorShout].sound.name, TRUE },
+ { "soundSShout", ArgFilename,
+ (LPVOID) &textAttribs[ColorSShout].sound.name, TRUE },
+ { "soundChannel1", ArgFilename,
+ (LPVOID) &textAttribs[ColorChannel1].sound.name, TRUE },
+ { "soundChannel", ArgFilename,
+ (LPVOID) &textAttribs[ColorChannel].sound.name, TRUE },
+ { "soundKibitz", ArgFilename,
+ (LPVOID) &textAttribs[ColorKibitz].sound.name, TRUE },
+ { "soundTell", ArgFilename,
+ (LPVOID) &textAttribs[ColorTell].sound.name, TRUE },
+ { "soundChallenge", ArgFilename,
+ (LPVOID) &textAttribs[ColorChallenge].sound.name, TRUE },
+ { "soundRequest", ArgFilename,
+ (LPVOID) &textAttribs[ColorRequest].sound.name, TRUE },
+ { "soundSeek", ArgFilename,
+ (LPVOID) &textAttribs[ColorSeek].sound.name, TRUE },
+ { "soundMove", ArgFilename, (LPVOID) &sounds[(int)SoundMove].name, TRUE },
+ { "soundBell", ArgFilename, (LPVOID) &sounds[(int)SoundBell].name, TRUE },
+ { "soundIcsWin", ArgFilename, (LPVOID) &sounds[(int)SoundIcsWin].name,TRUE },
+ { "soundIcsLoss", ArgFilename,
+ (LPVOID) &sounds[(int)SoundIcsLoss].name, TRUE },
+ { "soundIcsDraw", ArgFilename,
+ (LPVOID) &sounds[(int)SoundIcsDraw].name, TRUE },
+ { "soundIcsUnfinished", ArgFilename,
+ (LPVOID) &sounds[(int)SoundIcsUnfinished].name, TRUE},
+ { "soundIcsAlarm", ArgFilename,
+ (LPVOID) &sounds[(int)SoundAlarm].name, TRUE },
+ { "reuseFirst", ArgBoolean, (LPVOID) &appData.reuseFirst, FALSE },
+ { "reuse", ArgTrue, (LPVOID) &appData.reuseFirst, FALSE },
+ { "xreuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
+ { "-reuse", ArgFalse, (LPVOID) &appData.reuseFirst, FALSE },
+ { "reuseChessPrograms", ArgBoolean,
+ (LPVOID) &appData.reuseFirst, FALSE }, /* backward compat only */
+ { "reuseSecond", ArgBoolean, (LPVOID) &appData.reuseSecond, FALSE },
+ { "reuse2", ArgTrue, (LPVOID) &appData.reuseSecond, FALSE },
+ { "xreuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
+ { "-reuse2", ArgFalse, (LPVOID) &appData.reuseSecond, FALSE },
+ { "comPortSettings", ArgCommSettings, (LPVOID) &dcb, TRUE },
+ { "x", ArgInt, (LPVOID) &boardX, TRUE },
+ { "y", ArgInt, (LPVOID) &boardY, TRUE },
+ { "icsX", ArgInt, (LPVOID) &consoleX, TRUE },
+ { "icsY", ArgInt, (LPVOID) &consoleY, TRUE },
+ { "icsW", ArgInt, (LPVOID) &consoleW, TRUE },
+ { "icsH", ArgInt, (LPVOID) &consoleH, TRUE },
+ { "analysisX", ArgInt, (LPVOID) &analysisX, TRUE },
+ { "analysisY", ArgInt, (LPVOID) &analysisY, TRUE },
+ { "analysisW", ArgInt, (LPVOID) &analysisW, TRUE },
+ { "analysisH", ArgInt, (LPVOID) &analysisH, TRUE },
+ { "commentX", ArgInt, (LPVOID) &commentX, TRUE },
+ { "commentY", ArgInt, (LPVOID) &commentY, TRUE },
+ { "commentW", ArgInt, (LPVOID) &commentW, TRUE },
+ { "commentH", ArgInt, (LPVOID) &commentH, TRUE },
+ { "tagsX", ArgInt, (LPVOID) &editTagsX, TRUE },
+ { "tagsY", ArgInt, (LPVOID) &editTagsY, TRUE },
+ { "tagsW", ArgInt, (LPVOID) &editTagsW, TRUE },
+ { "tagsH", ArgInt, (LPVOID) &editTagsH, TRUE },
+ { "gameListX", ArgInt, (LPVOID) &gameListX, TRUE },
+ { "gameListY", ArgInt, (LPVOID) &gameListY, TRUE },
+ { "gameListW", ArgInt, (LPVOID) &gameListW, TRUE },
+ { "gameListH", ArgInt, (LPVOID) &gameListH, TRUE },
+ { "settingsFile", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
+ { "ini", ArgSettingsFilename, (LPVOID) &settingsFileName, FALSE },
+ { "saveSettingsOnExit", ArgBoolean, (LPVOID) &saveSettingsOnExit, TRUE },
+ { "chessProgram", ArgBoolean, (LPVOID) &chessProgram, FALSE },
+ { "cp", ArgTrue, (LPVOID) &chessProgram, FALSE },
+ { "xcp", ArgFalse, (LPVOID) &chessProgram, FALSE },
+ { "-cp", ArgFalse, (LPVOID) &chessProgram, FALSE },
+ { "icsMenu", ArgString, (LPVOID) &icsTextMenuString, TRUE },
+ { "icsNames", ArgString, (LPVOID) &icsNames, TRUE },
+ { "firstChessProgramNames", ArgString, (LPVOID) &firstChessProgramNames,
+ TRUE },
+ { "secondChessProgramNames", ArgString, (LPVOID) &secondChessProgramNames,
+ TRUE },
+ { "initialMode", ArgString, (LPVOID) &appData.initialMode, FALSE },
+ { "mode", ArgString, (LPVOID) &appData.initialMode, FALSE },
+ { "variant", ArgString, (LPVOID) &appData.variant, FALSE },
+ { "firstProtocolVersion", ArgInt, (LPVOID) &appData.firstProtocolVersion,
+ FALSE },
+ { "secondProtocolVersion", ArgInt, (LPVOID) &appData.secondProtocolVersion,
+ FALSE },
+ { "showButtonBar", ArgBoolean, (LPVOID) &appData.showButtonBar, TRUE },
+ { "buttons", ArgTrue, (LPVOID) &appData.showButtonBar, FALSE },
+ { "xbuttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
+ { "-buttons", ArgFalse, (LPVOID) &appData.showButtonBar, FALSE },
+#ifdef ZIPPY
+ { "zippyTalk", ArgBoolean, (LPVOID) &appData.zippyTalk, FALSE },
+ { "zt", ArgTrue, (LPVOID) &appData.zippyTalk, FALSE },
+ { "xzt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
+ { "-zt", ArgFalse, (LPVOID) &appData.zippyTalk, FALSE },
+ { "zippyPlay", ArgBoolean, (LPVOID) &appData.zippyPlay, FALSE },
+ { "zp", ArgTrue, (LPVOID) &appData.zippyPlay, FALSE },
+ { "xzp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
+ { "-zp", ArgFalse, (LPVOID) &appData.zippyPlay, FALSE },
+ { "zippyLines", ArgFilename, (LPVOID) &appData.zippyLines, FALSE },
+ { "zippyPinhead", ArgString, (LPVOID) &appData.zippyPinhead, FALSE },
+ { "zippyPassword", ArgString, (LPVOID) &appData.zippyPassword, FALSE },
+ { &quo